Skip to content

Commit f56b4ed

Browse files
fcollonvaltelamonian
authored andcommitted
Add unit test for plain text diff
1 parent 6c63e98 commit f56b4ed

File tree

7 files changed

+169
-56
lines changed

7 files changed

+169
-56
lines changed

src/components/diff/NbDiff.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export interface ICellDiffProps {
2525
* During component render, a Ref is created for the ReactDOM and after the component
2626
* is mounted, the PhosporJS widget is created and attached to the Ref.
2727
*/
28-
export class CellDiff extends React.Component<ICellDiffProps, {}> {
28+
export class CellDiff extends React.Component<ICellDiffProps> {
2929
private unAddedOrRemovedRef: RefObject<HTMLDivElement> = React.createRef<
3030
HTMLDivElement
3131
>();
@@ -39,7 +39,6 @@ export class CellDiff extends React.Component<ICellDiffProps, {}> {
3939

4040
constructor(props: ICellDiffProps) {
4141
super(props);
42-
this.state = {};
4342
}
4443

4544
componentDidMount(): void {
@@ -118,7 +117,10 @@ export class NBDiff extends React.Component<IDiffProps, INBDiffState> {
118117
nbdModel: undefined,
119118
errorMessage: undefined
120119
};
121-
this.performDiff(props.diffContext);
120+
}
121+
122+
componentDidMount() {
123+
this.performDiff(this.props.diffContext);
122124
}
123125

124126
render() {
@@ -166,7 +168,7 @@ export class NBDiff extends React.Component<IDiffProps, INBDiffState> {
166168
private performDiff(diffContext: IDiffContext): void {
167169
try {
168170
// Resolve what API parameter to call.
169-
let currentRefValue;
171+
let currentRefValue: any;
170172
if ('specialRef' in diffContext.currentRef) {
171173
currentRefValue = {
172174
special: diffContext.currentRef.specialRef

src/components/diff/PlainTextDiff.tsx

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ export class PlainTextDiff extends React.Component<
3232
constructor(props: IPlainTextDiffProps) {
3333
super(props);
3434
this.state = { errorMessage: null };
35-
this.performDiff(props.diffContext);
35+
}
36+
37+
componentDidMount() {
38+
this.performDiff(this.props.diffContext);
3639
}
3740

3841
render() {
@@ -68,7 +71,7 @@ export class PlainTextDiff extends React.Component<
6871
* to
6972
* @param diffContext the context in which to perform the diff
7073
*/
71-
private async performDiff(diffContext: IDiffContext): Promise<void> {
74+
private performDiff(diffContext: IDiffContext): void {
7275
try {
7376
// Resolve what API parameter to call.
7477
let currentRefValue: ICurrentReference;
@@ -82,33 +85,34 @@ export class PlainTextDiff extends React.Component<
8285
};
8386
}
8487

85-
try {
86-
const response = await httpGitRequest('/git/diffcontent', 'POST', {
87-
filename: this.props.path,
88-
prev_ref: { git: diffContext.previousRef.gitRef },
89-
curr_ref: currentRefValue,
90-
top_repo_path: this.props.topRepoPath
91-
});
92-
93-
const data = await response.json();
94-
95-
if (response.status !== 200) {
96-
// Handle error
97-
this.setState({
98-
errorMessage:
99-
data.message || 'Unknown error. Please check the server log.'
88+
httpGitRequest('/git/diffcontent', 'POST', {
89+
filename: this.props.path,
90+
prev_ref: { git: diffContext.previousRef.gitRef },
91+
curr_ref: currentRefValue,
92+
top_repo_path: this.props.topRepoPath
93+
}).then(response => {
94+
response
95+
.json()
96+
.then(data => {
97+
if (response.status !== 200) {
98+
// Handle error
99+
this.setState({
100+
errorMessage:
101+
data.message || 'Unknown error. Please check the server log.'
102+
});
103+
} else {
104+
this._addDiffViewer(data['prev_content'], data['curr_content']);
105+
}
106+
})
107+
.catch(reason => {
108+
console.error(reason);
109+
// Handle error
110+
this.setState({
111+
errorMessage:
112+
reason.message || 'Unknown error. Please check the server log.'
113+
});
100114
});
101-
} else {
102-
this._addDiffViewer(data['prev_content'], data['curr_content']);
103-
}
104-
} catch (reason) {
105-
console.error(reason);
106-
// Handle error
107-
this.setState({
108-
errorMessage:
109-
reason.message || 'Unknown error. Please check the server log.'
110-
});
111-
}
115+
});
112116
} catch (err) {
113117
console.error(err);
114118
throw ServerConnection.NetworkError;
@@ -126,7 +130,7 @@ export class PlainTextDiff extends React.Component<
126130

127131
mergeView(
128132
document.getElementById(
129-
`diffviewer-${this.props.path}-${getRefValue(
133+
`diffviewer-${this.props.path.replace('/', '-')}-${getRefValue(
130134
this.props.diffContext.currentRef
131135
)}`
132136
),

tests/test-components/Diff.spec.tsx

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,36 @@ import {
77
isDiffSupported
88
} from '../../src/components/diff/Diff';
99
import { NBDiff } from '../../src/components/diff/NbDiff';
10+
import { PlainTextDiff } from '../../src/components/diff/PlainTextDiff';
1011

1112
describe('Diff', () => {
12-
it('should render diff provider component when supported', function() {
13-
// Given
14-
const props: IDiffProps = {
15-
path: '/path/to/File.ipynb',
16-
topRepoPath: 'top/repo/path',
17-
diffContext: {
18-
currentRef: { specialRef: 'WORKING' },
19-
previousRef: { gitRef: '83baee' }
20-
}
21-
};
13+
([
14+
['/path/to/File.ipynb', NBDiff],
15+
['/path/to/File.py', PlainTextDiff],
16+
['/path/to/File.md', PlainTextDiff],
17+
['/path/to/File.txt', PlainTextDiff],
18+
['/path/to/File.json', PlainTextDiff]
19+
] as Array<[string, typeof React.Component]>).forEach(
20+
([filename, provider]) => {
21+
it(`should render ${provider} component for ${filename}`, () => {
22+
// Given
23+
const props: IDiffProps = {
24+
path: filename,
25+
topRepoPath: 'top/repo/path',
26+
diffContext: {
27+
currentRef: { specialRef: 'WORKING' },
28+
previousRef: { gitRef: '83baee' }
29+
}
30+
};
2231

23-
// When
24-
const node = shallow(<Diff {...props} />);
32+
// When
33+
const node = shallow(<Diff {...props} />);
2534

26-
// Then
27-
expect(node.find(NBDiff)).toHaveLength(1);
28-
});
35+
// Then
36+
expect(node.find(provider)).toHaveLength(1);
37+
});
38+
}
39+
);
2940

3041
it('should not render anything when not supported', function() {
3142
// Given

tests/test-components/NBDiff.spec.tsx

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import * as React from 'react';
44
import { IDiffProps } from '../../src/components/diff/Diff';
55
import { CellDiff, NBDiff } from '../../src/components/diff/NbDiff';
66
import { NBDiffHeader } from '../../src/components/diff/NBDiffHeader';
7-
import { createTestResponse } from './testutils';
87
import { httpGitRequest } from '../../src/git';
9-
import * as diffResponse from '../test-components/data/diffResponse.json';
8+
import * as diffResponse from '../test-components/data/nbDiffResponse.json';
9+
import { createTestResponse } from './testutils';
1010

1111
jest.mock('../../src/git');
1212

@@ -31,11 +31,10 @@ describe('NBDiff', () => {
3131
);
3232

3333
// When
34-
const node = shallow(<NBDiff {...props} />);
34+
const node = shallow<NBDiff>(<NBDiff {...props} />);
3535

3636
// Then
3737
await jsonResult;
38-
3938
node.update();
4039

4140
expect(httpGitRequest).toHaveBeenCalled();
@@ -60,16 +59,14 @@ describe('NBDiff', () => {
6059
}
6160
};
6261

63-
const jsonResult: Promise<any> = Promise.resolve({
64-
...diffResponse
65-
});
62+
const jsonResult: Promise<any> = Promise.resolve(diffResponse);
6663

6764
(httpGitRequest as jest.Mock).mockReturnValue(
6865
createTestResponse(200, jsonResult)
6966
);
7067

7168
// When
72-
const node = shallow(<NBDiff {...props} />);
69+
const node = shallow<NBDiff>(<NBDiff {...props} />);
7370

7471
// Then
7572
await jsonResult;
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import { shallow } from 'enzyme';
2+
import 'jest';
3+
import * as React from 'react';
4+
import { IDiffProps } from '../../src/components/diff/Diff';
5+
import { mergeView } from '../../src/components/diff/mergeview';
6+
import { PlainTextDiff } from '../../src/components/diff/PlainTextDiff';
7+
import { httpGitRequest } from '../../src/git';
8+
import * as diffResponse from '../test-components/data/textDiffResponse.json';
9+
import { createTestResponse } from './testutils';
10+
11+
jest.mock('../../src/git');
12+
jest.mock('../../src/components/diff/mergeview');
13+
14+
describe('PlainTextDiff', () => {
15+
it('should render error in if API response is failed', async () => {
16+
// Given
17+
const props: IDiffProps = {
18+
path: '/path/to/File.py',
19+
topRepoPath: '/top/repo/path',
20+
diffContext: {
21+
currentRef: { specialRef: 'WORKING' },
22+
previousRef: { gitRef: '83baee' }
23+
}
24+
};
25+
26+
const jsonResult = Promise.resolve({
27+
message: 'TEST_ERROR_MESSAGE'
28+
});
29+
30+
(httpGitRequest as jest.Mock).mockReturnValueOnce(
31+
createTestResponse(401, jsonResult)
32+
);
33+
34+
// When
35+
const node = shallow<PlainTextDiff>(<PlainTextDiff {...props} />);
36+
37+
// Then
38+
await jsonResult;
39+
40+
node.update();
41+
42+
expect(httpGitRequest).toHaveBeenCalled();
43+
expect(httpGitRequest).toBeCalledWith('/git/diffcontent', 'POST', {
44+
curr_ref: {
45+
special: 'WORKING'
46+
},
47+
filename: '/path/to/File.py',
48+
prev_ref: {
49+
git: '83baee'
50+
},
51+
top_repo_path: '/top/repo/path'
52+
});
53+
expect(node.find('.jp-git-diff-error').text()).toContain(
54+
'TEST_ERROR_MESSAGE'
55+
);
56+
});
57+
58+
it('should render header and cell diff components in success case', async () => {
59+
// Given
60+
const props: IDiffProps = {
61+
path: '/path/to/File.py',
62+
topRepoPath: '/top/repo/path',
63+
diffContext: {
64+
currentRef: { specialRef: 'WORKING' },
65+
previousRef: { gitRef: '83baee' }
66+
}
67+
};
68+
69+
const jsonResult = Promise.resolve(diffResponse);
70+
71+
(httpGitRequest as jest.Mock).mockReturnValueOnce(
72+
createTestResponse(200, jsonResult)
73+
);
74+
75+
const mockMergeView = mergeView as jest.Mocked<typeof mergeView>;
76+
77+
// When
78+
const node = shallow<PlainTextDiff>(<PlainTextDiff {...props} />);
79+
80+
// Then
81+
await jsonResult;
82+
node.update();
83+
84+
expect(httpGitRequest).toHaveBeenCalled();
85+
expect(httpGitRequest).toBeCalledWith('/git/diffcontent', 'POST', {
86+
curr_ref: {
87+
special: 'WORKING'
88+
},
89+
filename: '/path/to/File.py',
90+
prev_ref: {
91+
git: '83baee'
92+
},
93+
top_repo_path: '/top/repo/path'
94+
});
95+
expect(node.find('.jp-git-diff-error')).toHaveLength(0);
96+
expect(mockMergeView).toBeCalled();
97+
});
98+
});
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"prev_content": "# Program by Mitchell Aikens\n# No Copyright\n# 2012\n\n# Procedure 1\ndef main():\n try:\n # Get a number to maniuplate\n num = float(input(\"Please enter a number to manipulate.\\n\"))\n # Store the result of the value, after it has been manipulated\n # by Procedure 2\n addednum = addfive(num)\n # Store the result of the value, after it has been manipulated\n # by Procedure 3\n multipliednum = multiply(addednum)\n # Send the value to Procedure 4\n display(multipliednum)\n # Deal with exceptions from non-numeric user entry\n except ValueError:\n print(\"You must enter a valid number.\\n\")\n # Reset the value of num, to clear non-numeric data.\n num = 0\n # Call main, again.\n main()\n\n# Procedure 2\ndef addfive(num):\n return num + 5\n\n# Procedure 3\ndef multiply(addednum):\n return addednum * 2.452\n\n# Procedure 4\ndef display(multi):\n # Display the final value\n print(\"The final value is \",multi)\n\n# Call Procedure 1\nmain()\n", "curr_content": "# Program by Mitchell Aikens\n# No Copyright\n# 2012\n\n# Procedure 1\ndef main():\n try:\n # Get a number to maniuplate\n num = float(input(\"Please enter a number to manipulate.\\n\"))\n # Store the result of the value, after it has been manipulated\n # by Procedure 2\n addednum = addfive(num)\n multipliednum = multiply(addednum)\n # Send the value to Procedure 4\n display(multipliednum)\n # Deal with exceptions from non-numeric user entry\n except ValueError:\n print(\"You must enter a valid integer.\\n\")\n # Reset the value of num, to clear non-numeric data.\n num = 0\n # Call main, again.\n main()\n\n# Procedure 2\ndef addfive(num):\n return num + 5\n\n# Procedure 3\ndef multiply(addednum):\n return addednum * 2.452\n\n# Procedure 4\ndef display(multi):\n # Display the final value\n print(\"The final value is \",multi)\n\n# Procedure 5\ndef soustract_two(num):\n return num - 2\n\n# Call Procedure 1\nmain()\n"}

0 commit comments

Comments
 (0)