Skip to content

Commit 6e40cab

Browse files
Merge pull request #68 from aarongarciah/scroll-to-top
Scroll to top code block on question change
2 parents 1b6a5df + 184d978 commit 6e40cab

File tree

6 files changed

+171
-14
lines changed

6 files changed

+171
-14
lines changed

Diff for: __tests__/components/CodePreTag.test.jsx

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import React from 'react';
2+
import renderer from 'react-test-renderer';
3+
import { mount } from 'enzyme';
4+
import 'jest-styled-components';
5+
6+
import CodePreTag from '../../src/components/CodePreTag';
7+
8+
const shortCodeToRender = `
9+
function foo() {
10+
return 'bar';
11+
}
12+
`;
13+
14+
const longCodeToRender = `
15+
function EquipmentPattern(name) {
16+
this.equipments = [];
17+
this.name = name;
18+
}
19+
20+
EquipmentPattern.prototype.add = function(equipment) {
21+
this.equipments.push(equipment);
22+
};
23+
24+
EquipmentPattern.prototype.getPrice = function() {
25+
return this.equipments
26+
.map(function(equipment) {
27+
return equipment.getPrice();
28+
})
29+
.reduce(function(a, b) {
30+
return a + b;
31+
});
32+
};
33+
34+
function Equipment() {}
35+
36+
Equipment.prototype.getPrice = function() {
37+
return this.price;
38+
};
39+
40+
// -- leafs
41+
function FloppyDisk() {
42+
this.name = 'Floppy Disk';
43+
this.price = 70;
44+
}
45+
FloppyDisk.prototype = Object.create(Equipment.prototype);
46+
47+
function HardDrive() {
48+
this.name = 'Hard Drive';
49+
this.price = 250;
50+
}
51+
HardDrive.prototype = Object.create(Equipment.prototype);
52+
53+
function Memory() {
54+
this.name = '8gb memomry';
55+
this.price = 280;
56+
}
57+
Memory.prototype = Object.create(Equipment.prototype);
58+
59+
module.exports = [EquipmentPattern, FloppyDisk, HardDrive, Memory];
60+
`;
61+
62+
describe('<CodePreTag /> component', () => {
63+
it('renders children properly', () => {
64+
const tree = renderer
65+
.create(
66+
<CodePreTag>
67+
<code>{shortCodeToRender}</code>
68+
</CodePreTag>
69+
)
70+
.toJSON();
71+
72+
expect(tree).toMatchSnapshot();
73+
});
74+
75+
it('scrolls to position 0,0 on children change', () => {
76+
const container = mount(
77+
<CodePreTag style={{ height: 200 }}>
78+
<code>{longCodeToRender}</code>
79+
</CodePreTag>
80+
);
81+
const $container = container.getDOMNode();
82+
83+
// Initially the scroll position must be at the top
84+
expect($container.scrollTop).toBe(0);
85+
86+
// Test that the scroll position is updated correctly
87+
$container.scrollTop = 100;
88+
expect($container.scrollTop).toBe(100);
89+
90+
// Test that the scroll position is reset after changing its children
91+
container.setProps({ children: shortCodeToRender });
92+
expect($container.scrollTop).toBe(0);
93+
});
94+
});

Diff for: __tests__/components/ProgressBar.test.js

