Skip to content

Commit

Permalink
refactor(compiler): avoid using au class to find targets (#1768)
Browse files Browse the repository at this point in the history
[skip ci]
  • Loading branch information
bigopon committed May 21, 2023
1 parent a0d39e9 commit 0d30998
Show file tree
Hide file tree
Showing 31 changed files with 767 additions and 1,069 deletions.
1 change: 1 addition & 0 deletions packages/__tests__/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ module.exports = {
'mocha/no-synchronous-tests': 'off',

'@typescript-eslint/no-unused-vars': ["warn", { "varsIgnorePattern": "^_", "argsIgnorePattern": "^_" }],
'@typescript-eslint/prefer-readonly': 'off',
'@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
Expand Down
10 changes: 4 additions & 6 deletions packages/__tests__/3-runtime-html/au-compose.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ describe('3-runtime-html/au-compose.spec.ts', function () {
assert.visibleTextEqual(appHost, 'Hello');
assert.html.innerEqual(
appHost,
'<au-compose class="au"><div>Hello</div></au-compose>'
'<au-compose><div>Hello</div></au-compose>'
);

assert.strictEqual(node, appHost.querySelector('au-compose'));
Expand Down Expand Up @@ -755,7 +755,7 @@ describe('3-runtime-html/au-compose.spec.ts', function () {
it('works with [multiple successive updates] + [activate<Promise>]', async function () {
const baseTimeout = 75;
let timeout = baseTimeout;
const { appHost, component, startPromise, tearDown } = createFixture(
const { appHost, component, startPromise, stop } = createFixture(
`\${message}<au-compose component.bind="{ activate, value: i }" template.bind="view" view-model.ref="auCompose" containerless>`,
class App {
public i = 0;
Expand Down Expand Up @@ -789,7 +789,7 @@ describe('3-runtime-html/au-compose.spec.ts', function () {
assert.strictEqual(appHost.textContent, `hello world38`);
assert.html.innerEqual(appHost, 'hello world<div>38</div>');

await tearDown();
void stop();
assert.strictEqual(appHost.textContent, '');
});
});
Expand Down Expand Up @@ -1044,7 +1044,7 @@ describe('3-runtime-html/au-compose.spec.ts', function () {
return this.host.animate([{ color: 'blue' }, { color: 'green' }], { duration: 50 }).finished;
}
});
const { component, startPromise, tearDown } = createFixture(
const { component, startPromise } = createFixture(
`<au-compose repeat.for="vm of components" component.bind="vm">`,
class App {
public message = 'Aurelia';
Expand All @@ -1071,8 +1071,6 @@ describe('3-runtime-html/au-compose.spec.ts', function () {

component.remove();
await new Promise(r => setTimeout(r, 150));

await tearDown();
});
}
});
62 changes: 31 additions & 31 deletions packages/__tests__/3-runtime-html/au-slot.spec.tsx

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -182,39 +182,39 @@ describe('3-runtime-html/binding-commands.throttle-debounce.spec.ts', function (
const receiver = component.receiver;
component.value = 1;

assert.strictEqual(receiver.className, 'au', 'target value pre #1');
assert.strictEqual(receiver.className, '', 'target value pre #1');
ctx.platform.domWriteQueue.flush();
assert.strictEqual(receiver.className, 'au', 'target value #1');
assert.strictEqual(receiver.className, '', 'target value #1');

component.value = false;

assert.strictEqual(receiver.className, 'au', 'target value pre #2');
assert.strictEqual(receiver.className, '', 'target value pre #2');
ctx.platform.domWriteQueue.flush();
assert.strictEqual(receiver.className, 'au', 'target value #2');
assert.strictEqual(receiver.className, '', 'target value #2');

component.value = true;

assert.strictEqual(receiver.className, 'au', 'target value pre #3');
assert.strictEqual(receiver.className, '', 'target value pre #3');
ctx.platform.domWriteQueue.flush();
assert.strictEqual(receiver.className, 'au', 'target value #3');
assert.strictEqual(receiver.className, '', 'target value #3');

ctx.platform.domWriteQueue.flush();
assert.strictEqual(receiver.className, 'au', 'target value #4');
assert.strictEqual(receiver.className, '', 'target value #4');

await ctx.platform.taskQueue.yield();
assert.strictEqual(receiver.className, 'au selected', 'target value pre #5');
assert.strictEqual(receiver.className, 'selected', 'target value pre #5');

component.value = false;
assert.strictEqual(receiver.className, 'au selected', 'target value pre #5');
assert.strictEqual(receiver.className, 'selected', 'target value pre #5');
ctx.platform.domWriteQueue.flush();
assert.strictEqual(receiver.className, 'au selected', 'target value #5');
assert.strictEqual(receiver.className, 'selected', 'target value #5');

ctx.platform.domWriteQueue.flush();
assert.strictEqual(receiver.className, 'au selected', 'target value #6');
assert.strictEqual(receiver.className, 'selected', 'target value #6');

ctx.platform.domWriteQueue.flush();
await ctx.platform.taskQueue.yield();
assert.strictEqual(receiver.className, 'au', 'target value #6');
assert.strictEqual(receiver.className, '', 'target value #6');

await au.stop();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
} from '@aurelia/testing';
import { isFirefox, isNode } from '../util.js';

describe('3-runtime-html/template-compiler.harmony.spec.ts', function () {
describe('3-runtime-html/custom-elements.harmony.spec.ts', function () {
interface IHarmoniousCompilationTestCase {
title: string;
template: string | HTMLElement;
Expand Down
45 changes: 19 additions & 26 deletions packages/__tests__/3-runtime-html/custom-elements.let.spec.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
import { delegateSyntax } from '@aurelia/compat-v1';
import { ILogger } from '@aurelia/kernel';
import { assert, createFixture } from '@aurelia/testing';

describe('3-runtime-html/custom-elements.let.spec.ts', function () {
for (const command of [
'from-view',
'two-way',
'trigger',
'delegate',
'one-time',
'trigger',
'capture',
'attr',
'to-view',
]) {
it(`throws on non .bind/.to-view: "${command}"`, async function () {
const { tearDown, start } = createFixture(`<let a.${command}="bc">`, class { }, [delegateSyntax], /* no start */false);

it(`throws on non .bind/.to-view: "${command}"`, function () {
let ex: Error;
try {
await start();
createFixture(`<let a.${command}="bc">`, class { });
} catch (e) {
ex = e;
// assert.includes(e.toString(), `Invalid command ${command} for <let>. Only to-view/bind supported.`);
Expand All @@ -29,30 +23,30 @@ describe('3-runtime-html/custom-elements.let.spec.ts', function () {
);
}
assert.instanceOf(ex, Error);
await tearDown();
});
}

for (const command of ['bind']) {
it(`camel-cases the target with binding command [${command}]`, async function () {
const { tearDown, appHost, startPromise } = createFixture(`<let my-prop.${command}="1"></let>\${myProp}`);
it(`camel-cases the target with binding command [${command}]`, function () {
const { assertText } = createFixture(`<let my-prop.${command}="1"></let>\${myProp}`);

await startPromise;
assert.visibleTextEqual(appHost, '1');
await tearDown();
assertText('1');
});
}

it('camel-cases the target with interpolation', async function () {
const { tearDown, appHost, startPromise } = createFixture(`<let my-prop="\${1}"></let>\${myProp}`);
it('removes <let> element', function () {
createFixture(`<let my-prop="\${1}"></let>\${myProp}`)
.assertHtml('1');
});

it('camel-cases the target with interpolation', function () {
const { assertText } = createFixture(`<let my-prop="\${1}"></let>\${myProp}`);

await startPromise;
assert.visibleTextEqual(appHost, '1');
await tearDown();
assertText('1');
});

it('works with, and warns when encountering literal', async function () {
const { ctx, tearDown, appHost, start } = createFixture(
it('works with, and warns when encountering literal', function () {
const { ctx, assertText, start } = createFixture(
`<let my-prop="1"></let>\${myProp}`,
class { myProp = 0; },
[],
Expand All @@ -66,13 +60,12 @@ describe('3-runtime-html/custom-elements.let.spec.ts', function () {
return fn.apply(logger, args);
})(logger.warn);

await start();
assert.visibleTextEqual(appHost, '1');
await tearDown();
void start();
assertText('1');
});

// //<let [to-binding-context] />
it('assigns to vm with <let to-binding-context>', async function () {
it('assigns to vm with <let to-binding-context>', function () {
const { component } = createFixture(
`<let to-binding-context full-name.bind="firstName + \` \` + lastName"></let>
<div>\${fullName}</div></template>`,
Expand Down
48 changes: 12 additions & 36 deletions packages/__tests__/3-runtime-html/dom.spec.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,25 @@
import { FragmentNodeSequence } from '@aurelia/runtime-html';
import { FragmentNodeSequence, isRenderLocation } from '@aurelia/runtime-html';
import { TestContext, assert } from '@aurelia/testing';

describe('3-runtime-html/dom.spec.ts', function () {
const ctx = TestContext.create();
let sut: FragmentNodeSequence;

const widthArr = [1, 2, 3];
describe('constructor', function () {
for (const width of widthArr) {
it(`should correctly assign children (depth=1,width=${width})`, function () {
const node = ctx.doc.createElement('div');
const fragment = createFragment(ctx, node, 0, 1, width);
sut = new FragmentNodeSequence(ctx.platform, fragment);
assert.strictEqual(sut.childNodes.length, width, `sut.childNodes.length`);
assert.strictEqual(sut.childNodes[0] === sut.firstChild, true, `sut.childNodes[0] === sut.firstChild`);
assert.strictEqual(sut.childNodes[width - 1] === sut.lastChild, true, `sut.childNodes[width - 1] === sut.lastChild`);
});
}
});
const depthArr = [0, 1, 2, 3];
describe('findTargets', function () {
for (const width of widthArr) {
for (const depth of depthArr) {
// note: these findTargets tests are quite redundant, but the basic setup might come in handy later
it(`should return empty array when there are no targets (depth=${depth},width=${width})`, function () {
const node = ctx.doc.createElement('div');
const fragment = createFragment(ctx, node, 0, depth, width);
sut = new FragmentNodeSequence(ctx.platform, fragment);
const actual = sut.findTargets();
assert.strictEqual(actual.length, 0, `actual.length`);
});

it(`should return all elements when all are targets targets (depth=${depth},width=${width})`, function () {
const node = ctx.doc.createElement('div');
node.classList.add('au');
const fragment = createFragment(ctx, node, 0, depth, width);
sut = new FragmentNodeSequence(ctx.platform, fragment);
const actual = sut.findTargets();
assert.strictEqual(actual.length, fragment.querySelectorAll('div').length, `actual.length`);
});
}
}
describe('[UNIT] findTargets', function () {
it(`should return all elements at all depths`, function () {
const node = ctx.doc.createElement('div');
node.innerHTML = '<template><au-m></au-m><!--au-start--><!--au-end--><div><au-m></au-m><el></el></div>';
const fragment = (node.firstChild as HTMLTemplateElement).content;
sut = new FragmentNodeSequence(ctx.platform, fragment);
const actual = sut.findTargets();
assert.strictEqual(isRenderLocation(actual[0]), true);
assert.strictEqual(actual[1], fragment.querySelector('el'));
});
});

describe('insertBefore', function () {
describe('[UNIT] insertBefore', function () {
for (const width of widthArr) {
for (const depth of depthArr.filter(d => d > 0)) {
it(`should insert the view before the refNode under the parent of the refNode (depth=${depth},width=${width})`, function () {
Expand Down
58 changes: 7 additions & 51 deletions packages/__tests__/3-runtime-html/enhance.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ describe('3-runtime-html/enhance.spec.ts', function () {
.register(MyElement) // in real app, there should be more
.enhance({ host: _host, component: CustomElement.define({ name: 'enhance' }, class EnhanceRoot { }) });

assert.html.innerEqual(_host, '<my-element class="au"><span>42</span></my-element>', 'enhanced.innerHtml');
assert.html.innerEqual(_host, '<my-element><span>42</span></my-element>', 'enhanced.innerHtml');
assert.html.innerEqual(this.container, '', 'container.innerHtml - before attach');
}

Expand All @@ -243,8 +243,8 @@ describe('3-runtime-html/enhance.spec.ts', function () {
// The inverse order of the stop and detaching is intentional
public async detaching() {
await this.enhanceView.deactivate(this.enhanceView, null);
assert.html.innerEqual(this.enhancedHost, '<my-element class="au"></my-element>', 'enhanced.innerHtml');
assert.html.innerEqual(this.container, '<div><my-element class="au"></my-element></div>', 'enhanced.innerHtml');
assert.html.innerEqual(this.enhancedHost, '<my-element></my-element>', 'enhanced.innerHtml');
assert.html.innerEqual(this.container, '<div><my-element></my-element></div>', 'enhanced.innerHtml');
}

public unbinding() {
Expand All @@ -262,7 +262,7 @@ describe('3-runtime-html/enhance.spec.ts', function () {
.app({ host, component: App })
.start();

assert.html.innerEqual(host.querySelector('#container'), '<div><my-element class="au"><span>42</span></my-element></div>', 'container.innerHTML - after attach');
assert.html.innerEqual(host.querySelector('#container'), '<div><my-element><span>42</span></my-element></div>', 'container.innerHTML - after attach');

await au.stop();

Expand Down Expand Up @@ -339,7 +339,7 @@ describe('3-runtime-html/enhance.spec.ts', function () {

assert.notStrictEqual(parentController, void 0);
assert.strictEqual(component.myElController === parentController, true);
assert.html.innerEqual(appHost, '<my-el class="au"><div><div>Hello _div_</div></div></my-el>');
assert.html.innerEqual(appHost, '<my-el><div><div>Hello _div_</div></div></my-el>');

await tearDown();
assert.strictEqual(parentController, void 0);
Expand Down Expand Up @@ -368,7 +368,7 @@ describe('3-runtime-html/enhance.spec.ts', function () {
}))
});

assert.strictEqual(host.innerHTML, '<div class="au" data-id="12"></div>');
assert.strictEqual(host.innerHTML, '<div data-id="12"></div>');
await controller.deactivate(controller, null);
});

Expand All @@ -395,52 +395,8 @@ describe('3-runtime-html/enhance.spec.ts', function () {
)
});

assert.strictEqual(host.innerHTML, '<div class="au" data-id="11"></div>');
assert.strictEqual(host.innerHTML, '<div data-id="11"></div>');
assert.strictEqual(container.find(ValueConverter, 'plus10'), null, 'It should register resources with child contaienr only.');
await controller.deactivate(controller, null);
});

it('throws on template with a predefined "au"', async function () {
const ctx = TestContext.create();
const host = ctx.doc.createElement('div');

const container = ctx.container;
const au = new Aurelia(container);
host.innerHTML = '<div class="au"></div>';
let ex;
try {
await au.enhance({ host, component: { id: 1 } });
} catch (e) {
ex = e;
}
assert.instanceOf(ex, Error);
assert.strictEqual(host.innerHTML, '<div class="au"></div>');
});

it('throws on re-enhancement of a node that has an element with class="au"', async function () {
const ctx = TestContext.create();
const host = ctx.doc.createElement('div');

const container = ctx.container;
const au = new Aurelia(container);
host.innerHTML = `<div><div repeat.for="i of 3" data-id.bind="i">\${i}</div></div>`;
const controller = await au.enhance({ host, component: { id: 1 } });
assert.html.textContent(host, '012');
assert.throws(() => au.enhance({ host, component: {} }));
await controller.deactivate(controller, null);
});

it('does not throw on enhancement that did not result in "au" class', async function () {
const ctx = TestContext.create();
const host = ctx.doc.createElement('div');

const container = ctx.container;
const au = new Aurelia(container);
host.innerHTML = `<div><div repeat.for="i of 3">\${i}</div></div>`;
const controller = await au.enhance({ host, component: { id: 1 } });
assert.html.textContent(host, '012');
const controller2 = await au.enhance({ host, component: {} });
await controller2.deactivate(controller2, null);
await controller.deactivate(controller, null);
});
});

0 comments on commit 0d30998

Please sign in to comment.