Skip to content
This repository was archived by the owner on Dec 15, 2022. It is now read-only.

Commit d8f360e

Browse files
authored
Merge pull request #1903 from atom/aw/coverage/misc
Correct remaining flapping test coverage
2 parents 1066ab8 + a8a5d61 commit d8f360e

File tree

10 files changed

+598
-25
lines changed

10 files changed

+598
-25
lines changed

lib/atom/decoration.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,12 @@ class BareDecoration extends React.Component {
6464
componentDidUpdate(prevProps) {
6565
if (this.props.editorHolder !== prevProps.editorHolder) {
6666
this.editorSub.dispose();
67-
this.editorSub = this.state.editorHolder.observe(this.observeParents);
67+
this.editorSub = this.props.editorHolder.observe(this.observeParents);
6868
}
6969

7070
if (this.props.decorableHolder !== prevProps.decorableHolder) {
7171
this.decorableSub.dispose();
72-
this.decorableSub = this.state.decorableHolder.observe(this.observeParents);
72+
this.decorableSub = this.props.decorableHolder.observe(this.observeParents);
7373
}
7474

7575
if (
@@ -95,10 +95,10 @@ class BareDecoration extends React.Component {
9595
this.decorationHolder.map(decoration => decoration.destroy());
9696

9797
const editorValid = this.props.editorHolder.map(editor => !editor.isDestroyed()).getOr(false);
98-
const markableValid = this.props.decorableHolder.map(decorable => !decorable.isDestroyed()).getOr(false);
98+
const decorableValid = this.props.decorableHolder.map(decorable => !decorable.isDestroyed()).getOr(false);
9999

100100
// Ensure the Marker or MarkerLayer corresponds to the context's TextEditor
101-
const markableMatches = this.props.decorableHolder.map(decorable => this.props.editorHolder.map(editor => {
101+
const decorableMatches = this.props.decorableHolder.map(decorable => this.props.editorHolder.map(editor => {
102102
const layer = decorable.layer || decorable;
103103
const displayLayer = editor.getMarkerLayer(layer.id);
104104
if (!displayLayer) {
@@ -110,7 +110,7 @@ class BareDecoration extends React.Component {
110110
return true;
111111
}).getOr(false)).getOr(false);
112112

113-
if (!editorValid || !markableValid || !markableMatches) {
113+
if (!editorValid || !decorableValid || !decorableMatches) {
114114
return;
115115
}
116116

lib/controllers/editor-conflict-controller.js

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,7 @@ export default class EditorConflictController extends React.Component {
1818
commandRegistry: PropTypes.object.isRequired,
1919
resolutionProgress: PropTypes.object.isRequired,
2020
isRebase: PropTypes.bool.isRequired,
21-
refreshResolutionProgress: PropTypes.func,
22-
}
23-
24-
static defaultProps = {
25-
refreshResolutionProgress: () => {},
21+
refreshResolutionProgress: PropTypes.func.isRequired,
2622
}
2723

2824
constructor(props, context) {
@@ -49,7 +45,6 @@ export default class EditorConflictController extends React.Component {
4945
const buffer = this.props.editor.getBuffer();
5046

5147
this.subscriptions.add(
52-
this.props.editor.onDidStopChanging(() => this.forceUpdate()),
5348
this.props.editor.onDidDestroy(() => this.props.refreshResolutionProgress(this.props.editor.getPath())),
5449
buffer.onDidReload(() => this.reparseConflicts()),
5550
);
@@ -171,7 +166,7 @@ export default class EditorConflictController extends React.Component {
171166
}
172167

173168
dismissConflicts(conflicts) {
174-
this.setState((prevState, props) => {
169+
this.setState(prevState => {
175170
const {added} = compareSets(new Set(conflicts), prevState.conflicts);
176171
return {conflicts: added};
177172
});

lib/models/conflicts/banner.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export default class Banner {
2626
revert() {
2727
const range = this.getMarker().getBufferRange();
2828
this.editor.setTextInBufferRange(range, this.originalText);
29+
this.getMarker().setBufferRange(range);
2930
}
3031

3132
delete() {

lib/models/conflicts/side.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ export default class Side {
9898
revert() {
9999
const range = this.getMarker().getBufferRange();
100100
this.editor.setTextInBufferRange(range, this.originalText);
101+
this.getMarker().setBufferRange(range);
101102
}
102103

103104
deleteBanner() {

lib/models/repository-states/present.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -610,9 +610,6 @@ export default class Present extends State {
610610
const bundle = await this.git().getStatusBundle();
611611
const results = await this.formatChangedFiles(bundle);
612612
results.branch = bundle.branch;
613-
if (!results.branch.aheadBehind) {
614-
results.branch.aheadBehind = {ahead: null, behind: null};
615-
}
616613
return results;
617614
} catch (err) {
618615
if (err instanceof LargeRepoError) {
@@ -855,7 +852,7 @@ export default class Present extends State {
855852
// Direct blob access
856853

857854
getBlobContents(sha) {
858-
return this.cache.getOrSet(Keys.blob(sha), () => {
855+
return this.cache.getOrSet(Keys.blob.oneWith(sha), () => {
859856
return this.git().getBlobContents(sha);
860857
});
861858
}
@@ -876,6 +873,7 @@ export default class Present extends State {
876873

877874
// Cache
878875

876+
/* istanbul ignore next */
879877
getCache() {
880878
return this.cache;
881879
}
@@ -974,6 +972,7 @@ class Cache {
974972
this.didUpdate();
975973
}
976974

975+
/* istanbul ignore next */
977976
[Symbol.iterator]() {
978977
return this.storage[Symbol.iterator]();
979978
}
@@ -988,6 +987,7 @@ class Cache {
988987
this.emitter.emit('did-update');
989988
}
990989

990+
/* istanbul ignore next */
991991
onDidUpdate(callback) {
992992
return this.emitter.on('did-update', callback);
993993
}
@@ -1025,6 +1025,7 @@ class CacheKey {
10251025
}
10261026
}
10271027

1028+
/* istanbul ignore next */
10281029
toString() {
10291030
return `CacheKey(${this.primary})`;
10301031
}
@@ -1041,6 +1042,7 @@ class GroupKey {
10411042
}
10421043
}
10431044

1045+
/* istanbul ignore next */
10441046
toString() {
10451047
return `GroupKey(${this.group})`;
10461048
}

test/atom/decoration.test.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,69 @@ describe('Decoration', function() {
9999
});
100100
});
101101

102+
describe('when called with changed props', function() {
103+
let wrapper, originalDecoration;
104+
105+
beforeEach(function() {
106+
const app = (
107+
<Decoration
108+
editor={editor}
109+
decorable={marker}
110+
type="line"
111+
position="head"
112+
className="something"
113+
/>
114+
);
115+
wrapper = mount(app);
116+
117+
originalDecoration = editor.getLineDecorations({position: 'head', class: 'something'})[0];
118+
});
119+
120+
it('redecorates when a new Editor and Marker are provided', async function() {
121+
const newEditor = await workspace.open(require.resolve('../../package.json'));
122+
const newMarker = newEditor.markBufferRange([[0, 0], [2, 0]]);
123+
124+
wrapper.setProps({editor: newEditor, decorable: newMarker});
125+
126+
assert.isTrue(originalDecoration.isDestroyed());
127+
assert.lengthOf(editor.getLineDecorations({position: 'head', class: 'something'}), 0);
128+
assert.lengthOf(newEditor.getLineDecorations({position: 'head', class: 'something'}), 1);
129+
});
130+
131+
it('redecorates when a new MarkerLayer is provided', function() {
132+
const newLayer = editor.addMarkerLayer();
133+
134+
wrapper.setProps({decorable: newLayer, decorateMethod: 'decorateMarkerLayer'});
135+
136+
assert.isTrue(originalDecoration.isDestroyed());
137+
assert.lengthOf(editor.getLineDecorations({position: 'head', class: 'something'}), 0);
138+
139+
// Turns out Atom doesn't provide any public way to query the markers on a layer.
140+
assert.lengthOf(
141+
Array.from(editor.decorationManager.layerDecorationsByMarkerLayer.get(newLayer)),
142+
1,
143+
);
144+
});
145+
146+
it('updates decoration properties', function() {
147+
wrapper.setProps({className: 'different'});
148+
149+
assert.lengthOf(editor.getLineDecorations({position: 'head', class: 'something'}), 0);
150+
assert.lengthOf(editor.getLineDecorations({position: 'head', class: 'different'}), 1);
151+
assert.isFalse(originalDecoration.isDestroyed());
152+
assert.strictEqual(originalDecoration.getProperties().class, 'different');
153+
});
154+
155+
it('does not redecorate when the decorable is on the wrong TextEditor', async function() {
156+
const newEditor = await workspace.open(require.resolve('../../package.json'));
157+
158+
wrapper.setProps({editor: newEditor});
159+
160+
assert.isTrue(originalDecoration.isDestroyed());
161+
assert.lengthOf(editor.getLineDecorations({}), 0);
162+
});
163+
});
164+
102165
it('destroys its decoration on unmount', function() {
103166
const app = (
104167
<Decoration

test/controllers/editor-conflict-controller.test.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,49 @@ describe('EditorConflictController', function() {
166166
assert.strictEqual(conflicts[2].getChosenSide(), conflicts[2].getSide(THEIRS));
167167
});
168168

169+
it('resolves multiple conflicts as "ours"', function() {
170+
assert.isFalse(conflicts[0].isResolved());
171+
assert.isFalse(conflicts[1].isResolved());
172+
assert.isFalse(conflicts[2].isResolved());
173+
174+
editor.setCursorBufferPosition([8, 3]); // On "Your changes"
175+
editor.addCursorAtBufferPosition([11, 2]); // On "Text in between 0 and 1."
176+
editor.addCursorAtBufferPosition([14, 5]); // On "My middle changes"
177+
editor.addCursorAtBufferPosition([15, 0]); // On "======="
178+
commandRegistry.dispatch(editorView, 'github:resolve-as-ours');
179+
180+
assert.isTrue(conflicts[0].isResolved());
181+
assert.strictEqual(conflicts[0].getChosenSide(), conflicts[0].getSide(OURS));
182+
assert.deepEqual(conflicts[0].getUnchosenSides(), [conflicts[0].getSide(THEIRS)]);
183+
184+
assert.isTrue(conflicts[1].isResolved());
185+
assert.strictEqual(conflicts[1].getChosenSide(), conflicts[1].getSide(OURS));
186+
assert.deepEqual(conflicts[1].getUnchosenSides(), [conflicts[1].getSide(THEIRS)]);
187+
188+
assert.isFalse(conflicts[2].isResolved());
189+
});
190+
191+
it('resolves multiple conflicts as "theirs"', function() {
192+
assert.isFalse(conflicts[0].isResolved());
193+
assert.isFalse(conflicts[1].isResolved());
194+
assert.isFalse(conflicts[2].isResolved());
195+
196+
editor.setCursorBufferPosition([8, 3]); // On "Your changes"
197+
editor.addCursorAtBufferPosition([11, 2]); // On "Text in between 0 and 1."
198+
editor.addCursorAtBufferPosition([22, 5]); // On "More of my changes"
199+
commandRegistry.dispatch(editorView, 'github:resolve-as-theirs');
200+
201+
assert.isTrue(conflicts[0].isResolved());
202+
assert.strictEqual(conflicts[0].getChosenSide(), conflicts[0].getSide(THEIRS));
203+
assert.deepEqual(conflicts[0].getUnchosenSides(), [conflicts[0].getSide(OURS)]);
204+
205+
assert.isFalse(conflicts[1].isResolved());
206+
207+
assert.isTrue(conflicts[2].isResolved());
208+
assert.strictEqual(conflicts[2].getChosenSide(), conflicts[2].getSide(THEIRS));
209+
assert.deepEqual(conflicts[2].getUnchosenSides(), [conflicts[2].getSide(OURS)]);
210+
});
211+
169212
it('disregards conflicts with cursors on both sides', function() {
170213
editor.setCursorBufferPosition([6, 3]); // On "Multi-line even"
171214
editor.addCursorAtBufferPosition([14, 1]); // On "My middle changes"
@@ -316,6 +359,26 @@ describe('EditorConflictController', function() {
316359

317360
await assert.async.isTrue(refreshResolutionProgress.calledWith(fixtureFile));
318361
});
362+
363+
it('performs a resolution from the context menu', function() {
364+
const conflict = conflicts[1];
365+
assert.isFalse(conflict.isResolved());
366+
367+
wrapper.find('ConflictController').at(1).prop('resolveAsSequence')([OURS]);
368+
369+
assert.isTrue(conflict.isResolved());
370+
assert.strictEqual(conflict.getChosenSide(), conflict.getSide(OURS));
371+
});
372+
373+
it('dismisses a conflict from the context menu', function() {
374+
const conflict = conflicts[2];
375+
376+
wrapper.find('ConflictController').at(2).prop('dismiss')();
377+
wrapper.update();
378+
379+
assert.lengthOf(wrapper.find(ConflictController), 2);
380+
assert.isFalse(wrapper.find(ConflictController).someWhere(cc => cc.prop('conflict') === conflict));
381+
});
319382
});
320383

321384
describe('on a file with 3-way diff markers', function() {
@@ -442,4 +505,12 @@ describe('EditorConflictController', function() {
442505
assert.equal(editor.getText(), 'These are my changes\nThese are your changes\n\nPast the end\n');
443506
});
444507
});
508+
509+
it('cleans up its subscriptions when unmounting', async function() {
510+
await useFixture('triple-2way-diff.txt');
511+
wrapper.unmount();
512+
513+
editor.destroy();
514+
assert.isFalse(refreshResolutionProgress.called);
515+
});
445516
});
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Before the start
2+
3+
<<<<<<< HEAD
4+
These are my changes
5+
=======
6+
>>>>>>> master
7+
8+
Past the end

0 commit comments

Comments
 (0)