blob: 6aa7f7cf9d609cb1f358d588e19298262b93e0ea [file] [log] [blame]
/**
* @license
* Copyright (C) 2016 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';
import './gr-account-info';
import {SinonSpyMember, stubRestApi} from '../../../test/test-utils';
import {GrAccountInfo} from './gr-account-info';
import {AccountDetailInfo, ServerInfo} from '../../../types/common';
import {
createAccountWithIdNameAndEmail,
createPreferences,
createServerInfo,
} from '../../../test/test-data-generators';
import {IronInputElement} from '@polymer/iron-input';
import {SinonStubbedMember} from 'sinon/pkg/sinon-esm';
import {RestApiService} from '../../../services/gr-rest-api/gr-rest-api';
const basicFixture = fixtureFromElement('gr-account-info');
suite('gr-account-info tests', () => {
let element!: GrAccountInfo;
let account: AccountDetailInfo;
let config: ServerInfo;
function queryIronInput(selector: string): IronInputElement {
const input = element.root?.querySelector<IronInputElement>(selector);
if (!input) assert.fail(`<iron-input> with id ${selector} not found.`);
return input;
}
function valueOf(title: string): Element {
const sections = element.root?.querySelectorAll('section') ?? [];
let titleEl;
for (let i = 0; i < sections.length; i++) {
titleEl = sections[i].querySelector('.title');
if (titleEl?.textContent === title) {
const el = sections[i].querySelector('.value');
if (el) return el;
}
}
assert.fail(`element with title ${title} not found`);
}
setup(async () => {
account = createAccountWithIdNameAndEmail(123) as AccountDetailInfo;
config = createServerInfo();
stubRestApi('getAccount').returns(Promise.resolve(account));
stubRestApi('getConfig').returns(Promise.resolve(config));
stubRestApi('getPreferences').returns(Promise.resolve(createPreferences()));
element = basicFixture.instantiate();
await element.loadData();
await flush();
});
test('basic account info render', () => {
assert.isFalse(element._loading);
assert.equal(valueOf('ID').textContent, `${account._account_id}`);
assert.equal(valueOf('Email').textContent, account.email);
assert.equal(valueOf('Username').textContent, account.username);
});
test('full name render (immutable)', () => {
const section = element.$.nameSection;
const displaySpan = section.querySelectorAll('.value')[0];
const inputSpan = section.querySelectorAll('.value')[1];
assert.isFalse(element.nameMutable);
assert.isFalse(displaySpan.hasAttribute('hidden'));
assert.equal(displaySpan.textContent, account.name);
assert.isTrue(inputSpan.hasAttribute('hidden'));
});
test('full name render (mutable)', () => {
element.set('_serverConfig', {
auth: {editable_account_fields: ['FULL_NAME']},
});
const section = element.$.nameSection;
const displaySpan = section.querySelectorAll('.value')[0];
const inputSpan = section.querySelectorAll('.value')[1];
assert.isTrue(element.nameMutable);
assert.isTrue(displaySpan.hasAttribute('hidden'));
assert.equal(queryIronInput('#nameIronInput').bindValue, account.name);
assert.isFalse(inputSpan.hasAttribute('hidden'));
});
test('username render (immutable)', () => {
const section = element.$.usernameSection;
const displaySpan = section.querySelectorAll('.value')[0];
const inputSpan = section.querySelectorAll('.value')[1];
assert.isFalse(element.usernameMutable);
assert.isFalse(displaySpan.hasAttribute('hidden'));
assert.equal(displaySpan.textContent, account.username);
assert.isTrue(inputSpan.hasAttribute('hidden'));
});
test('username render (mutable)', () => {
element.set('_serverConfig', {
auth: {editable_account_fields: ['USER_NAME']},
});
element.set('_account.username', '');
element.set('_username', '');
const section = element.$.usernameSection;
const displaySpan = section.querySelectorAll('.value')[0];
const inputSpan = section.querySelectorAll('.value')[1];
assert.isTrue(element.usernameMutable);
assert.isTrue(displaySpan.hasAttribute('hidden'));
assert.equal(
queryIronInput('#usernameIronInput').bindValue,
account.username
);
assert.isFalse(inputSpan.hasAttribute('hidden'));
});
suite('account info edit', () => {
let nameChangedSpy: SinonSpyMember<typeof element._nameChanged>;
let usernameChangedSpy: SinonSpyMember<typeof element._usernameChanged>;
let statusChangedSpy: SinonSpyMember<typeof element._statusChanged>;
let nameStub: SinonStubbedMember<RestApiService['setAccountName']>;
let usernameStub: SinonStubbedMember<RestApiService['setAccountUsername']>;
let statusStub: SinonStubbedMember<RestApiService['setAccountStatus']>;
setup(() => {
nameChangedSpy = sinon.spy(element, '_nameChanged');
usernameChangedSpy = sinon.spy(element, '_usernameChanged');
statusChangedSpy = sinon.spy(element, '_statusChanged');
element.set('_serverConfig', {
auth: {editable_account_fields: ['FULL_NAME', 'USER_NAME']},
});
nameStub = stubRestApi('setAccountName').returns(Promise.resolve());
usernameStub = stubRestApi('setAccountUsername').returns(
Promise.resolve()
);
statusStub = stubRestApi('setAccountStatus').returns(Promise.resolve());
});
test('name', done => {
assert.isTrue(element.nameMutable);
assert.isFalse(element.hasUnsavedChanges);
element.set('_account.name', 'new name');
assert.isTrue(nameChangedSpy.called);
assert.isFalse(statusChangedSpy.called);
assert.isTrue(element.hasUnsavedChanges);
element.save().then(() => {
assert.isFalse(usernameStub.called);
assert.isTrue(nameStub.called);
assert.isFalse(statusStub.called);
nameStub.lastCall.returnValue.then(() => {
assert.equal(nameStub.lastCall.args[0], 'new name');
done();
});
});
});
test('username', done => {
element.set('_account.username', '');
element._hasUsernameChange = false;
assert.isTrue(element.usernameMutable);
element.set('_username', 'new username');
assert.isTrue(usernameChangedSpy.called);
assert.isFalse(statusChangedSpy.called);
assert.isTrue(element.hasUnsavedChanges);
element.save().then(() => {
assert.isTrue(usernameStub.called);
assert.isFalse(nameStub.called);
assert.isFalse(statusStub.called);
usernameStub.lastCall.returnValue.then(() => {
assert.equal(usernameStub.lastCall.args[0], 'new username');
done();
});
});
});
test('status', done => {
assert.isFalse(element.hasUnsavedChanges);
element.set('_account.status', 'new status');
assert.isFalse(nameChangedSpy.called);
assert.isTrue(statusChangedSpy.called);
assert.isTrue(element.hasUnsavedChanges);
element.save().then(() => {
assert.isFalse(usernameStub.called);
assert.isTrue(statusStub.called);
assert.isFalse(nameStub.called);
statusStub.lastCall.returnValue.then(() => {
assert.equal(statusStub.lastCall.args[0], 'new status');
done();
});
});
});
});
suite('edit name and status', () => {
let nameChangedSpy: SinonSpyMember<typeof element._nameChanged>;
let statusChangedSpy: SinonSpyMember<typeof element._statusChanged>;
let nameStub: SinonStubbedMember<RestApiService['setAccountName']>;
let statusStub: SinonStubbedMember<RestApiService['setAccountStatus']>;
setup(() => {
nameChangedSpy = sinon.spy(element, '_nameChanged');
statusChangedSpy = sinon.spy(element, '_statusChanged');
element.set('_serverConfig', {
auth: {editable_account_fields: ['FULL_NAME']},
});
nameStub = stubRestApi('setAccountName').returns(Promise.resolve());
statusStub = stubRestApi('setAccountStatus').returns(Promise.resolve());
stubRestApi('setAccountUsername').returns(Promise.resolve());
});
test('set name and status', done => {
assert.isTrue(element.nameMutable);
assert.isFalse(element.hasUnsavedChanges);
element.set('_account.name', 'new name');
assert.isTrue(nameChangedSpy.called);
element.set('_account.status', 'new status');
assert.isTrue(statusChangedSpy.called);
assert.isTrue(element.hasUnsavedChanges);
element.save().then(() => {
assert.isTrue(statusStub.called);
assert.isTrue(nameStub.called);
assert.equal(nameStub.lastCall.args[0], 'new name');
assert.equal(statusStub.lastCall.args[0], 'new status');
done();
});
});
});
suite('set status but read name', () => {
let statusChangedSpy: SinonSpyMember<typeof element._statusChanged>;
let statusStub: SinonStubbedMember<RestApiService['setAccountStatus']>;
setup(() => {
statusChangedSpy = sinon.spy(element, '_statusChanged');
element.set('_serverConfig', {auth: {editable_account_fields: []}});
statusStub = stubRestApi('setAccountStatus').returns(Promise.resolve());
});
test('read full name but set status', done => {
const section = element.$.nameSection;
const displaySpan = section.querySelectorAll('.value')[0];
const inputSpan = section.querySelectorAll('.value')[1];
assert.isFalse(element.nameMutable);
assert.isFalse(element.hasUnsavedChanges);
assert.isFalse(displaySpan.hasAttribute('hidden'));
assert.equal(displaySpan.textContent, account.name);
assert.isTrue(inputSpan.hasAttribute('hidden'));
element.set('_account.status', 'new status');
assert.isTrue(statusChangedSpy.called);
assert.isTrue(element.hasUnsavedChanges);
element.save().then(() => {
assert.isTrue(statusStub.called);
statusStub.lastCall.returnValue.then(() => {
assert.equal(statusStub.lastCall.args[0], 'new status');
done();
});
});
});
});
test('_usernameChanged compares usernames with loose equality', () => {
element._account = {};
element._username = '';
element._hasUsernameChange = false;
element._loading = false;
// _usernameChanged is an observer, but call it here after setting
// _hasUsernameChange in the test to force recomputation.
element._usernameChanged();
flush();
assert.isFalse(element._hasUsernameChange);
element.set('_username', 'test');
flush();
assert.isTrue(element._hasUsernameChange);
});
test('_hideAvatarChangeUrl', () => {
assert.equal(element._hideAvatarChangeUrl(''), 'hide');
assert.equal(element._hideAvatarChangeUrl('https://example.com'), '');
});
});