-2
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,6 @@ describe('<ProgressBar /> component', () => {
5353

5454
it('has styled-component rendered classes', () => {
5555
const tree = renderer.create(result).toJSON();
56-
// console.log(tree);
57-
5856
expect(tree.children[0].props.className).toBeDefined();
5957
});
6058

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`<CodePreTag /> component renders children properly 1`] = `
4+
<pre>
5+
<code>
6+
7+
function foo() {
8+
return 'bar';
9+
}
10+
11+
</code>
12+
</pre>
13+
`;

Diff for: __tests__/pages/__snapshots__/Game.test.js.snap

+40-10
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ exports[`Game page - GAME - DARK style renders a <Code /> component 1`] = `
164164
}
165165
>
166166
<SyntaxHighlighter
167+
PreTag={[Function]}
167168
className="fixed"
168169
language="javascript"
169170
style={
@@ -313,7 +314,7 @@ exports[`Game page - GAME - DARK style renders a <Code /> component 1`] = `
313314
}
314315
}
315316
>
316-
<pre
317+
<CodePreTag
317318
className="fixed"
318319
style={
319320
Object {
@@ -326,10 +327,24 @@ exports[`Game page - GAME - DARK style renders a <Code /> component 1`] = `
326327
}
327328
}
328329
>
329-
<code>
330-
Code ES5 - Prototype
331-
</code>
332-
</pre>
330+
<pre
331+
className="fixed"
332+
style={
333+
Object {
334+
"background": "#282828",
335+
"border": "1px solid #555",
336+
"color": "#ebdbb2",
337+
"display": "block",
338+
"overflowX": "auto",
339+
"padding": "1em",
340+
}
341+
}
342+
>
343+
<code>
344+
Code ES5 - Prototype
345+
</code>
346+
</pre>
347+
</CodePreTag>
333348
</SyntaxHighlighter>
334349
</Code>
335350
`;
@@ -592,6 +607,7 @@ exports[`Game page - GAME - LIGHT style renders a <Code /> component 1`] = `
592607
}
593608
>
594609
<SyntaxHighlighter
610+
PreTag={[Function]}
595611
className="fixed"
596612
language="javascript"
597613
style={
@@ -712,7 +728,7 @@ exports[`Game page - GAME - LIGHT style renders a <Code /> component 1`] = `
712728
}
713729
}
714730
>
715-
<pre
731+
<CodePreTag
716732
className="fixed"
717733
style={
718734
Object {
@@ -725,10 +741,24 @@ exports[`Game page - GAME - LIGHT style renders a <Code /> component 1`] = `
725741
}
726742
}
727743
>
728-
<code>
729-
Code ES5 - Prototype
730-
</code>
731-
</pre>
744+
<pre
745+
className="fixed"
746+
style={
747+
Object {
748+
"background": "#fafafa",
749+
"border": "1px solid #d8d8d8",
750+
"color": "#383a42",
751+
"display": "block",
752+
"overflowX": "auto",
753+
"padding": "1em",
754+
}
755+
}
756+
>
757+
<code>
758+
Code ES5 - Prototype
759+
</code>
760+
</pre>
761+
</CodePreTag>
732762
</SyntaxHighlighter>
733763
</Code>
734764
`;

Diff for: src/components/Code.jsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { connect } from 'react-redux';
44
import { Light as SyntaxHighlighter } from 'react-syntax-highlighter';
55
import js from 'react-syntax-highlighter/dist/languages/hljs/javascript';
66
import { getJS, getCurrent } from '../selectors';
7+
import CodePreTag from './CodePreTag';
78

89
SyntaxHighlighter.registerLanguage('javascript', js);
910

@@ -13,13 +14,13 @@ const Code = props => {
1314
return (
1415
<Fragment>
1516
{js === 'es5' && (
16-
<SyntaxHighlighter language="javascript" style={style} className="fixed">
17+
<SyntaxHighlighter language="javascript" style={style} className="fixed" PreTag={CodePreTag}>
1718
{current.codeES5}
1819
</SyntaxHighlighter>
1920
)}
2021

2122
{js === 'es6' && (
22-
<SyntaxHighlighter language="javascript" style={style} className="fixed">
23+
<SyntaxHighlighter language="javascript" style={style} className="fixed" PreTag={CodePreTag}>
2324
{current.codeES6}
2425
</SyntaxHighlighter>
2526
)}

Diff for: src/components/CodePreTag.jsx

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import React, { useRef, useEffect } from 'react';
2+
import PropTypes from 'prop-types';
3+
4+
const CodePreTag = ({ children, ...restProps }) => {
5+
const syntaxHighlighterEl = useRef(null);
6+
7+
useEffect(() => {
8+
if (syntaxHighlighterEl.current) {
9+
syntaxHighlighterEl.current.scrollTop = 0;
10+
syntaxHighlighterEl.current.scrollLeft = 0;
11+
}
12+
}, [children]);
13+
14+
return <pre {...restProps} ref={syntaxHighlighterEl}>{children}</pre>;
15+
};
16+
17+
CodePreTag.propTypes = {
18+
children: PropTypes.node
19+
};
20+
21+
export default CodePreTag;

0 commit comments

Comments
 (0)