| <!DOCTYPE html> |
| <!-- |
| @license |
| Copyright (C) 2017 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"> |
| <meta charset="utf-8"> |
| <title>gr-file-list-header</title> |
| |
| <script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script> |
| |
| <script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script> |
| <script src="/components/wct-browser-legacy/browser.js"></script> |
| <script src="/node_modules/page/page.js"></script> |
| |
| <test-fixture id="basic"> |
| <template> |
| <gr-file-list-header></gr-file-list-header> |
| </template> |
| </test-fixture> |
| |
| <test-fixture id="blank"> |
| <template> |
| <div></div> |
| </template> |
| </test-fixture> |
| |
| <script type="module"> |
| import '../../../test/common-test-setup.js'; |
| import './gr-file-list-header.js'; |
| import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js'; |
| import {GrFileListConstants} from '../gr-file-list-constants.js'; |
| import {GerritNav} from '../../core/gr-navigation/gr-navigation.js'; |
| |
| suite('gr-file-list-header tests', () => { |
| let element; |
| let sandbox; |
| |
| setup(() => { |
| sandbox = sinon.sandbox.create(); |
| stub('gr-rest-api-interface', { |
| getConfig() { return Promise.resolve({test: 'config'}); }, |
| getAccount() { return Promise.resolve(null); }, |
| _fetchSharedCacheURL() { return Promise.resolve({}); }, |
| }); |
| element = fixture('basic'); |
| }); |
| |
| teardown(done => { |
| flush(() => { |
| sandbox.restore(); |
| done(); |
| }); |
| }); |
| |
| test('Diff preferences hidden when no prefs or diffPrefsDisabled', () => { |
| element.diffPrefsDisabled = true; |
| flushAsynchronousOperations(); |
| assert.isTrue(element.$.diffPrefsContainer.hidden); |
| |
| element.diffPrefsDisabled = false; |
| flushAsynchronousOperations(); |
| assert.isTrue(element.$.diffPrefsContainer.hidden); |
| |
| element.diffPrefsDisabled = true; |
| element.diffPrefs = {font_size: '12'}; |
| flushAsynchronousOperations(); |
| assert.isTrue(element.$.diffPrefsContainer.hidden); |
| |
| element.diffPrefsDisabled = false; |
| flushAsynchronousOperations(); |
| assert.isFalse(element.$.diffPrefsContainer.hidden); |
| }); |
| |
| test('_computeDescriptionReadOnly', () => { |
| 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', () => { |
| assert.equal(element._computeDescriptionPlaceholder(true), |
| 'No patchset description'); |
| assert.equal(element._computeDescriptionPlaceholder(false), |
| 'Add patchset description'); |
| }); |
| |
| test('description editing', () => { |
| const putDescStub = sandbox.stub(element.$.restAPI, 'setDescription') |
| .returns(Promise.resolve({ok: true})); |
| |
| element.changeNum = '42'; |
| element.basePatchNum = 'PARENT'; |
| element.patchNum = 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(); |
| |
| // The element has a description, so the account chip should be visible |
| // and the description label should not exist. |
| const chip = dom(element.root).querySelector('#descriptionChip'); |
| let label = dom(element.root).querySelector('#descriptionLabel'); |
| |
| assert.equal(chip.text, 'test'); |
| assert.isNotOk(label); |
| |
| // Simulate tapping the remove button, but call function directly so that |
| // can determine what happens after the promise is resolved. |
| return element._handleDescriptionRemoved() |
| .then(() => { |
| // The API stub should be called with an empty string for the new |
| // description. |
| assert.equal(putDescStub.lastCall.args[2], ''); |
| assert.equal(element.change.revisions.rev1.description, ''); |
| |
| flushAsynchronousOperations(); |
| // The editable label should now be visible and the chip hidden. |
| label = dom(element.root).querySelector('#descriptionLabel'); |
| assert.isOk(label); |
| assert.equal(getComputedStyle(chip).display, 'none'); |
| assert.notEqual(getComputedStyle(label).display, 'none'); |
| assert.isFalse(label.readOnly); |
| // Edit the label to have a new value of test2, and save. |
| label.editing = true; |
| label._inputText = 'test2'; |
| label._save(); |
| flushAsynchronousOperations(); |
| // The API stub should be called with an `test2` for the new |
| // description. |
| assert.equal(putDescStub.callCount, 2); |
| assert.equal(putDescStub.lastCall.args[2], 'test2'); |
| }) |
| .then(() => { |
| flushAsynchronousOperations(); |
| // The chip should be visible again, and the label hidden. |
| assert.equal(element.change.revisions.rev1.description, 'test2'); |
| assert.equal(getComputedStyle(label).display, 'none'); |
| assert.notEqual(getComputedStyle(chip).display, 'none'); |
| }); |
| }); |
| |
| test('expandAllDiffs called when expand button clicked', () => { |
| element.shownFileCount = 1; |
| flushAsynchronousOperations(); |
| sandbox.stub(element, '_expandAllDiffs'); |
| MockInteractions.tap(dom(element.root).querySelector( |
| '#expandBtn')); |
| assert.isTrue(element._expandAllDiffs.called); |
| }); |
| |
| test('collapseAllDiffs called when expand button clicked', () => { |
| element.shownFileCount = 1; |
| flushAsynchronousOperations(); |
| sandbox.stub(element, '_collapseAllDiffs'); |
| MockInteractions.tap(dom(element.root).querySelector( |
| '#collapseBtn')); |
| assert.isTrue(element._collapseAllDiffs.called); |
| }); |
| |
| test('show/hide diffs disabled for large amounts of files', done => { |
| const computeSpy = sandbox.spy(element, '_fileListActionsVisible'); |
| element._files = []; |
| element.changeNum = '42'; |
| element.basePatchNum = 'PARENT'; |
| element.patchNum = '2'; |
| element.shownFileCount = 1; |
| flush(() => { |
| assert.isTrue(computeSpy.lastCall.returnValue); |
| _.times(element._maxFilesForBulkActions + 1, () => { |
| element.shownFileCount = element.shownFileCount + 1; |
| }); |
| assert.isFalse(computeSpy.lastCall.returnValue); |
| done(); |
| }); |
| }); |
| |
| test('fileViewActions are properly hidden', () => { |
| const actions = element.shadowRoot |
| .querySelector('.fileViewActions'); |
| assert.equal(getComputedStyle(actions).display, 'none'); |
| element.filesExpanded = GrFileListConstants.FilesExpandedState.SOME; |
| flushAsynchronousOperations(); |
| assert.notEqual(getComputedStyle(actions).display, 'none'); |
| element.filesExpanded = GrFileListConstants.FilesExpandedState.ALL; |
| flushAsynchronousOperations(); |
| assert.notEqual(getComputedStyle(actions).display, 'none'); |
| element.filesExpanded = GrFileListConstants.FilesExpandedState.NONE; |
| flushAsynchronousOperations(); |
| assert.equal(getComputedStyle(actions).display, 'none'); |
| }); |
| |
| test('expand/collapse buttons are toggled correctly', () => { |
| element.shownFileCount = 10; |
| flushAsynchronousOperations(); |
| const expandBtn = element.shadowRoot.querySelector('#expandBtn'); |
| const collapseBtn = element.shadowRoot.querySelector('#collapseBtn'); |
| assert.notEqual(getComputedStyle(expandBtn).display, 'none'); |
| assert.equal(getComputedStyle(collapseBtn).display, 'none'); |
| element.filesExpanded = GrFileListConstants.FilesExpandedState.SOME; |
| flushAsynchronousOperations(); |
| assert.notEqual(getComputedStyle(expandBtn).display, 'none'); |
| assert.equal(getComputedStyle(collapseBtn).display, 'none'); |
| element.filesExpanded = GrFileListConstants.FilesExpandedState.ALL; |
| flushAsynchronousOperations(); |
| assert.equal(getComputedStyle(expandBtn).display, 'none'); |
| assert.notEqual(getComputedStyle(collapseBtn).display, 'none'); |
| element.filesExpanded = GrFileListConstants.FilesExpandedState.NONE; |
| flushAsynchronousOperations(); |
| assert.notEqual(getComputedStyle(expandBtn).display, 'none'); |
| assert.equal(getComputedStyle(collapseBtn).display, 'none'); |
| }); |
| |
| test('navigateToChange called when range select changes', () => { |
| const navigateToChangeStub = sandbox.stub(GerritNav, 'navigateToChange'); |
| element.change = { |
| change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca', |
| revisions: { |
| rev2: {_number: 2}, |
| rev1: {_number: 1}, |
| rev13: {_number: 13}, |
| rev3: {_number: 3}, |
| }, |
| status: 'NEW', |
| labels: {}, |
| }; |
| element.basePatchNum = 1; |
| element.patchNum = 2; |
| |
| element._handlePatchChange({detail: {basePatchNum: 1, patchNum: 3}}); |
| assert.equal(navigateToChangeStub.callCount, 1); |
| assert.isTrue(navigateToChangeStub.lastCall |
| .calledWithExactly(element.change, 3, 1)); |
| }); |
| |
| test('class is applied to file list on old patch set', () => { |
| const allPatchSets = [{num: 4}, {num: 2}, {num: 1}]; |
| assert.equal(element._computePatchInfoClass('1', allPatchSets), |
| 'patchInfoOldPatchSet'); |
| assert.equal(element._computePatchInfoClass('2', allPatchSets), |
| 'patchInfoOldPatchSet'); |
| assert.equal(element._computePatchInfoClass('4', allPatchSets), ''); |
| }); |
| |
| suite('editMode behavior', () => { |
| setup(() => { |
| element.diffPrefsDisabled = false; |
| element.diffPrefs = {}; |
| }); |
| |
| const isVisible = el => { |
| assert.ok(el); |
| return getComputedStyle(el).getPropertyValue('display') !== 'none'; |
| }; |
| |
| test('patch specific elements', () => { |
| element.editMode = true; |
| sandbox.stub(element, 'computeLatestPatchNum').returns('2'); |
| flushAsynchronousOperations(); |
| |
| assert.isFalse(isVisible(element.$.diffPrefsContainer)); |
| assert.isFalse(isVisible(element.shadowRoot |
| .querySelector('.descriptionContainer'))); |
| |
| element.editMode = false; |
| flushAsynchronousOperations(); |
| |
| assert.isTrue(isVisible(element.shadowRoot |
| .querySelector('.descriptionContainer'))); |
| assert.isTrue(isVisible(element.$.diffPrefsContainer)); |
| }); |
| |
| test('edit-controls visibility', () => { |
| element.editMode = true; |
| flushAsynchronousOperations(); |
| assert.isTrue(isVisible(element.$.editControls.parentElement)); |
| |
| element.editMode = false; |
| flushAsynchronousOperations(); |
| assert.isFalse(isVisible(element.$.editControls.parentElement)); |
| }); |
| |
| test('_computeUploadHelpContainerClass', () => { |
| // Only show the upload helper button when an unmerged change is viewed |
| // by its owner. |
| const accountA = {_account_id: 1}; |
| const accountB = {_account_id: 2}; |
| assert.notInclude(element._computeUploadHelpContainerClass( |
| {owner: accountA}, accountA), 'hide'); |
| assert.include(element._computeUploadHelpContainerClass( |
| {owner: accountA}, accountB), 'hide'); |
| }); |
| }); |
| }); |
| </script> |