| <!DOCTYPE html> |
| <!-- |
| Copyright (C) 2015 The Android Open Source Project |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| |
| <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes"> |
| <title>gr-change-view</title> |
| |
| <script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script> |
| <script src="../../../bower_components/web-component-tester/browser.js"></script> |
| <script src="../../../bower_components/page/page.js"></script> |
| |
| <link rel="import" href="../../../bower_components/iron-test-helpers/iron-test-helpers.html"> |
| <link rel="import" href="gr-change-view.html"> |
| |
| <script>void(0);</script> |
| |
| <test-fixture id="basic"> |
| <template> |
| <gr-change-view></gr-change-view> |
| </template> |
| </test-fixture> |
| |
| <script> |
| suite('gr-change-view tests', function() { |
| var element; |
| var sandbox; |
| var showStub; |
| var TEST_SCROLL_TOP_PX = 100; |
| |
| setup(function() { |
| sandbox = sinon.sandbox.create(); |
| showStub = sandbox.stub(page, 'show'); |
| stub('gr-rest-api-interface', { |
| getConfig: function() { return Promise.resolve({}); }, |
| getAccount: function() { return Promise.resolve(null); }, |
| }); |
| element = fixture('basic'); |
| }); |
| |
| teardown(function(done) { |
| flush(function() { |
| sandbox.restore(); |
| done(); |
| }); |
| }); |
| |
| suite('keyboard shortcuts', function() { |
| test('S should toggle the CL star', function() { |
| var starStub = sandbox.stub(element.$.changeStar, 'toggleStar'); |
| MockInteractions.pressAndReleaseKeyOn(element, 83, null, 's'); |
| assert(starStub.called); |
| }); |
| |
| test('U should navigate to / if no backPage set', function() { |
| MockInteractions.pressAndReleaseKeyOn(element, 85, null, 'u'); |
| assert(showStub.lastCall.calledWithExactly('/')); |
| }); |
| |
| test('U should navigate to backPage if set', function() { |
| element.backPage = '/dashboard/self'; |
| MockInteractions.pressAndReleaseKeyOn(element, 85, null, 'u'); |
| assert(showStub.lastCall.calledWithExactly('/dashboard/self')); |
| }); |
| |
| test('A fires an error event when not logged in', function(done) { |
| sandbox.stub(element, '_getLoggedIn').returns(Promise.resolve(false)); |
| var loggedInErrorSpy = sandbox.spy(); |
| element.addEventListener('show-auth-required', loggedInErrorSpy); |
| MockInteractions.pressAndReleaseKeyOn(element, 65, null, 'a'); |
| flush(function() { |
| assert.isFalse(element.$.replyOverlay.opened); |
| assert.isTrue(loggedInErrorSpy.called); |
| done(); |
| }); |
| }); |
| |
| test('shift A does not open reply overlay', function(done) { |
| sandbox.stub(element, '_getLoggedIn').returns(Promise.resolve(true)); |
| MockInteractions.pressAndReleaseKeyOn(element, 65, 'shift', 'a'); |
| flush(function() { |
| assert.isFalse(element.$.replyOverlay.opened); |
| done(); |
| }); |
| }); |
| |
| test('A toggles overlay when logged in', function(done) { |
| sandbox.stub(element, '_getLoggedIn').returns(Promise.resolve(true)); |
| MockInteractions.pressAndReleaseKeyOn(element, 65, null, 'a'); |
| flush(function() { |
| assert.isTrue(element.$.replyOverlay.opened); |
| element.$.replyOverlay.close(); |
| assert.isFalse(element.$.replyOverlay.opened); |
| done(); |
| }); |
| }); |
| |
| test('X should expand all messages', function() { |
| var handleExpand = |
| sandbox.stub(element.$.messageList, 'handleExpandCollapse'); |
| MockInteractions.pressAndReleaseKeyOn(element, 88, null, 'x'); |
| assert(handleExpand.calledWith(true)); |
| }); |
| |
| test('Z should collapse all messages', function() { |
| var handleExpand = |
| sandbox.stub(element.$.messageList, 'handleExpandCollapse'); |
| MockInteractions.pressAndReleaseKeyOn(element, 90, null, 'z'); |
| assert(handleExpand.calledWith(false)); |
| }); |
| |
| test('shift + R should fetch and navigate to the latest patch set', |
| function(done) { |
| element._changeNum = '42'; |
| element._patchRange = { |
| basePatchNum: 'PARENT', |
| patchNum: 1, |
| }; |
| element._change = { |
| change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca', |
| _number: 42, |
| revisions: { |
| rev1: {_number: 1}, |
| }, |
| current_revision: 'rev1', |
| status: 'NEW', |
| labels: {}, |
| actions: {}, |
| }; |
| |
| sandbox.stub(element.$.actions, 'reload'); |
| |
| showStub.restore(); |
| showStub = sandbox.stub(page, 'show', function(arg) { |
| assert.equal(arg, '/c/42'); |
| done(); |
| }); |
| |
| MockInteractions.pressAndReleaseKeyOn(element, 82, 'shift', 'r'); |
| }); |
| |
| test('d should open download overlay', function() { |
| var stub = sandbox.stub(element.$.downloadOverlay, 'open'); |
| MockInteractions.pressAndReleaseKeyOn(element, 68, null, 'd'); |
| assert.isTrue(stub.called); |
| }); |
| }); |
| |
| test('_computeDescriptionReadOnly', function() { |
| assert.equal(element._computeDescriptionReadOnly(false, |
| {owner: {_account_id: 1}}, {_account_id: 1}), true); |
| assert.equal(element._computeDescriptionReadOnly(true, |
| {owner: {_account_id: 0}}, {_account_id: 1}), true); |
| assert.equal(element._computeDescriptionReadOnly(true, |
| {owner: {_account_id: 1}}, {_account_id: 1}), false); |
| }); |
| |
| test('_computeDescriptionPlaceholder', function() { |
| assert.equal(element._computeDescriptionPlaceholder(true), |
| 'No patch set description'); |
| assert.equal(element._computeDescriptionPlaceholder(false), |
| 'Add a patch set description'); |
| }); |
| |
| test('_computePatchSetDisabled', function() { |
| var basePatchNum = 'PARENT'; |
| var patchNum = 1; |
| assert.equal(element._computePatchSetDisabled(patchNum, basePatchNum), |
| false); |
| basePatchNum = 1; |
| assert.equal(element._computePatchSetDisabled(patchNum, basePatchNum), |
| true); |
| patchNum = 2; |
| assert.equal(element._computePatchSetDisabled(patchNum, basePatchNum), |
| false); |
| }); |
| |
| test('_prepareCommitMsgForLinkify', function() { |
| var commitMessage = 'R=test@google.com'; |
| var result = element._prepareCommitMsgForLinkify(commitMessage); |
| assert.equal(result, 'R=\u200Btest@google.com'); |
| |
| commitMessage = 'R=test@google.com\nR=test@google.com'; |
| var result = element._prepareCommitMsgForLinkify(commitMessage); |
| assert.equal(result, 'R=\u200Btest@google.com\nR=\u200Btest@google.com'); |
| }), |
| |
| test('_handleDescriptionChanged', function() { |
| var putDescStub = sandbox.stub(element.$.restAPI, 'setDescription') |
| .returns(Promise.resolve({ok: true})); |
| sandbox.stub(element, '_computeDescriptionReadOnly'); |
| |
| element._changeNum = '42'; |
| element._patchRange = { |
| basePatchNum: 'PARENT', |
| patchNum: 1, |
| }; |
| element._selectedPatchNum = '1'; |
| element._change = { |
| change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca', |
| revisions: { |
| rev1: {_number: 1, description: 'test', commit: {commit: 'rev1'}}, |
| }, |
| current_revision: 'rev1', |
| status: 'NEW', |
| labels: {}, |
| actions: {}, |
| owner: {_account_id: 1}, |
| }; |
| element._account = {_account_id: 1}; |
| element._loggedIn = true; |
| |
| flushAsynchronousOperations(); |
| var label = element.$.descriptionLabel; |
| assert.equal(label.value, 'test'); |
| label.editing = true; |
| label._inputText = 'test2'; |
| label._save(); |
| flushAsynchronousOperations(); |
| assert.isTrue(putDescStub.called); |
| assert.equal(putDescStub.args[0][2], 'test2'); |
| }); |
| |
| test('_updateRebaseAction', function() { |
| var currentRevisionActions = { |
| cherrypick: { |
| enabled: true, |
| label: 'Cherry Pick', |
| method: 'POST', |
| title: 'cherrypick' |
| }, |
| rebase: { |
| enabled: true, |
| label: 'Rebase', |
| method: 'POST', |
| title: 'Rebase onto tip of branch or parent change' |
| }, |
| }; |
| |
| // Rebase enabled should always end up true. |
| // When rebase is enabled initially, rebaseOnCurrent should be set to |
| // true. |
| assert.equal(element._updateRebaseAction(currentRevisionActions), |
| currentRevisionActions); |
| |
| assert.isTrue(currentRevisionActions.rebase.enabled); |
| assert.isTrue(currentRevisionActions.rebase.rebaseOnCurrent); |
| |
| delete currentRevisionActions.rebase.enabled; |
| |
| // When rebase is not enabled initially, rebaseOnCurrent should be set to |
| // false. |
| assert.equal(element._updateRebaseAction(currentRevisionActions), |
| currentRevisionActions); |
| |
| assert.isTrue(currentRevisionActions.rebase.enabled); |
| assert.isFalse(currentRevisionActions.rebase.rebaseOnCurrent); |
| }); |
| |
| test('_reload is called when an approved label is removed', function() { |
| var vote = {_account_id: 1, name: 'bojack', value: 1}; |
| element._changeNum = '42'; |
| element._patchRange = { |
| basePatchNum: 'PARENT', |
| patchNum: 1, |
| }; |
| element._change = { |
| change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca', |
| revisions: { |
| rev2: {_number: 2}, |
| rev1: {_number: 1}, |
| rev13: {_number: 13}, |
| rev3: {_number: 3}, |
| }, |
| current_revision: 'rev3', |
| status: 'NEW', |
| labels: { |
| test: { |
| all: [vote], |
| default_value: 0, |
| values: [], |
| approved: {}, |
| }, |
| }, |
| }; |
| flushAsynchronousOperations(); |
| var reloadStub = sandbox.stub(element, '_reload'); |
| element.splice('_change.labels.test.all', 0, 1); |
| assert.isFalse(reloadStub.called); |
| element._change.labels.test.all.push(vote); |
| element._change.labels.test.all.push(vote); |
| element._change.labels.test.approved = vote; |
| flushAsynchronousOperations(); |
| element.splice('_change.labels.test.all', 0, 2); |
| assert.isTrue(reloadStub.called); |
| assert.isTrue(reloadStub.calledOnce); |
| }); |
| |
| test('reply button has updated count when there are drafts', function() { |
| var replyButton = element.$$('gr-button.reply'); |
| assert.ok(replyButton); |
| assert.equal(replyButton.textContent, 'Reply'); |
| |
| element._diffDrafts = null; |
| assert.equal(replyButton.textContent, 'Reply'); |
| |
| element._diffDrafts = {}; |
| assert.equal(replyButton.textContent, 'Reply'); |
| |
| element._diffDrafts = { |
| 'file1.txt': [{}], |
| 'file2.txt': [{}, {}], |
| }; |
| assert.equal(replyButton.textContent, 'Reply (3)'); |
| }); |
| |
| test('comment events properly update diff drafts', function() { |
| element._patchRange = { |
| basePatchNum: 'PARENT', |
| patchNum: 2, |
| }; |
| var draft = { |
| __draft: true, |
| id: 'id1', |
| path: '/foo/bar.txt', |
| text: 'hello', |
| }; |
| element._handleCommentSave({target: {comment: draft}}); |
| draft.patch_set = 2; |
| assert.deepEqual(element._diffDrafts, {'/foo/bar.txt': [draft]}); |
| draft.patch_set = null; |
| draft.text = 'hello, there'; |
| element._handleCommentSave({target: {comment: draft}}); |
| draft.patch_set = 2; |
| assert.deepEqual(element._diffDrafts, {'/foo/bar.txt': [draft]}); |
| var draft2 = { |
| __draft: true, |
| id: 'id2', |
| path: '/foo/bar.txt', |
| text: 'hola', |
| }; |
| element._handleCommentSave({target: {comment: draft2}}); |
| draft2.patch_set = 2; |
| assert.deepEqual(element._diffDrafts, {'/foo/bar.txt': [draft, draft2]}); |
| draft.patch_set = null; |
| element._handleCommentDiscard({target: {comment: draft}}); |
| draft.patch_set = 2; |
| assert.deepEqual(element._diffDrafts, {'/foo/bar.txt': [draft2]}); |
| element._handleCommentDiscard({target: {comment: draft2}}); |
| assert.deepEqual(element._diffDrafts, {}); |
| }); |
| |
| test('change num change', function() { |
| element._changeNum = null; |
| element._patchRange = { |
| basePatchNum: 'PARENT', |
| patchNum: 2, |
| }; |
| element._change = { |
| change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca', |
| labels: {}, |
| }; |
| element.viewState.changeNum = null; |
| element.viewState.diffMode = 'UNIFIED'; |
| assert.equal(element.viewState.numFilesShown, 200); |
| assert.equal(element._numFilesShown, 200); |
| element._numFilesShown = 150; |
| flushAsynchronousOperations(); |
| assert.equal(element.viewState.diffMode, 'UNIFIED'); |
| assert.equal(element.viewState.numFilesShown, 150); |
| |
| element._changeNum = '1'; |
| element.params = {changeNum: '1'}; |
| element._change.newProp = '1'; |
| flushAsynchronousOperations(); |
| assert.equal(element.viewState.diffMode, 'UNIFIED'); |
| assert.equal(element.viewState.changeNum, '1'); |
| |
| element._changeNum = '2'; |
| element.params = {changeNum: '2'}; |
| element._change.newProp = '2'; |
| flushAsynchronousOperations(); |
| assert.isNull(element.viewState.diffMode); |
| assert.equal(element.viewState.changeNum, '2'); |
| assert.equal(element.viewState.numFilesShown, 200); |
| assert.equal(element._numFilesShown, 200); |
| }); |
| |
| test('patch num change', function(done) { |
| element._changeNum = '42'; |
| element._patchRange = { |
| basePatchNum: 'PARENT', |
| patchNum: 2, |
| }; |
| element._change = { |
| change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca', |
| revisions: { |
| rev2: {_number: 2}, |
| rev1: {_number: 1}, |
| rev13: {_number: 13}, |
| rev3: {_number: 3}, |
| }, |
| current_revision: 'rev3', |
| status: 'NEW', |
| labels: {}, |
| }; |
| element.viewState.diffMode = 'UNIFIED'; |
| flushAsynchronousOperations(); |
| |
| var selectEl = element.$$('.patchInfo-header select'); |
| assert.ok(selectEl); |
| var optionEls = Polymer.dom(element.root).querySelectorAll( |
| '.patchInfo-header option'); |
| assert.equal(optionEls.length, 4); |
| var select = element.$$('.patchInfo-header #patchSetSelect').bindValue; |
| assert.notEqual(select, 1); |
| assert.equal(select, 2); |
| assert.notEqual(select, 3); |
| assert.equal(optionEls[3].value, 13); |
| |
| var numEvents = 0; |
| selectEl.addEventListener('change', function(e) { |
| assert.equal(element.viewState.diffMode, 'UNIFIED'); |
| numEvents++; |
| if (numEvents == 1) { |
| assert(showStub.lastCall.calledWithExactly('/c/42/1'), |
| 'Should navigate to /c/42/1'); |
| selectEl.value = '3'; |
| element.fire('change', {}, {node: selectEl}); |
| } else if (numEvents == 2) { |
| assert(showStub.lastCall.calledWithExactly('/c/42/3'), |
| 'Should navigate to /c/42/3'); |
| done(); |
| } |
| }); |
| selectEl.value = '1'; |
| element.fire('change', {}, {node: selectEl}); |
| }); |
| |
| test('patch num change with missing current_revision', function(done) { |
| element._changeNum = '42'; |
| element._patchRange = { |
| basePatchNum: 'PARENT', |
| patchNum: 2, |
| }; |
| element._change = { |
| change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca', |
| revisions: { |
| rev2: {_number: 2}, |
| rev1: {_number: 1}, |
| rev13: {_number: 13}, |
| rev3: {_number: 3}, |
| }, |
| status: 'NEW', |
| labels: {}, |
| }; |
| flushAsynchronousOperations(); |
| var selectEl = element.$$('.patchInfo-header select'); |
| assert.ok(selectEl); |
| var optionEls = Polymer.dom(element.root).querySelectorAll( |
| '.patchInfo-header option'); |
| assert.equal(optionEls.length, 4); |
| assert.notEqual( |
| element.$$('.patchInfo-header #patchSetSelect').bindValue, 1); |
| assert.equal( |
| element.$$('.patchInfo-header #patchSetSelect').bindValue, 2); |
| assert.notEqual( |
| element.$$('.patchInfo-header #patchSetSelect').bindValue, 3); |
| assert.equal(optionEls[3].value, 13); |
| |
| var numEvents = 0; |
| selectEl.addEventListener('change', function(e) { |
| numEvents++; |
| if (numEvents == 1) { |
| assert(showStub.lastCall.calledWithExactly('/c/42/1'), |
| 'Should navigate to /c/42/1'); |
| selectEl.value = '3'; |
| element.fire('change', {}, {node: selectEl}); |
| } else if (numEvents == 2) { |
| assert(showStub.lastCall.calledWithExactly('/c/42/3'), |
| 'Should navigate to /c/42/3'); |
| done(); |
| } |
| }); |
| selectEl.value = '1'; |
| element.fire('change', {}, {node: selectEl}); |
| }); |
| |
| test('don’t reload entire page when patchRange changes', function() { |
| var reloadStub = sandbox.stub(element, '_reload', |
| function() { return Promise.resolve(); }); |
| var reloadPatchDependentStub = sandbox.stub(element, |
| '_reloadPatchNumDependentResources', |
| function() { return Promise.resolve(); }); |
| var relatedClearSpy = sandbox.spy(element.$.relatedChanges, 'clear'); |
| |
| var value = { |
| view: 'gr-change-view', |
| patchNum: '1', |
| }; |
| element._paramsChanged(value); |
| assert.isTrue(reloadStub.calledOnce); |
| assert.isTrue(relatedClearSpy.calledOnce); |
| |
| element._initialLoadComplete = true; |
| |
| value.basePatchNum = '1'; |
| value.patchNum = '2'; |
| element._paramsChanged(value); |
| assert.isFalse(reloadStub.calledTwice); |
| assert.isTrue(reloadPatchDependentStub.calledOnce); |
| assert.isTrue(relatedClearSpy.calledOnce); |
| }); |
| |
| test('reload entire page when patchRange doesnt change', function() { |
| var reloadStub = sandbox.stub(element, '_reload', |
| function() { return Promise.resolve(); }); |
| |
| var value = { |
| view: 'gr-change-view', |
| }; |
| element._paramsChanged(value); |
| assert.isTrue(reloadStub.calledOnce); |
| element._initialLoadComplete = true; |
| element._paramsChanged(value); |
| assert.isTrue(reloadStub.calledTwice); |
| }); |
| |
| test('include base patch when not parent', function() { |
| element._changeNum = '42'; |
| element._patchRange = { |
| basePatchNum: '2', |
| patchNum: '3', |
| }; |
| element._change = { |
| change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca', |
| revisions: { |
| rev2: {_number: 2}, |
| rev1: {_number: 1}, |
| rev13: {_number: 13}, |
| rev3: {_number: 3}, |
| }, |
| status: 'NEW', |
| labels: {}, |
| }; |
| |
| element._changePatchNum(13); |
| assert(showStub.lastCall.calledWithExactly('/c/42/2..13')); |
| |
| element._patchRange.basePatchNum = 'PARENT'; |
| |
| element._changePatchNum(3); |
| assert(showStub.lastCall.calledWithExactly('/c/42/3')); |
| }); |
| |
| test('related changes are updated and new patch selected after rebase', |
| function(done) { |
| element._changeNum = '42'; |
| sandbox.stub(element, 'computeLatestPatchNum', function() { |
| return 1; |
| }); |
| sandbox.stub(element, '_reload', |
| function() { return Promise.resolve(); }); |
| var e = {detail: {action: 'rebase'}}; |
| element._handleReloadChange(e).then(function() { |
| assert.isTrue(showStub.lastCall.calledWithExactly('/c/42')); |
| done(); |
| }); |
| }); |
| |
| test('related changes are not updated after other action', function(done) { |
| sandbox.stub(element, '_reload', |
| function() { return Promise.resolve(); }); |
| sandbox.stub(element, '_updateSelected'); |
| sandbox.stub(element.$.relatedChanges, 'reload'); |
| var e = {detail: {action: 'abandon'}}; |
| element._handleReloadChange(e).then(function() { |
| assert.isFalse(showStub.called); |
| done(); |
| }); |
| }); |
| |
| test('change status new', function() { |
| element._changeNum = '1'; |
| element._patchRange = { |
| basePatchNum: 'PARENT', |
| patchNum: 1, |
| }; |
| element._change = { |
| change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca', |
| revisions: { |
| rev1: {_number: 1}, |
| }, |
| current_revision: 'rev1', |
| status: 'NEW', |
| labels: {}, |
| }; |
| var status = element._computeChangeStatus(element._change, '1'); |
| assert.equal(status, ''); |
| }); |
| |
| test('change status draft', function() { |
| element._changeNum = '1'; |
| element._patchRange = { |
| basePatchNum: 'PARENT', |
| patchNum: 1, |
| }; |
| element._change = { |
| change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca', |
| revisions: { |
| rev1: {_number: 1}, |
| }, |
| current_revision: 'rev1', |
| status: 'DRAFT', |
| labels: {}, |
| }; |
| var status = element._computeChangeStatus(element._change, '1'); |
| assert.equal(status, 'Draft'); |
| }); |
| |
| test('change status merged', function() { |
| element._changeNum = '1'; |
| element._patchRange = { |
| basePatchNum: 'PARENT', |
| patchNum: 1, |
| }; |
| element._change = { |
| change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca', |
| revisions: { |
| rev1: {_number: 1}, |
| }, |
| current_revision: 'rev1', |
| status: element.ChangeStatus.MERGED, |
| labels: {}, |
| }; |
| var status = element._computeChangeStatus(element._change, '1'); |
| assert.equal(status, 'Merged'); |
| }); |
| |
| test('revision status draft', function() { |
| element._changeNum = '1'; |
| element._patchRange = { |
| basePatchNum: 'PARENT', |
| patchNum: 1, |
| }; |
| element._change = { |
| change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca', |
| revisions: { |
| rev1: {_number: 1}, |
| rev2: { |
| _number: 2, |
| draft: true, |
| }, |
| }, |
| current_revision: 'rev1', |
| status: 'NEW', |
| labels: {}, |
| }; |
| var status = element._computeChangeStatus(element._change, '2'); |
| assert.equal(status, 'Draft'); |
| }); |
| |
| test('_computeMergedCommitInfo', function() { |
| var dummyRevs = { |
| 1: {commit: {commit: 1}}, |
| 2: {commit: {}}, |
| }; |
| assert.deepEqual(element._computeMergedCommitInfo(0, dummyRevs), {}); |
| assert.deepEqual(element._computeMergedCommitInfo(1, dummyRevs), |
| dummyRevs[1].commit); |
| |
| // Regression test for issue 5337. |
| var commit = element._computeMergedCommitInfo(2, dummyRevs); |
| assert.notDeepEqual(commit, dummyRevs[2]); |
| assert.deepEqual(commit, {commit: 2}); |
| }); |
| |
| test('get latest revision', function() { |
| var change = { |
| revisions: { |
| rev1: {_number: 1}, |
| rev3: {_number: 3}, |
| }, |
| current_revision: 'rev3', |
| }; |
| assert.equal(element._getLatestRevisionSHA(change), 'rev3'); |
| change = { |
| revisions: { |
| rev1: {_number: 1}, |
| }, |
| }; |
| assert.equal(element._getLatestRevisionSHA(change), 'rev1'); |
| }); |
| |
| test('show commit message edit button', function() { |
| var _change = { |
| status: element.ChangeStatus.MERGED, |
| }; |
| assert.isTrue(element._computeHideEditCommitMessage(false, false, {})); |
| assert.isTrue(element._computeHideEditCommitMessage(true, true, {})); |
| assert.isTrue(element._computeHideEditCommitMessage(false, true, {})); |
| assert.isFalse(element._computeHideEditCommitMessage(true, false, {})); |
| assert.isTrue(element._computeHideEditCommitMessage(true, false, |
| _change)); |
| }); |
| |
| test('_computeChangeIdCommitMessageError', function() { |
| var commitMessage = |
| 'Change-Id: I4ce18b2395bca69d7a9aa48bf4554faa56282483'; |
| var change = {change_id: 'I4ce18b2395bca69d7a9aa48bf4554faa56282483'}; |
| assert.equal( |
| element._computeChangeIdCommitMessageError(commitMessage, change), |
| null); |
| |
| change = {change_id: 'I4ce18b2395bca69d7a9aa48bf4554faa56282484'}; |
| assert.equal( |
| element._computeChangeIdCommitMessageError(commitMessage, change), |
| 'mismatch'); |
| |
| commitMessage = 'This is the greatest change.'; |
| assert.equal( |
| element._computeChangeIdCommitMessageError(commitMessage, change), |
| 'missing'); |
| }); |
| |
| test('multiple change Ids in commit message picks last', function() { |
| var commitMessage = [ |
| 'Change-Id: I4ce18b2395bca69d7a9aa48bf4554faa56282484', |
| 'Change-Id: I4ce18b2395bca69d7a9aa48bf4554faa56282483', |
| ].join('\n'); |
| var change = {change_id: 'I4ce18b2395bca69d7a9aa48bf4554faa56282483'}; |
| assert.equal( |
| element._computeChangeIdCommitMessageError(commitMessage, change), |
| null); |
| change = {change_id: 'I4ce18b2395bca69d7a9aa48bf4554faa56282484'}; |
| assert.equal( |
| element._computeChangeIdCommitMessageError(commitMessage, change), |
| 'mismatch'); |
| }); |
| |
| test('does not count change Id that starts mid line', function() { |
| var commitMessage = [ |
| 'Change-Id: I4ce18b2395bca69d7a9aa48bf4554faa56282484', |
| 'Change-Id: I4ce18b2395bca69d7a9aa48bf4554faa56282483', |
| ].join(' and '); |
| var change = {change_id: 'I4ce18b2395bca69d7a9aa48bf4554faa56282484'}; |
| assert.equal( |
| element._computeChangeIdCommitMessageError(commitMessage, change), |
| null); |
| change = {change_id: 'I4ce18b2395bca69d7a9aa48bf4554faa56282483'}; |
| assert.equal( |
| element._computeChangeIdCommitMessageError(commitMessage, change), |
| 'mismatch'); |
| }); |
| |
| test('_computeTitleAttributeWarning', function() { |
| var changeIdCommitMessageError = 'missing'; |
| assert.equal( |
| element._computeTitleAttributeWarning(changeIdCommitMessageError), |
| 'No Change-Id in commit message'); |
| |
| var changeIdCommitMessageError = 'mismatch'; |
| assert.equal( |
| element._computeTitleAttributeWarning(changeIdCommitMessageError), |
| 'Change-Id mismatch'); |
| }); |
| |
| test('_computeChangeIdClass', function() { |
| var changeIdCommitMessageError = 'missing'; |
| assert.equal( |
| element._computeChangeIdClass(changeIdCommitMessageError), ''); |
| |
| var changeIdCommitMessageError = 'mismatch'; |
| assert.equal( |
| element._computeChangeIdClass(changeIdCommitMessageError), 'warning'); |
| }); |
| |
| test('topic is coalesced to null', function(done) { |
| sandbox.stub(element, '_changeChanged'); |
| sandbox.stub(element.$.restAPI, 'getChangeDetail', function() { |
| return Promise.resolve({ |
| id: '123456789', |
| labels: {}, |
| current_revision: 'foo', |
| revisions: {foo: {commit: {}}}, |
| }); |
| }); |
| |
| element._getChangeDetail().then(function() { |
| assert.isNull(element._change.topic); |
| done(); |
| }); |
| }); |
| |
| test('commit sha is populated from getChangeDetail', function(done) { |
| sandbox.stub(element, '_changeChanged'); |
| sandbox.stub(element.$.restAPI, 'getChangeDetail', function() { |
| return Promise.resolve({ |
| id: '123456789', |
| labels: {}, |
| current_revision: 'foo', |
| revisions: {foo: {commit: {}}}, |
| }); |
| }); |
| |
| element._getChangeDetail().then(function() { |
| assert.equal('foo', element._commitInfo.commit); |
| done(); |
| }); |
| }); |
| |
| test('reply dialog focus can be controlled', function() { |
| var FocusTarget = element.$.replyDialog.FocusTarget; |
| var openStub = sandbox.stub(element, '_openReplyDialog'); |
| |
| var e = {detail: {}}; |
| element._handleShowReplyDialog(e); |
| assert(openStub.lastCall.calledWithExactly(FocusTarget.REVIEWERS), |
| '_openReplyDialog should have been passed REVIEWERS'); |
| |
| e.detail.value = {ccsOnly: true}; |
| element._handleShowReplyDialog(e); |
| assert(openStub.lastCall.calledWithExactly(FocusTarget.CCS), |
| '_openReplyDialog should have been passed CCS'); |
| }); |
| |
| test('class is applied to file list on old patch set', function() { |
| var allPatchSets = [{num: 1}, {num: 2}, {num: 4}]; |
| assert.equal(element._computePatchInfoClass('1', allPatchSets), |
| 'patchInfo--oldPatchSet'); |
| assert.equal(element._computePatchInfoClass('2', allPatchSets), |
| 'patchInfo--oldPatchSet'); |
| assert.equal(element._computePatchInfoClass('4', allPatchSets), ''); |
| }); |
| |
| test('getUrlParameter functionality', function() { |
| var locationStub = sandbox.stub(element, '_getLocationSearch'); |
| |
| locationStub.returns('?test'); |
| assert.equal(element._getUrlParameter('test'), 'test'); |
| locationStub.returns('?test2=12&test=3'); |
| assert.equal(element._getUrlParameter('test'), 'test'); |
| locationStub.returns(''); |
| assert.isNull(element._getUrlParameter('test')); |
| locationStub.returns('?'); |
| assert.isNull(element._getUrlParameter('test')); |
| locationStub.returns('?test2'); |
| assert.isNull(element._getUrlParameter('test')); |
| |
| }); |
| |
| test('revert dialog opened with revert param', function(done) { |
| sandbox.stub(element.$.restAPI, 'getLoggedIn', function() { |
| return Promise.resolve(true); |
| }); |
| sandbox.stub(Gerrit, 'awaitPluginsLoaded', function() { |
| return Promise.resolve(); |
| }); |
| |
| element._patchRange = { |
| basePatchNum: 'PARENT', |
| patchNum: 2, |
| }; |
| element._change = { |
| change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca', |
| revisions: { |
| rev1: {_number: 1}, |
| }, |
| current_revision: 'rev1', |
| status: element.ChangeStatus.MERGED, |
| labels: {}, |
| actions: {}, |
| }; |
| |
| var urlParamStub = sandbox.stub(element, '_getUrlParameter', |
| function(param) { |
| assert.equal(param, 'revert'); |
| return param; |
| }); |
| |
| var revertDialogStub = sandbox.stub(element.$.actions, 'showRevertDialog', |
| done); |
| |
| element._maybeShowRevertDialog(); |
| assert.isTrue(Gerrit.awaitPluginsLoaded.called); |
| }); |
| |
| suite('scroll related tests', function() { |
| test('document scrolling calls function to set scroll height', |
| function(done) { |
| var originalHeight = document.body.scrollHeight; |
| var scrollStub = sandbox.stub(element, '_handleScroll', |
| function() { |
| assert.isTrue(scrollStub.called); |
| document.body.style.height = |
| originalHeight + 'px'; |
| scrollStub.restore(); |
| done(); |
| }); |
| document.body.style.height = '10000px'; |
| document.body.scrollTop = TEST_SCROLL_TOP_PX; |
| element._handleScroll(); |
| }); |
| |
| test('history is loaded correctly', function() { |
| history.replaceState( |
| { |
| scrollTop: 100, |
| path: location.pathname, |
| }, |
| location.pathname); |
| |
| var reloadStub = sandbox.stub(element, '_reload', |
| function() { |
| // When element is reloaded, ensure that the history |
| // state has the scrollTop set earlier. This will then |
| // be reset. |
| assert.isTrue(history.state.scrollTop == 100); |
| return Promise.resolve({}); |
| }); |
| |
| // simulate reloading component, which is done when route |
| // changes to match a regex of change view type. |
| element._paramsChanged({view: 'gr-change-view'}); |
| }); |
| }); |
| |
| suite('reply dialog tests', function() { |
| setup(function() { |
| sandbox.stub(element.$.replyDialog, '_draftChanged'); |
| }); |
| |
| test('reply from comment adds quote text', function() { |
| var e = {detail: {message: {message: 'quote text'}}}; |
| element._handleMessageReply(e); |
| assert.equal(element.$.replyDialog.draft, '> quote text\n\n'); |
| assert.equal(element.$.replyDialog.quote, '> quote text\n\n'); |
| }); |
| |
| test('reply from comment replaces quote text', function() { |
| element.$.replyDialog.draft = '> old quote text\n\n some draft text'; |
| element.$.replyDialog.quote = '> old quote text\n\n'; |
| var e = {detail: {message: {message: 'quote text'}}}; |
| element._handleMessageReply(e); |
| assert.equal(element.$.replyDialog.draft, '> quote text\n\n'); |
| assert.equal(element.$.replyDialog.quote, '> quote text\n\n'); |
| }); |
| |
| test('reply from same comment preserves quote text', function() { |
| element.$.replyDialog.draft = '> quote text\n\n some draft text'; |
| element.$.replyDialog.quote = '> quote text\n\n'; |
| var e = {detail: {message: {message: 'quote text'}}}; |
| element._handleMessageReply(e); |
| assert.equal(element.$.replyDialog.draft, |
| '> quote text\n\n some draft text'); |
| assert.equal(element.$.replyDialog.quote, '> quote text\n\n'); |
| }); |
| |
| test('reply from top of page contains previous draft', function() { |
| var div = document.createElement('div'); |
| element.$.replyDialog.draft = '> quote text\n\n some draft text'; |
| element.$.replyDialog.quote = '> quote text\n\n'; |
| var e = {target: div, preventDefault: sandbox.spy()}; |
| element._handleReplyTap(e); |
| assert.equal(element.$.replyDialog.draft, |
| '> quote text\n\n some draft text'); |
| assert.equal(element.$.replyDialog.quote, '> quote text\n\n'); |
| }); |
| }); |
| |
| test('reply button is disabled until server config is loaded', function() { |
| assert.isTrue(element._replyDisabled); |
| element.serverConfig = {}; |
| assert.isFalse(element._replyDisabled); |
| }); |
| |
| suite('commit message expand/collapse', function() { |
| test('commitCollapseToggle hidden for short commit message', function() { |
| element._latestCommitMessage = ''; |
| assert.isTrue(element.$.commitCollapseToggle.hasAttribute('hidden')); |
| }); |
| |
| test('commitCollapseToggle shown for long commit message', function() { |
| element._latestCommitMessage = _.times(31, String).join('\n'); |
| assert.isFalse(element.$.commitCollapseToggle.hasAttribute('hidden')); |
| }); |
| |
| test('commitCollapseToggle functions', function() { |
| element._latestCommitMessage = _.times(31, String).join('\n'); |
| assert.isTrue(element._commitCollapsed); |
| assert.isTrue( |
| element.$.commitMessage.classList.contains('collapsed')); |
| MockInteractions.tap(element.$.commitCollapseToggleButton); |
| assert.isFalse(element._commitCollapsed); |
| assert.isFalse( |
| element.$.commitMessage.classList.contains('collapsed')); |
| }); |
| }); |
| |
| suite('related changes expand/collapse', function() { |
| var updateHeightSpy; |
| setup(function() { |
| updateHeightSpy = sandbox.spy(element, '_updateRelatedChangeMaxHeight'); |
| }); |
| |
| test('relatedChangesToggle shown height greater than changeInfo height', |
| function() { |
| assert.isTrue(element.$.relatedChangesToggle.hasAttribute('hidden')); |
| |
| sandbox.stub(element, '_getOffsetHeight', function() { |
| return 50; |
| }); |
| |
| sandbox.stub(element, '_getScrollHeight', function() { |
| return 60; |
| }); |
| element._relatedChangesLoading = false; |
| assert.isFalse(element.$.relatedChangesToggle.hasAttribute('hidden')); |
| assert.equal(updateHeightSpy.callCount, 1); |
| }); |
| |
| test('relatedChangesToggle hidden height less than changeInfo height', |
| function() { |
| assert.isTrue(element.$.relatedChangesToggle.hasAttribute('hidden')); |
| sandbox.stub(element, '_getOffsetHeight', function() { |
| return 50; |
| }); |
| |
| sandbox.stub(element, '_getScrollHeight', function() { |
| return 40; |
| }); |
| element._relatedChangesLoading = false; |
| assert.isTrue(element.$.relatedChangesToggle.hasAttribute('hidden')); |
| assert.equal(updateHeightSpy.callCount, 1); |
| }); |
| |
| test('relatedChangesToggle functions', function() { |
| sandbox.stub(element, '_getOffsetHeight', function() { |
| return 50; |
| }); |
| |
| sandbox.stub(element, '_getScrollHeight', function() { |
| return 60; |
| }); |
| element._relatedChangesLoading = false; |
| assert.isTrue(element._relatedChangesCollapsed); |
| assert.isTrue( |
| element.$.relatedChanges.classList.contains('collapsed')); |
| MockInteractions.tap(element.$.relatedChangesToggleButton); |
| assert.isFalse(element._relatedChangesCollapsed); |
| assert.isFalse( |
| element.$.relatedChanges.classList.contains('collapsed')); |
| }); |
| |
| test('_updateRelatedChangeMaxHeight without commit toggle', function() { |
| sandbox.stub(element, '_getOffsetHeight', function() { |
| return 50; |
| }); |
| |
| sandbox.stub(element, '_getLineHeight', function() { |
| return 12; |
| }); |
| |
| // 50 (existing height) - 24 (extra height) = 26 (adjusted height). |
| // 50 (existing height) % 12 (line height) = 2 (remainder). |
| // 26 (adjusted height) - 2 (remainder) = 24 (max height to set). |
| |
| element._updateRelatedChangeMaxHeight(); |
| assert.equal(element.customStyle['--relation-chain-max-height'], |
| '24px'); |
| assert.equal(element.customStyle['--related-change-btn-top-padding'], |
| undefined); |
| }); |
| |
| test('_updateRelatedChangeMaxHeight with commit toggle', function() { |
| element._latestCommitMessage = _.times(31, String).join('\n'); |
| sandbox.stub(element, '_getOffsetHeight', function() { |
| return 50; |
| }); |
| |
| sandbox.stub(element, '_getLineHeight', function() { |
| return 12; |
| }); |
| |
| // 50 (existing height) % 12 (line height) = 2 (remainder). |
| // 50 (existing height) - 2 (remainder) = 48 (max height to set). |
| |
| element._updateRelatedChangeMaxHeight(); |
| assert.equal(element.customStyle['--relation-chain-max-height'], |
| '48px'); |
| assert.equal(element.customStyle['--related-change-btn-top-padding'], |
| '2px'); |
| }); |
| |
| suite('update checks', function() { |
| setup(function() { |
| sandbox.spy(element, '_startUpdateCheckTimer'); |
| sandbox.stub(element, 'async', function(f) { |
| // Only fire the async callback one time. |
| if (element.async.callCount > 1) { return; } |
| f.call(element); |
| }); |
| }); |
| |
| test('_startUpdateCheckTimer negative delay', function() { |
| sandbox.stub(element, 'fetchIsLatestKnown'); |
| |
| element.serverConfig = {change: {update_delay: -1}}; |
| |
| assert.isTrue(element._startUpdateCheckTimer.called); |
| assert.isFalse(element.fetchIsLatestKnown.called); |
| }); |
| |
| test('_startUpdateCheckTimer up-to-date', function() { |
| sandbox.stub(element, 'fetchIsLatestKnown', |
| function() { return Promise.resolve(true); }); |
| |
| element.serverConfig = {change: {update_delay: 12345}}; |
| |
| assert.isTrue(element._startUpdateCheckTimer.called); |
| assert.isTrue(element.fetchIsLatestKnown.called); |
| assert.equal(element.async.lastCall.args[1], 12345 * 1000); |
| }); |
| |
| test('_startUpdateCheckTimer out-of-date shows an alert', |
| function(done) { |
| sandbox.stub(element, 'fetchIsLatestKnown', |
| function() { return Promise.resolve(false); }); |
| element.addEventListener('show-alert', function() { |
| done(); |
| }); |
| element.serverConfig = {change: {update_delay: 12345}}; |
| }); |
| }); |
| }); |
| }); |
| </script> |