diff options
Diffstat (limited to 'polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html')
-rw-r--r-- | polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html | 613 |
1 files changed, 374 insertions, 239 deletions
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html index e422354810..faf529b464 100644 --- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html +++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html @@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- +@license Copyright (C) 2015 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); @@ -47,29 +48,120 @@ limitations under the License. sandbox.restore(); }); - test('reload cancels before network resolves', () => { + test('cancel', () => { element = fixture('basic'); const cancelStub = sandbox.stub(element.$.diffBuilder, 'cancel'); + element.cancel(); + assert.isTrue(cancelStub.calledOnce); + }); - // Stub the network calls into requests that never resolve. - sandbox.stub(element, '_getDiff', () => new Promise(() => {})); - - element.reload(); - assert.isTrue(cancelStub.called); + test('line limit with line_wrapping', () => { + element = fixture('basic'); + element.prefs = {line_wrapping: true, line_length: 80, tab_size: 2}; + flushAsynchronousOperations(); + assert.equal(element.customStyle['--line-limit'], '80ch'); }); - test('_diffLength', () => { + test('line limit without line_wrapping', () => { element = fixture('basic'); - const mock = document.createElement('mock-diff-response'); - assert.equal(element._diffLength(mock.diffResponse), 52); + element.prefs = {line_wrapping: false, line_length: 80, tab_size: 2}; + flushAsynchronousOperations(); + assert.isNotOk(element.customStyle['--line-limit']); + }); + + suite('_get{PatchNum|IsParentComment}ByLineAndContent', () => { + let lineEl; + let contentEl; + + setup(() => { + element = fixture('basic'); + lineEl = document.createElement('td'); + contentEl = document.createElement('span'); + }); + + suite('_getPatchNumByLineAndContent', () => { + test('right side', () => { + element.patchRange = {patchNum: 4, basePatchNum: 'PARENT'}; + lineEl.classList.add('right'); + assert.equal(element._getPatchNumByLineAndContent(lineEl, contentEl), + 4); + }); + + test('left side parent by linenum', () => { + element.patchRange = {patchNum: 4, basePatchNum: 'PARENT'}; + lineEl.classList.add('left'); + assert.equal(element._getPatchNumByLineAndContent(lineEl, contentEl), + 4); + }); + + test('left side parent by content', () => { + element.patchRange = {patchNum: 4, basePatchNum: 'PARENT'}; + contentEl.classList.add('remove'); + assert.equal(element._getPatchNumByLineAndContent(lineEl, contentEl), + 4); + }); + + test('left side merge parent', () => { + element.patchRange = {patchNum: 4, basePatchNum: -2}; + contentEl.classList.add('remove'); + assert.equal(element._getPatchNumByLineAndContent(lineEl, contentEl), + 4); + }); + + test('left side non parent', () => { + element.patchRange = {patchNum: 4, basePatchNum: 3}; + contentEl.classList.add('remove'); + assert.equal(element._getPatchNumByLineAndContent(lineEl, contentEl), + 3); + }); + }); + + suite('_getIsParentCommentByLineAndContent', () => { + test('right side', () => { + element.patchRange = {patchNum: 4, basePatchNum: 'PARENT'}; + lineEl.classList.add('right'); + assert.isFalse( + element._getIsParentCommentByLineAndContent(lineEl, contentEl)); + }); + + test('left side parent by linenum', () => { + element.patchRange = {patchNum: 4, basePatchNum: 'PARENT'}; + lineEl.classList.add('left'); + assert.isTrue( + element._getIsParentCommentByLineAndContent(lineEl, contentEl)); + }); + + test('left side parent by content', () => { + element.patchRange = {patchNum: 4, basePatchNum: 'PARENT'}; + contentEl.classList.add('remove'); + assert.isTrue( + element._getIsParentCommentByLineAndContent(lineEl, contentEl)); + }); + + test('left side merge parent', () => { + element.patchRange = {patchNum: 4, basePatchNum: -2}; + contentEl.classList.add('remove'); + assert.isTrue( + element._getIsParentCommentByLineAndContent(lineEl, contentEl)); + }); + + test('left side non parent', () => { + element.patchRange = {patchNum: 4, basePatchNum: 3}; + contentEl.classList.add('remove'); + assert.isFalse( + element._getIsParentCommentByLineAndContent(lineEl, contentEl)); + }); + }); }); suite('not logged in', () => { setup(() => { + const getLoggedInPromise = Promise.resolve(false); stub('gr-rest-api-interface', { - getLoggedIn() { return Promise.resolve(false); }, + getLoggedIn() { return getLoggedInPromise; }, }); element = fixture('basic'); + return getLoggedInPromise; }); test('toggleLeftDiff', () => { @@ -79,15 +171,12 @@ limitations under the License. assert.isFalse(element.classList.contains('no-left')); }); - test('addDraftAtLine', done => { + test('addDraftAtLine', () => { sandbox.stub(element, '_selectLine'); const loggedInErrorSpy = sandbox.spy(); element.addEventListener('show-auth-required', loggedInErrorSpy); element.addDraftAtLine(); - flush(() => { - assert.isTrue(loggedInErrorSpy.called); - done(); - }); + assert.isTrue(loggedInErrorSpy.called); }); test('view does not start with displayLine classList', () => { @@ -103,26 +192,6 @@ limitations under the License. element.$$('.diffContainer').classList.contains('displayLine')); }); - test('loads files weblinks', done => { - sandbox.stub(element.$.restAPI, 'getDiff').returns( - Promise.resolve({ - meta_a: { - web_links: 'foo', - }, - meta_b: { - web_links: 'bar', - }, - })); - element.patchRange = {}; - element._getDiff().then(() => { - assert.deepEqual(element.filesWeblinks, { - meta_a: 'foo', - meta_b: 'bar', - }); - done(); - }); - }); - test('remove comment', () => { element.comments = { meta: { @@ -224,20 +293,6 @@ limitations under the License. }); }); - test('_getRangeString', () => { - const side = 'PARENT'; - const range = { - startLine: 1, - startChar: 1, - endLine: 1, - endChar: 2, - }; - assert.equal(element._getRangeString(side, range), - 'range-1-1-1-2-PARENT'); - assert.equal(element._getRangeString(side, null), - 'line-PARENT'); - }), - test('thread groups', () => { const contentEl = document.createElement('div'); const commentSide = 'left'; @@ -254,18 +309,15 @@ limitations under the License. element.patchRange = {basePatchNum: 1, patchNum: 2}; element.path = 'file.txt'; - sandbox.stub(element.$.diffBuilder, 'createCommentThreadGroup', () => { - const threadGroup = - document.createElement('gr-diff-comment-thread-group'); - threadGroup.patchForNewThreads = 1; - return threadGroup; - }); + const mock = document.createElement('mock-diff-response'); + element.$.diffBuilder._builder = element.$.diffBuilder._getDiffBuilder( + mock.diffResponse, {}, {tab_size: 2, line_length: 80}); // No thread groups. assert.isNotOk(element._getThreadGroupForLine(contentEl)); // A thread group gets created. - assert.isOk(element._getOrCreateThreadAtLineRange(contentEl, + assert.isOk(element._getOrCreateThread(contentEl, patchNum, commentSide, side)); // Try to fetch a thread with a different range. @@ -276,7 +328,7 @@ limitations under the License. endChar: 3, }; - assert.isOk(element._getOrCreateThreadAtLineRange( + assert.isOk(element._getOrCreateThread( contentEl, patchNum, commentSide, side, range)); // The new thread group can be fetched. assert.isOk(element._getThreadGroupForLine(contentEl)); @@ -294,7 +346,6 @@ limitations under the License. suite('image diffs', () => { let mockFile1; let mockFile2; - const stubs = []; setup(() => { mockFile1 = { body: 'Qk06AAAAAAAAADYAAAAoAAAAAQAAAP////8BACAAAAAAAAAAAAATCwAAE' + @@ -306,66 +357,29 @@ limitations under the License. 'wsAAAAAAAAAAAAA/////w==', type: 'image/bmp', }; - const mockCommit = { - commit: '9a1a1d10baece5efbba10bc4ccf808a67a50ac0a', - parents: [{ - commit: '7338aa9adfe57909f1fdaf88975cdea467d3382f', - subject: 'Added a carrot', - }], - author: { - name: 'Wyatt Allen', - email: 'wyatta@google.com', - date: '2016-05-23 21:44:51.000000000', - tz: -420, - }, - committer: { - name: 'Wyatt Allen', - email: 'wyatta@google.com', - date: '2016-05-25 00:25:41.000000000', - tz: -420, - }, - subject: 'Updated the carrot', - message: 'Updated the carrot\n\nChange-Id: Iabcd123\n', - }; - const mockComments = {baseComments: [], comments: []}; - - stubs.push(sandbox.stub(element.$.restAPI, 'getCommitInfo', - () => Promise.resolve(mockCommit))); - stubs.push(sandbox.stub(element.$.restAPI, - 'getChangeFileContents', - (changeId, patchNum, path, opt_parentIndex) => { - return Promise.resolve(opt_parentIndex === 1 ? mockFile1 : - mockFile2); - })); - stubs.push(sandbox.stub(element.$.restAPI, '_getDiffComments', - () => Promise.resolve(mockComments))); - stubs.push(sandbox.stub(element.$.restAPI, 'getDiffDrafts', - () => Promise.resolve(mockComments))); element.patchRange = {basePatchNum: 'PARENT', patchNum: 1}; element.comments = {left: [], right: []}; + element.isImageDiff = true; + element.prefs = { + auto_hide_diff_table_header: true, + context: 10, + cursor_blink_rate: 0, + font_size: 12, + ignore_whitespace: 'IGNORE_NONE', + intraline_difference: true, + line_length: 100, + line_wrapping: false, + show_line_endings: true, + show_tabs: true, + show_whitespace_errors: true, + syntax_highlighting: true, + tab_size: 8, + theme: 'DEFAULT', + }; }); test('renders image diffs with same file name', done => { - const mockDiff = { - meta_a: {name: 'carrot.jpg', content_type: 'image/jpeg', lines: 66}, - meta_b: {name: 'carrot.jpg', content_type: 'image/jpeg', - lines: 560}, - intraline_status: 'OK', - change_type: 'MODIFIED', - diff_header: [ - 'diff --git a/carrot.jpg b/carrot.jpg', - 'index 2adc47d..f9c2f2c 100644', - '--- a/carrot.jpg', - '+++ b/carrot.jpg', - 'Binary files differ', - ], - content: [{skip: 66}], - binary: true, - }; - stubs.push(sandbox.stub(element, '_getDiff', - () => Promise.resolve(mockDiff))); - const rendered = () => { // Recognizes that it should be an image diff. assert.isTrue(element.isImageDiff); @@ -396,7 +410,7 @@ limitations under the License. assert.isOk(leftImage); assert.equal(leftImage.getAttribute('src'), 'data:image/bmp;base64, ' + mockFile1.body); - assert.equal(leftLabelContent.textContent, '1⨉1 image/bmp'); + assert.equal(leftLabelContent.textContent, '1×1 image/bmp'); leftLoaded = true; if (rightLoaded) { element.removeEventListener('render', rendered); @@ -408,7 +422,7 @@ limitations under the License. assert.isOk(rightImage); assert.equal(rightImage.getAttribute('src'), 'data:image/bmp;base64, ' + mockFile2.body); - assert.equal(rightLabelContent.textContent, '1⨉1 image/bmp'); + assert.equal(rightLabelContent.textContent, '1×1 image/bmp'); rightLoaded = true; if (leftLoaded) { @@ -420,10 +434,24 @@ limitations under the License. element.addEventListener('render', rendered); - element.$.restAPI.getDiffPreferences().then(prefs => { - element.prefs = prefs; - element.reload(); - }); + element.baseImage = mockFile1; + element.revisionImage = mockFile2; + element.diff = { + meta_a: {name: 'carrot.jpg', content_type: 'image/jpeg', lines: 66}, + meta_b: {name: 'carrot.jpg', content_type: 'image/jpeg', + lines: 560}, + intraline_status: 'OK', + change_type: 'MODIFIED', + diff_header: [ + 'diff --git a/carrot.jpg b/carrot.jpg', + 'index 2adc47d..f9c2f2c 100644', + '--- a/carrot.jpg', + '+++ b/carrot.jpg', + 'Binary files differ', + ], + content: [{skip: 66}], + binary: true, + }; }); test('renders image diffs with a different file name', done => { @@ -443,8 +471,6 @@ limitations under the License. content: [{skip: 66}], binary: true, }; - stubs.push(sandbox.stub(element, '_getDiff', - () => Promise.resolve(mockDiff))); const rendered = () => { // Recognizes that it should be an image diff. @@ -478,7 +504,7 @@ limitations under the License. assert.isOk(leftImage); assert.equal(leftImage.getAttribute('src'), 'data:image/bmp;base64, ' + mockFile1.body); - assert.equal(leftLabelContent.textContent, '1⨉1 image/bmp'); + assert.equal(leftLabelContent.textContent, '1×1 image/bmp'); leftLoaded = true; if (rightLoaded) { element.removeEventListener('render', rendered); @@ -490,7 +516,7 @@ limitations under the License. assert.isOk(rightImage); assert.equal(rightImage.getAttribute('src'), 'data:image/bmp;base64, ' + mockFile2.body); - assert.equal(rightLabelContent.textContent, '1⨉1 image/bmp'); + assert.equal(rightLabelContent.textContent, '1×1 image/bmp'); rightLoaded = true; if (leftLoaded) { @@ -502,10 +528,11 @@ limitations under the License. element.addEventListener('render', rendered); - element.$.restAPI.getDiffPreferences().then(prefs => { - element.prefs = prefs; - element.reload(); - }); + element.baseImage = mockFile1; + element.baseImage._name = mockDiff.meta_a.name; + element.revisionImage = mockFile2; + element.revisionImage._name = mockDiff.meta_b.name; + element.diff = mockDiff; }); test('renders added image', done => { @@ -524,8 +551,6 @@ limitations under the License. content: [{skip: 66}], binary: true, }; - stubs.push(sandbox.stub(element, '_getDiff', - () => Promise.resolve(mockDiff))); element.addEventListener('render', () => { // Recognizes that it should be an image diff. @@ -541,10 +566,8 @@ limitations under the License. done(); }); - element.$.restAPI.getDiffPreferences().then(prefs => { - element.prefs = prefs; - element.reload(); - }); + element.revisionImage = mockFile2; + element.diff = mockDiff; }); test('renders removed image', done => { @@ -563,8 +586,6 @@ limitations under the License. content: [{skip: 66}], binary: true, }; - stubs.push(sandbox.stub(element, '_getDiff', - () => Promise.resolve(mockDiff))); element.addEventListener('render', () => { // Recognizes that it should be an image diff. @@ -580,10 +601,8 @@ limitations under the License. done(); }); - element.$.restAPI.getDiffPreferences().then(prefs => { - element.prefs = prefs; - element.reload(); - }); + element.baseImage = mockFile1; + element.diff = mockDiff; }); test('does not render disallowed image type', done => { @@ -604,9 +623,6 @@ limitations under the License. }; mockFile1.type = 'image/jpeg-evil'; - stubs.push(sandbox.stub(element, '_getDiff', - () => Promise.resolve(mockDiff))); - element.addEventListener('render', () => { // Recognizes that it should be an image diff. assert.isTrue(element.isImageDiff); @@ -617,10 +633,8 @@ limitations under the License. done(); }); - element.$.restAPI.getDiffPreferences().then(prefs => { - element.prefs = prefs; - element.reload(); - }); + element.baseImage = mockFile1; + element.diff = mockDiff; }); }); @@ -667,20 +681,10 @@ limitations under the License. content.click(); }); - test('_getDiff handles null diff responses', done => { - stub('gr-rest-api-interface', { - getDiff() { return Promise.resolve(null); }, - }); - element.changeNum = 123; - element.patchRange = {basePatchNum: 1, patchNum: 2}; - element.path = 'file.txt'; - element._getDiff().then(done); - }); - suite('getCursorStops', () => { const setupDiff = function() { const mock = document.createElement('mock-diff-response'); - element._diff = mock.diffResponse; + element.diff = mock.diffResponse; element.comments = { left: [], right: [], @@ -729,13 +733,8 @@ limitations under the License. suite('logged in', () => { let fakeLineEl; setup(() => { - stub('gr-rest-api-interface', { - getLoggedIn() { return Promise.resolve(true); }, - getPreferences() { - return Promise.resolve({time_format: 'HHMM_12'}); - }, - }); element = fixture('basic'); + element.loggedIn = true; element.patchRange = {}; fakeLineEl = { @@ -746,40 +745,40 @@ limitations under the License. }; }); - test('addDraftAtLine', done => { + test('addDraftAtLine', () => { sandbox.stub(element, '_selectLine'); sandbox.stub(element, '_createComment'); - const loggedInErrorSpy = sandbox.spy(); - element.addEventListener('show-auth-required', loggedInErrorSpy); element.addDraftAtLine(fakeLineEl); - flush(() => { - assert.isFalse(loggedInErrorSpy.called); - assert.isTrue(element._createComment - .calledWithExactly(fakeLineEl, 42)); - done(); - }); + assert.isTrue(element._createComment + .calledWithExactly(fakeLineEl, 42)); }); - test('addDraftAtLine on an edit', done => { + test('addDraftAtLine on an edit', () => { element.patchRange.basePatchNum = element.EDIT_NAME; sandbox.stub(element, '_selectLine'); sandbox.stub(element, '_createComment'); - const loggedInErrorSpy = sandbox.spy(); const alertSpy = sandbox.spy(); - element.addEventListener('show-auth-required', loggedInErrorSpy); element.addEventListener('show-alert', alertSpy); element.addDraftAtLine(fakeLineEl); - flush(() => { - assert.isFalse(loggedInErrorSpy.called); - assert.isTrue(alertSpy.called); - assert.isFalse(element._createComment.called); - done(); - }); + assert.isTrue(alertSpy.called); + assert.isFalse(element._createComment.called); + }); + + test('addDraftAtLine on an edit base', () => { + element.patchRange.patchNum = element.EDIT_NAME; + element.patchRange.basePatchNum = element.PARENT_NAME; + sandbox.stub(element, '_selectLine'); + sandbox.stub(element, '_createComment'); + const alertSpy = sandbox.spy(); + element.addEventListener('show-alert', alertSpy); + element.addDraftAtLine(fakeLineEl); + assert.isTrue(alertSpy.called); + assert.isFalse(element._createComment.called); }); suite('change in preferences', () => { setup(() => { - element._diff = { + element.diff = { meta_a: {name: 'carrot.jpg', content_type: 'image/jpeg', lines: 66}, meta_b: {name: 'carrot.jpg', content_type: 'image/jpeg', lines: 560}, @@ -864,6 +863,28 @@ limitations under the License. assert.include(element.comments.left, comment); }); + test('discarding a draft', () => { + const draftID = 'tempID'; + const id = 'savedID'; + const comment = { + __draft: true, + __draftID: draftID, + side: 'PARENT', + __commentSide: 'left', + }; + const diffCommentsModifiedStub = sandbox.stub(); + element.addEventListener('diff-comments-modified', + diffCommentsModifiedStub); + element.comments.left.push(comment); + comment.id = id; + element.fire('comment-discard', {comment}); + const drafts = element.comments.left.filter(item => { + return item.__draftID === draftID; + }); + assert.equal(drafts.length, 0); + assert.isTrue(diffCommentsModifiedStub.called); + }); + test('saving a draft', () => { const draftID = 'tempID'; const id = 'savedID'; @@ -873,21 +894,26 @@ limitations under the License. side: 'PARENT', __commentSide: 'left', }; + const diffCommentsModifiedStub = sandbox.stub(); + element.addEventListener('diff-comments-modified', + diffCommentsModifiedStub); element.comments.left.push(comment); comment.id = id; - element.fire('comment-update', {comment}); + element.fire('comment-save', {comment}); const drafts = element.comments.left.filter(item => { return item.__draftID === draftID; }); assert.equal(drafts.length, 1); assert.equal(drafts[0].id, id); + assert.isTrue(diffCommentsModifiedStub.called); }); }); }); suite('diff header', () => { setup(() => { - element._diff = { + element = fixture('basic'); + element.diff = { meta_a: {name: 'carrot.jpg', content_type: 'image/jpeg', lines: 66}, meta_b: {name: 'carrot.jpg', content_type: 'image/jpeg', lines: 560}, @@ -900,21 +926,30 @@ limitations under the License. test('hidden', () => { assert.equal(element._diffHeaderItems.length, 0); - element.push('_diff.diff_header', 'diff --git a/test.jpg b/test.jpg'); + element.push('diff.diff_header', 'diff --git a/test.jpg b/test.jpg'); assert.equal(element._diffHeaderItems.length, 0); - element.push('_diff.diff_header', 'index 2adc47d..f9c2f2c 100644'); + element.push('diff.diff_header', 'index 2adc47d..f9c2f2c 100644'); assert.equal(element._diffHeaderItems.length, 0); - element.push('_diff.diff_header', '--- a/test.jpg'); + element.push('diff.diff_header', '--- a/test.jpg'); assert.equal(element._diffHeaderItems.length, 0); - element.push('_diff.diff_header', '+++ b/test.jpg'); + element.push('diff.diff_header', '+++ b/test.jpg'); assert.equal(element._diffHeaderItems.length, 0); - element.push('_diff.diff_header', 'test'); + element.push('diff.diff_header', 'test'); assert.equal(element._diffHeaderItems.length, 1); flushAsynchronousOperations(); assert.equal(element.$.diffHeader.textContent.trim(), 'test'); - element.set('_diff.binary', true); + }); + + test('binary files', () => { + element.diff.binary = true; + assert.equal(element._diffHeaderItems.length, 0); + element.push('diff.diff_header', 'diff --git a/test.jpg b/test.jpg'); assert.equal(element._diffHeaderItems.length, 0); + element.push('diff.diff_header', 'test'); + assert.equal(element._diffHeaderItems.length, 1); + element.push('diff.diff_header', 'Binary files differ'); + assert.equal(element._diffHeaderItems.length, 1); }); }); @@ -924,39 +959,47 @@ limitations under the License. setup(() => { element = fixture('basic'); renderStub = sandbox.stub(element.$.diffBuilder, 'render', - () => Promise.resolve()); + () => { + Promise.resolve(); + element.$.diffBuilder.dispatchEvent( + new CustomEvent('render', {bubbles: true})); + }); const mock = document.createElement('mock-diff-response'); - element._diff = mock.diffResponse; + sandbox.stub(element.$.diffBuilder, 'getDiffLength').returns(10000); + element.diff = mock.diffResponse; element.comments = {left: [], right: []}; element.noRenderOnPrefsChange = true; }); - test('lage render w/ context = 10', () => { + test('large render w/ context = 10', done => { element.prefs = {context: 10}; - sandbox.stub(element, '_diffLength', () => 10000); - return element._renderDiffTable().then(() => { + element.addEventListener('render', () => { assert.isTrue(renderStub.called); assert.isFalse(element._showWarning); + done(); }); + element._renderDiffTable(); }); - test('lage render w/ whole file and bypass', () => { + test('large render w/ whole file and bypass', done => { element.prefs = {context: -1}; element._safetyBypass = 10; - sandbox.stub(element, '_diffLength', () => 10000); - return element._renderDiffTable().then(() => { + element.addEventListener('render', () => { assert.isTrue(renderStub.called); assert.isFalse(element._showWarning); + done(); }); + element._renderDiffTable(); }); - test('lage render w/ whole file and no bypass', () => { + test('large render w/ whole file and no bypass', done => { element.prefs = {context: -1}; - sandbox.stub(element, '_diffLength', () => 10000); - return element._renderDiffTable().then(() => { + element.addEventListener('render', () => { assert.isFalse(renderStub.called); assert.isTrue(element._showWarning); + done(); }); + element._renderDiffTable(); }); }); @@ -965,52 +1008,144 @@ limitations under the License. element = fixture('basic'); }); - test('clearBlame', () => { - element._blame = []; + test('unsetting', () => { + element.blame = []; const setBlameSpy = sandbox.spy(element.$.diffBuilder, 'setBlame'); element.classList.add('showBlame'); - element.clearBlame(); - assert.isNull(element._blame); + element.blame = null; assert.isTrue(setBlameSpy.calledWithExactly(null)); assert.isFalse(element.classList.contains('showBlame')); }); - test('loadBlame', () => { + test('setting', () => { const mockBlame = [{id: 'commit id', ranges: [{start: 1, end: 2}]}]; - const showAlertStub = sinon.stub(); - element.addEventListener('show-alert', showAlertStub); - const getBlameStub = sandbox.stub(element.$.restAPI, 'getBlame') - .returns(Promise.resolve(mockBlame)); - element.changeNum = 42; - element.patchRange = {patchNum: 5, basePatchNum: 4}; - element.path = 'foo/bar.baz'; - return element.loadBlame().then(() => { - assert.isTrue(getBlameStub.calledWithExactly( - 42, 5, 'foo/bar.baz', true)); - assert.isFalse(showAlertStub.called); - assert.equal(element._blame, mockBlame); - assert.isTrue(element.classList.contains('showBlame')); - }); - }); - - test('loadBlame empty', () => { - const mockBlame = []; - const showAlertStub = sinon.stub(); - element.addEventListener('show-alert', showAlertStub); - sandbox.stub(element.$.restAPI, 'getBlame') - .returns(Promise.resolve(mockBlame)); - element.changeNum = 42; - element.patchRange = {patchNum: 5, basePatchNum: 4}; - element.path = 'foo/bar.baz'; - return element.loadBlame() - .then(() => { - assert.isTrue(false, 'Promise should not resolve'); - }) - .catch(() => { - assert.isTrue(showAlertStub.calledOnce); - assert.isNull(element._blame); - assert.isFalse(element.classList.contains('showBlame')); - }); + element.blame = mockBlame; + assert.isTrue(element.classList.contains('showBlame')); + }); + }); + + suite('trailing newlines', () => { + setup(() => { + element = fixture('basic'); + }); + + suite('_lastChunkForSide', () => { + test('deltas', () => { + const diff = {content: [ + {a: ['foo', 'bar'], b: ['baz']}, + {ab: ['foo', 'bar', 'baz']}, + {b: ['foo']}, + ]}; + assert.equal(element._lastChunkForSide(diff, false), diff.content[2]); + assert.equal(element._lastChunkForSide(diff, true), diff.content[1]); + + diff.content.push({a: ['foo'], b: ['bar']}); + assert.equal(element._lastChunkForSide(diff, false), diff.content[3]); + assert.equal(element._lastChunkForSide(diff, true), diff.content[3]); + }); + + test('addition', () => { + const diff = {content: [ + {b: ['foo', 'bar', 'baz']}, + ]}; + assert.equal(element._lastChunkForSide(diff, false), diff.content[0]); + assert.isNull(element._lastChunkForSide(diff, true)); + }); + + test('deletion', () => { + const diff = {content: [ + {a: ['foo', 'bar', 'baz']}, + ]}; + assert.isNull(element._lastChunkForSide(diff, false)); + assert.equal(element._lastChunkForSide(diff, true), diff.content[0]); + }); + + test('empty', () => { + const diff = {content: []}; + assert.isNull(element._lastChunkForSide(diff, false)); + assert.isNull(element._lastChunkForSide(diff, true)); + }); + }); + + suite('_hasTrailingNewlines', () => { + test('shared no trailing', () => { + const diff = undefined; + sandbox.stub(element, '_lastChunkForSide') + .returns({ab: ['foo', 'bar']}); + assert.isFalse(element._hasTrailingNewlines(diff, false)); + assert.isFalse(element._hasTrailingNewlines(diff, true)); + }); + + test('delta trailing in right', () => { + const diff = undefined; + sandbox.stub(element, '_lastChunkForSide') + .returns({a: ['foo', 'bar'], b: ['baz', '']}); + assert.isTrue(element._hasTrailingNewlines(diff, false)); + assert.isFalse(element._hasTrailingNewlines(diff, true)); + }); + + test('addition', () => { + const diff = undefined; + sandbox.stub(element, '_lastChunkForSide', (diff, leftSide) => { + if (leftSide) { return null; } + return {b: ['foo', '']}; + }); + assert.isTrue(element._hasTrailingNewlines(diff, false)); + assert.isNull(element._hasTrailingNewlines(diff, true)); + }); + + test('deletion', () => { + const diff = undefined; + sandbox.stub(element, '_lastChunkForSide', (diff, leftSide) => { + if (!leftSide) { return null; } + return {a: ['foo']}; + }); + assert.isNull(element._hasTrailingNewlines(diff, false)); + assert.isFalse(element._hasTrailingNewlines(diff, true)); + }); + }); + + test('_computeNewlineWarning', () => { + const NO_NEWLINE_BASE = 'No newline at end of base file.'; + const NO_NEWLINE_REVISION = 'No newline at end of revision file.'; + + let hasLeft; + let hasRight; + sandbox.stub(element, '_hasTrailingNewlines', (diff, left) => { + if (left) { return hasLeft; } + return hasRight; + }); + const diff = undefined; + + // The revision has a trailing newline, but the base doesn't. + hasLeft = true; + hasRight = false; + assert.equal(element._computeNewlineWarning(diff), NO_NEWLINE_REVISION); + + // Trailing newlines were undetermined in the revision. + hasLeft = true; + hasRight = null; + assert.isNull(element._computeNewlineWarning(diff)); + + // Missing trailing newlines in the base. + hasLeft = false; + hasRight = null; + assert.equal(element._computeNewlineWarning(diff), NO_NEWLINE_BASE); + + // Missing trailing newlines in both. + hasLeft = false; + hasRight = false; + assert.equal(element._computeNewlineWarning(diff), + NO_NEWLINE_BASE + ' — ' + NO_NEWLINE_REVISION); + }); + + test('_computeNewlineWarningClass', () => { + const hidden = 'newlineWarning hidden'; + const shown = 'newlineWarning'; + assert.equal(element._computeNewlineWarningClass(null, true), hidden); + assert.equal(element._computeNewlineWarningClass('foo', true), hidden); + assert.equal(element._computeNewlineWarningClass(null, false), hidden); + assert.equal(element._computeNewlineWarningClass('foo', false), shown); }); }); }); |