blob: d691e87b71463f9f29cce9392f6d755b73f1b521 [file] [log] [blame]
/**
* @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.
*/
import '../../../test/common-test-setup-karma.js';
import './gr-file-list-header.js';
import {FilesExpandedState} from '../gr-file-list-constants.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
import {generateChange} from '../../../test/test-utils.js';
import 'lodash/lodash.js';
const basicFixture = fixtureFromElement('gr-file-list-header');
suite('gr-file-list-header tests', () => {
let element;
setup(() => {
stub('gr-rest-api-interface', {
getConfig() { return Promise.resolve({test: 'config'}); },
getAccount() { return Promise.resolve(null); },
_fetchSharedCacheURL() { return Promise.resolve({}); },
});
element = basicFixture.instantiate();
});
teardown(done => {
flush(() => {
done();
});
});
test('Diff preferences hidden when no prefs or diffPrefsDisabled', () => {
element.diffPrefsDisabled = true;
flush();
assert.isTrue(element.$.diffPrefsContainer.hidden);
element.diffPrefsDisabled = false;
flush();
assert.isTrue(element.$.diffPrefsContainer.hidden);
element.diffPrefsDisabled = true;
element.diffPrefs = {font_size: '12'};
flush();
assert.isTrue(element.$.diffPrefsContainer.hidden);
element.diffPrefsDisabled = false;
flush();
assert.isFalse(element.$.diffPrefsContainer.hidden);
});
test('_computeDescriptionReadOnly', () => {
element.loggedIn = false;
element.change = {owner: {_account_id: 1}};
element.account = {_account_id: 1};
assert.equal(element._descriptionReadOnly, true);
element.loggedIn = true;
element.change = {owner: {_account_id: 0}};
element.account = {_account_id: 1};
assert.equal(element._descriptionReadOnly, true);
element.loggedIn = true;
element.change = {owner: {_account_id: 1}};
element.account = {_account_id: 1};
assert.equal(element._descriptionReadOnly, false);
});
test('_computeDescriptionPlaceholder', () => {
assert.equal(element._computeDescriptionPlaceholder(true),
'No patchset description');
assert.equal(element._computeDescriptionPlaceholder(false),
'Add patchset description');
});
test('description editing', () => {
const putDescStub = sinon.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.owner = {_account_id: 1};
element.loggedIn = true;
flush();
// The element has a description, so the account chip should be visible
element.owner = {_account_id: 1};
// and the description label should not exist.
const chip = element.root.querySelector('#descriptionChip');
let label = 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, '');
flush();
// The editable label should now be visible and the chip hidden.
label = 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();
flush();
// 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(() => {
flush();
// 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;
flush();
sinon.stub(element, '_expandAllDiffs');
MockInteractions.tap(element.root.querySelector(
'#expandBtn'));
assert.isTrue(element._expandAllDiffs.called);
});
test('collapseAllDiffs called when expand button clicked', () => {
element.shownFileCount = 1;
flush();
sinon.stub(element, '_collapseAllDiffs');
MockInteractions.tap(element.root.querySelector(
'#collapseBtn'));
assert.isTrue(element._collapseAllDiffs.called);
});
test('show/hide diffs disabled for large amounts of files', done => {
const computeSpy = sinon.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 = FilesExpandedState.SOME;
flush();
assert.notEqual(getComputedStyle(actions).display, 'none');
element.filesExpanded = FilesExpandedState.ALL;
flush();
assert.notEqual(getComputedStyle(actions).display, 'none');
element.filesExpanded = FilesExpandedState.NONE;
flush();
assert.equal(getComputedStyle(actions).display, 'none');
});
test('expand/collapse buttons are toggled correctly', () => {
element.shownFileCount = 10;
flush();
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 = FilesExpandedState.SOME;
flush();
assert.notEqual(getComputedStyle(expandBtn).display, 'none');
assert.equal(getComputedStyle(collapseBtn).display, 'none');
element.filesExpanded = FilesExpandedState.ALL;
flush();
assert.equal(getComputedStyle(expandBtn).display, 'none');
assert.notEqual(getComputedStyle(collapseBtn).display, 'none');
element.filesExpanded = FilesExpandedState.NONE;
flush();
assert.notEqual(getComputedStyle(expandBtn).display, 'none');
assert.equal(getComputedStyle(collapseBtn).display, 'none');
});
test('navigateToChange called when range select changes', () => {
const navigateToChangeStub = sinon.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;
element.allPatchSets = generateChange({revisionsCount: 2}).revisions;
flush();
assert.isFalse(isVisible(element.$.diffPrefsContainer));
assert.isFalse(isVisible(element.shadowRoot
.querySelector('.descriptionContainer')));
element.editMode = false;
flush();
assert.isTrue(isVisible(element.shadowRoot
.querySelector('.descriptionContainer')));
assert.isTrue(isVisible(element.$.diffPrefsContainer));
});
test('edit-controls visibility', () => {
element.editMode = false;
flush();
// on the first render, when editMode is false, editControls are not
// in the DOM to reduce size of DOM and make first render faster.
assert.isNull(element.shadowRoot
.querySelector('#editControls'));
element.editMode = true;
flush();
assert.isTrue(isVisible(element.shadowRoot
.querySelector('#editControls').parentElement));
element.editMode = false;
flush();
assert.isFalse(isVisible(element.shadowRoot
.querySelector('#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');
});
});
});