Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: migrate test app package to TypeScript #132

Merged
merged 10 commits into from
Nov 27, 2023
5 changes: 4 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,11 @@ jobs:
pnpm-version: 8.5.1
node-version: 18.x
args: "--frozen-lockfile"
- name: Update TS version
- name: Update TS version on addon package
run: pnpm add -D ${{ matrix.typescript-scenario }}
working-directory: ember-prismic-dom
- name: Update TS version on test-app package
run: pnpm add -D ${{ matrix.typescript-scenario }}
working-directory: test-app
- name: Type checking
run: pnpm lint:types
File renamed without changes.
1 change: 1 addition & 0 deletions test-app/app/components/group-list-item.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<ul>{{yield}} elephant</ul>
vscav marked this conversation as resolved.
Show resolved Hide resolved
12 changes: 12 additions & 0 deletions test-app/app/components/group-list-item.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import templateOnlyComponent from '@ember/component/template-only';

export interface GroupListItemSignature {
Element: HTMLUListElement;
Blocks: {
default: [];
};
}

const GroupListItem = templateOnlyComponent<GroupListItemSignature>();

export default GroupListItem;
1 change: 1 addition & 0 deletions test-app/app/components/hyperlink.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<a href={{@node.node.data.url}}>{{yield}}</a>
vscav marked this conversation as resolved.
Show resolved Hide resolved
17 changes: 17 additions & 0 deletions test-app/app/components/hyperlink.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import templateOnlyComponent from '@ember/component/template-only';

export interface HyperlinkSignature {
Element: HTMLAnchorElement;
// The `node` argument should be a TreeNode, but that type is not exported
// from the package.
// https://github.com/prismicio/prismic-richtext/blob/495456d843ef79153ab9de87cc76b1cc940f6aec/src/types.ts#L136
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Args: { node: any };
Blocks: {
default: [];
};
}

const Hyperlink = templateOnlyComponent<HyperlinkSignature>();

export default Hyperlink;
1 change: 1 addition & 0 deletions test-app/app/components/list-item.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<li>{{yield}} banana</li>
vscav marked this conversation as resolved.
Show resolved Hide resolved
12 changes: 12 additions & 0 deletions test-app/app/components/list-item.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import templateOnlyComponent from '@ember/component/template-only';

export interface ListItemSignature {
Element: HTMLUListElement;
Blocks: {
default: [];
};
}

const ListItem = templateOnlyComponent<ListItemSignature>();

export default ListItem;
1 change: 1 addition & 0 deletions test-app/app/components/super-custom.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<mark>{{yield}}</mark>
vscav marked this conversation as resolved.
Show resolved Hide resolved
12 changes: 12 additions & 0 deletions test-app/app/components/super-custom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import templateOnlyComponent from '@ember/component/template-only';

interface SuperCustomSignature {
Element: HTMLElement;
Blocks: {
default: [];
};
}

const SuperCustom = templateOnlyComponent<SuperCustomSignature>();

export default SuperCustom;
File renamed without changes.
10 changes: 10 additions & 0 deletions test-app/config/ember-try.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
const getChannelURL = require('ember-source-channel-url');
const { embroiderSafe, embroiderOptimized } = require('@embroider/test-setup');

// Needed for ember-source < 4.8, when preview types were first shipped
const emberTypesPackages = {
'@types/ember__application': '^4.0.10',
'@types/ember__component': '^4.0.21',
'@types/ember__routing': '^4.0.19',
};

