blob: d7acc617fc0d2cca73f4bd48e9e7ae68e47c1bb4 [file] [log] [blame]
/**
* @license
* Copyright 2020 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import '../../../test/common-test-setup-karma';
import './gr-endpoint-decorator';
import '../gr-endpoint-param/gr-endpoint-param';
import '../gr-endpoint-slot/gr-endpoint-slot';
import {fixture, html} from '@open-wc/testing-helpers';
import {
mockPromise,
queryAndAssert,
resetPlugins,
} from '../../../test/test-utils';
import {getPluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader';
import {GrEndpointDecorator} from './gr-endpoint-decorator';
import {PluginApi} from '../../../api/plugin';
import {GrEndpointParam} from '../gr-endpoint-param/gr-endpoint-param';
suite('gr-endpoint-decorator', () => {
let container: HTMLElement;
let plugin: PluginApi;
let decorationHook: any;
let decorationHookWithSlot: any;
let replacementHook: any;
let first: GrEndpointDecorator;
let second: GrEndpointDecorator;
let banana: GrEndpointDecorator;
setup(async () => {
resetPlugins();
container = await fixture(
html`<div>
<gr-endpoint-decorator name="first">
<gr-endpoint-param
name="first-param"
.value=${'barbar'}
></gr-endpoint-param>
<p>
<span>test slot</span>
<gr-endpoint-slot name="test"></gr-endpoint-slot>
</p>
</gr-endpoint-decorator>
<gr-endpoint-decorator name="second">
<gr-endpoint-param
name="second-param"
.value=${'foofoo'}
></gr-endpoint-param>
</gr-endpoint-decorator>
<gr-endpoint-decorator name="banana">
<gr-endpoint-param
name="banana-param"
.value=${'yes'}
></gr-endpoint-param>
</gr-endpoint-decorator>
</div>`
);
first = queryAndAssert<GrEndpointDecorator>(
container,
'gr-endpoint-decorator[name="first"]'
);
second = queryAndAssert<GrEndpointDecorator>(
container,
'gr-endpoint-decorator[name="second"]'
);
banana = queryAndAssert<GrEndpointDecorator>(
container,
'gr-endpoint-decorator[name="banana"]'
);
window.Gerrit.install(
p => {
plugin = p;
},
'0.1',
'http://some/plugin/url.js'
);
// Decoration
decorationHook = plugin.registerCustomComponent('first', 'some-module');
const decorationHookPromise = mockPromise();
decorationHook.onAttached(() => decorationHookPromise.resolve());
// Decoration with slot
decorationHookWithSlot = plugin.registerCustomComponent(
'first',
'some-module-2',
{slot: 'test'}
);
const decorationHookSlotPromise = mockPromise();
decorationHookWithSlot.onAttached(() =>
decorationHookSlotPromise.resolve()
);
// Replacement
replacementHook = plugin.registerCustomComponent('second', 'other-module', {
replace: true,
});
const replacementHookPromise = mockPromise();
replacementHook.onAttached(() => replacementHookPromise.resolve());
// Mimic all plugins loaded.
getPluginLoader().loadPlugins([]);
await decorationHookPromise;
await decorationHookSlotPromise;
await replacementHookPromise;
});
teardown(() => {
resetPlugins();
});
test('imports plugin-provided modules into endpoints', () => {
const endpoints = Array.from(
container.querySelectorAll('gr-endpoint-decorator')
);
assert.equal(endpoints.length, 3);
});
test('first decoration', () => {
const element = first;
const modules = Array.from(element.children).filter(
element => element.nodeName === 'SOME-MODULE'
);
assert.equal(modules.length, 1);
const [module] = modules;
assert.isOk(module);
assert.equal((module as any)['first-param'], 'barbar');
return decorationHook
.getLastAttached()
.then((element: any) => {
assert.strictEqual(element, module);
})
.then(() => {
element.remove();
assert.equal(decorationHook.getAllAttached().length, 0);
});
});
test('decoration with slot', () => {
const element = first;
const modules = [...element.querySelectorAll('some-module-2')];
assert.equal(modules.length, 1);
const [module] = modules;
assert.isOk(module);
assert.equal((module as any)['first-param'], 'barbar');
return decorationHookWithSlot
.getLastAttached()
.then((element: any) => {
assert.strictEqual(element, module);
})
.then(() => {
element.remove();
assert.equal(decorationHookWithSlot.getAllAttached().length, 0);
});
});
test('replacement', () => {
const element = second;
const module = Array.from(element.children).find(
element => element.nodeName === 'OTHER-MODULE'
);
assert.isOk(module);
assert.equal((module as any)['second-param'], 'foofoo');
return replacementHook
.getLastAttached()
.then((element: any) => {
assert.strictEqual(element, module);
})
.then(() => {
element.remove();
assert.equal(replacementHook.getAllAttached().length, 0);
});
});
test('late registration', async () => {
const bananaHook = plugin.registerCustomComponent('banana', 'noob-noob');
const bananaHookPromise = mockPromise();
bananaHook.onAttached(() => bananaHookPromise.resolve());
await bananaHookPromise;
const element = banana;
const module = Array.from(element.children).find(
element => element.nodeName === 'NOOB-NOOB'
);
assert.isOk(module);
});
test('two modules', async () => {
const bananaHook1 = plugin.registerCustomComponent('banana', 'mod-one');
const bananaHookPromise1 = mockPromise();
bananaHook1.onAttached(() => bananaHookPromise1.resolve());
await bananaHookPromise1;
const bananaHook = plugin.registerCustomComponent('banana', 'mod-two');
const bananaHookPromise2 = mockPromise();
bananaHook.onAttached(() => bananaHookPromise2.resolve());
await bananaHookPromise2;
const element = banana;
const module1 = Array.from(element.children).find(
element => element.nodeName === 'MOD-ONE'
);
assert.isOk(module1);
const module2 = Array.from(element.children).find(
element => element.nodeName === 'MOD-TWO'
);
assert.isOk(module2);
});
test('late param setup', async () => {
let element = banana;
const param = queryAndAssert<GrEndpointParam>(element, 'gr-endpoint-param');
param['value'] = undefined;
await param.updateComplete;
const bananaHook = plugin.registerCustomComponent('banana', 'noob-noob');
const bananaHookPromise = mockPromise();
bananaHook.onAttached(() => bananaHookPromise.resolve());
element = queryAndAssert<GrEndpointDecorator>(
container,
'gr-endpoint-decorator[name="banana"]'
);
let module = Array.from(element.children).find(
element => element.nodeName === 'NOOB-NOOB'
);
// Module waits for param to be defined.
assert.isNotOk(module);
const value = {abc: 'def'};
param.value = value;
await param.updateComplete;
await bananaHookPromise;
module = Array.from(element.children).find(
element => element.nodeName === 'NOOB-NOOB'
);
assert.isOk(module);
assert.strictEqual((module as any)['banana-param'], value);
});
test('param is bound', async () => {
const element = banana;
const param = queryAndAssert<GrEndpointParam>(element, 'gr-endpoint-param');
const value1 = {abc: 'def'};
const value2 = {def: 'abc'};
param.value = value1;
await param.updateComplete;
const bananaHook = plugin.registerCustomComponent('banana', 'noob-noob');
const bananaHookPromise = mockPromise();
bananaHook.onAttached(() => bananaHookPromise.resolve());
await bananaHookPromise;
const module = Array.from(element.children).find(
element => element.nodeName === 'NOOB-NOOB'
);
assert.isOk(module);
assert.strictEqual((module as any)['banana-param'], value1);
param.value = value2;
await param.updateComplete;
assert.strictEqual((module as any)['banana-param'], value2);
});
});