module.exports = async function () {
return {
usePnpm: true,
Expand All @@ -12,6 +19,7 @@ module.exports = async function () {
npm: {
devDependencies: {
'ember-source': '~3.28.0',
...emberTypesPackages,
},
},
},
Expand All @@ -20,6 +28,7 @@ module.exports = async function () {
npm: {
devDependencies: {
'ember-source': '~4.4.0',
...emberTypesPackages,
},
},
},
Expand Down Expand Up @@ -75,6 +84,7 @@ module.exports = async function () {
npm: {
devDependencies: {
'ember-source': '~3.28.0',
...emberTypesPackages,
},
ember: {
edition: 'classic',
Expand Down
4 changes: 3 additions & 1 deletion test-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@
"lint:hbs:fix": "ember-template-lint . --fix",
"lint:js": "eslint . --cache",
"lint:js:fix": "eslint . --fix",
"lint:types": "glint",
"start": "ember serve",
"test": "concurrently \"pnpm:lint\" \"pnpm:test:*\" --names \"lint,test:\"",
"test:ember": "ember test"
"test:ember": "ember test",
"try:ember": "ember try:one"
},
"devDependencies": {
"@babel/eslint-parser": "^7.23.3",
Expand Down
14 changes: 0 additions & 14 deletions test-app/tests/helpers/clean-html.js

This file was deleted.

18 changes: 18 additions & 0 deletions test-app/tests/helpers/clean-html.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export default function cleanHtml({
element,
}: {
element: HTMLElement;
}): string {
const elementHelperIds = / id="[a-zA-Z0-9]*"/g;
const emberViewClass = / class="ember-view"/g;
const extraWhiteSpace = /\s{2,}/g;
const spaceBetweenTags = />(\s+)</g;
const spaceAroundContent = />(\s+)([^<]+)(\s+)</g;

return element.innerHTML
.replace(elementHelperIds, '')
.replace(emberViewClass, '')
.replace(extraWhiteSpace, ' ')
.replace(spaceBetweenTags, '><')
.replace(spaceAroundContent, '>$2<');
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ import {
setupApplicationTest as upstreamSetupApplicationTest,
setupRenderingTest as upstreamSetupRenderingTest,
setupTest as upstreamSetupTest,
type SetupTestOptions,
} from 'ember-qunit';

// This file exists to provide wrappers around ember-qunit's / ember-mocha's
// test setup functions. This way, you can easily extend the setup that is
// needed per test type.

function setupApplicationTest(hooks, options) {
function setupApplicationTest(
hooks: NestedHooks,
options: SetupTestOptions,
): void {
upstreamSetupApplicationTest(hooks, options);

// Additional setup for application tests can be done here.
Expand All @@ -27,13 +31,16 @@ function setupApplicationTest(hooks, options) {
// setupMirage(hooks); // ember-cli-mirage
}

function setupRenderingTest(hooks, options) {
function setupRenderingTest(
hooks: NestedHooks,
options: SetupTestOptions,
): void {
upstreamSetupRenderingTest(hooks, options);

// Additional setup for rendering tests can be done here.
}

function setupTest(hooks, options) {
function setupTest(hooks: NestedHooks, options: SetupTestOptions): void {
upstreamSetupTest(hooks, options);

// Additional setup for unit tests can be done here.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,44 @@
import { render } from '@ember/test-helpers';
import { setupRenderingTest } from 'ember-qunit';
import { module, test } from 'qunit';
import { setComponentTemplate } from '@ember/component';
import Component from '@glimmer/component';

import type { TestContext as TestContextBase } from '@ember/test-helpers';
import type { PrismicDomArgs } from 'ember-prismic-dom/components/prismic/dom';
import { hbs } from 'ember-cli-htmlbars';

import cleanHtml from '../../../helpers/clean-html';
import GroupListItem, {
type GroupListItemSignature,
} from 'test-app/components/group-list-item';
import Hyperlink, {
type HyperlinkSignature,
} from 'test-app/components/hyperlink';
import ListItem, {
type ListItemSignature,
} from 'test-app/components/list-item';
import SuperCustom from 'test-app/components/super-custom';

import cleanHtml from 'test-app/tests/helpers/clean-html';
import type { TemplateOnlyComponent } from '@ember/component/template-only';

interface TestContext extends TestContextBase {
element: HTMLElement;
nodes: PrismicDomArgs['nodes'];
groupListItem: TemplateOnlyComponent<GroupListItemSignature>;
hyperlink: TemplateOnlyComponent<HyperlinkSignature>;
listItem: TemplateOnlyComponent<ListItemSignature> | undefined;
}

module('Integration | Component | prismic/dom', function (hooks) {
setupRenderingTest(hooks);

module('single elements', function () {
test('renders string', async function (assert) {
await render(hbs`<Prismic::Dom @nodes='some text' />`);
test('renders string', async function (this: TestContext, assert) {
await render<TestContext>(hbs`<Prismic::Dom @nodes='some text' />`);
assert.strictEqual(cleanHtml(this), '<div>some text</div>');
});
});

module('custom elements', function () {
test('hyperlink', async function (assert) {
class Hyperlink extends Component {}
setComponentTemplate(
hbs`<a href={{@node.node.data.url}}>{{yield}}</a>`,
Hyperlink,
);

this.hyperlink = Hyperlink;

test('hyperlink', async function (this: TestContext, assert) {
this.nodes = [
{
type: 'paragraph',
Expand All @@ -43,19 +54,20 @@ module('Integration | Component | prismic/dom', function (hooks) {
},
];

await render(
this.hyperlink = Hyperlink;

await render<TestContext>(
hbs`<Prismic::Dom @nodes={{this.nodes}} @hyperlink={{this.hyperlink}} />`,
);

assert.strictEqual(
cleanHtml(this),
'<div><p>A <a href="https://example.org">link</a> to somewhere</p></div>',
);
});

test('handle passing a custom component as a string', async function (assert) {
class SuperCustom extends Component {}
setComponentTemplate(hbs`<mark>{{yield}}</mark>`, SuperCustom);

test('handle passing a custom component as a string', async function (this: TestContext, assert) {
this.owner.register('component:super-custom', SuperCustom);
this.nodes = [
{
type: 'paragraph',
Expand All @@ -64,15 +76,14 @@ module('Integration | Component | prismic/dom', function (hooks) {
{
start: 2,
end: 7,
type: 'super-custom',
type: 'strong',
},
],
},
];
this.owner.register('component:super-custom', SuperCustom);

await render(
hbs`<Prismic::Dom @nodes={{this.nodes}} @super-custom="super-custom" />`,
await render<TestContext>(
hbs`<Prismic::Dom @nodes={{this.nodes}} @strong="super-custom" />`,
);

assert.strictEqual(
Expand All @@ -81,22 +92,16 @@ module('Integration | Component | prismic/dom', function (hooks) {
);
});

test('list', async function (assert) {
class GroupListItem extends Component {}
class ListItem extends Component {}

setComponentTemplate(hbs`<ul>{{~yield~}} elephant</ul>`, GroupListItem);
setComponentTemplate(hbs`<li>{{~yield}} banana</li>`, ListItem);

test('list', async function (this: TestContext, assert) {
this.nodes = [
{ type: 'list-item', text: 'one', spans: [] },
{ type: 'list-item', text: 'two', spans: [] },
];

this.groupListItem = GroupListItem;
this.listItem = '';
this.listItem = undefined;

await render(
await render<TestContext>(
hbs`<Prismic::Dom @nodes={{this.nodes}} @group-list-item={{this.groupListItem}} @list-item={{this.listItem}}/>`,
);

Expand All @@ -115,21 +120,21 @@ module('Integration | Component | prismic/dom', function (hooks) {
});

module('complex combinations', function () {
test('list', async function (assert) {
test('list', async function (this: TestContext, assert) {
this.nodes = [
{ type: 'o-list-item', text: 'one', spans: [] },
{ type: 'o-list-item', text: 'two', spans: [] },
];

await render(hbs`<Prismic::Dom @nodes={{this.nodes}} />`);
await render<TestContext>(hbs`<Prismic::Dom @nodes={{this.nodes}} />`);

assert.strictEqual(
cleanHtml(this),
'<div><ol><li>one</li><li>two</li></ol></div>',
);
});

test('it renders text with overlapping spans', async function (assert) {
test('it renders text with overlapping spans', async function (this: TestContext, assert) {
this.nodes = [
{
type: 'paragraph',
Expand All @@ -141,15 +146,15 @@ module('Integration | Component | prismic/dom', function (hooks) {
},
];

await render(hbs`<Prismic::Dom @nodes={{this.nodes}} />`);
await render<TestContext>(hbs`<Prismic::Dom @nodes={{this.nodes}} />`);

assert.strictEqual(
cleanHtml(this),
'<div><p>This is some text with <strong>overla<em>pp</em></strong><em>ings</em> spans and here</p></div>',
);
});

test('it renders links with overlapping styles', async function (assert) {
test('it renders links with overlapping styles', async function (this: TestContext, assert) {
this.nodes = [
{
type: 'paragraph',
Expand All @@ -167,7 +172,7 @@ module('Integration | Component | prismic/dom', function (hooks) {
},
];

await render(hbs`<Prismic::Dom @nodes={{this.nodes}} />`);
await render<TestContext>(hbs`<Prismic::Dom @nodes={{this.nodes}} />`);

assert.strictEqual(
cleanHtml(this),
Expand Down