From 77eb8c38f60f128cf1a61f16c55efcf364855a7c Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Sat, 15 Jul 2023 15:03:09 -0400 Subject: [PATCH 1/5] Add additional fixture helpers based on usage discovered needed in this batch of work as well as what's planned --- tests/fixture-helper.ts | 30 ++++++++++++++++++++++++++++++ tests/utils.ts | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 tests/fixture-helper.ts diff --git a/tests/fixture-helper.ts b/tests/fixture-helper.ts new file mode 100644 index 00000000..ba10f306 --- /dev/null +++ b/tests/fixture-helper.ts @@ -0,0 +1,30 @@ +import { matchesFixture } from './assertions.js'; +import { copyFixture, runScript } from './utils.js'; + +export class AddonFixtureHelper { + #cwd: string; + #scenario: string; + #packageManager: 'npm' | 'pnpm' | 'yarn'; + + constructor(options: { + cwd: string; + scenario?: string; + packageManager: 'pnpm' | 'npm' | 'yarn'; + }) { + this.#cwd = options.cwd; + this.#scenario = options.scenario || 'default'; + this.#packageManager = options.packageManager; + } + + async use(file: string) { + await copyFixture(file, { scenario: this.#scenario, cwd: this.#cwd }); + } + + async build() { + await runScript({ cwd: this.#cwd, script: 'build', packageManager: this.#packageManager }); + } + + async matches(outputFile: string) { + await matchesFixture(outputFile, { scenario: this.#scenario, cwd: this.#cwd }); + } +} diff --git a/tests/utils.ts b/tests/utils.ts index 9c0341d3..95b717d8 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -13,6 +13,43 @@ const fixturesPath = path.join(__dirname, 'fixtures'); export const SUPPORTED_PACKAGE_MANAGERS = ['npm', 'yarn', 'pnpm'] as const; +export async function copyFixture( + /** + * Which file within the fixture-set / scenario to copy + */ + newFile: string, + options?: { + /** + * Which fixture set to use + */ + scenario?: string; + /** + * By default, the file used will be the same as the testFilePath, but + * in the fixtures directory under the (maybe) specified scenario. + * this can be overridden, if needed. + * (like if you're testFilePath is deep with in an existing monorepo, and wouldn't + * inherently match our default-project structure used in the fixtures) + */ + file?: string; + /** + * The working directory to use for the relative paths. Defaults to process.cwd() (node default) + */ + cwd?: string; + } +) { + let scenario = options?.scenario ?? 'default'; + let fixtureFile = options?.file ?? newFile; + + if (options?.cwd) { + newFile = path.join(options.cwd, newFile); + } + + let fixtureContents = await fixture(fixtureFile, { scenario }); + + await fse.mkdir(path.dirname(newFile), { recursive: true }); + await fs.writeFile(newFile, fixtureContents); +} + export async function fixture( /** * Which file within in the fixture-set / scenario to read From 1a38eb37750386797fe53055e886164a8d9afcf2 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Sat, 15 Jul 2023 15:03:57 -0400 Subject: [PATCH 2/5] Editors may run prettier per workspace, rather than per .prettierrc.js (the root), so the .prettierignore *is* needed in the tests directory --- tests/.prettierignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 tests/.prettierignore diff --git a/tests/.prettierignore b/tests/.prettierignore new file mode 100644 index 00000000..410367b9 --- /dev/null +++ b/tests/.prettierignore @@ -0,0 +1,3 @@ +# Editors may run prettier per-workspace, which would ignore +# the top-level workspaces' prettier config. +fixtures/ From 3ea81fa9757aadef551ca4937c6ed148805fa5cd Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Sat, 15 Jul 2023 15:04:36 -0400 Subject: [PATCH 3/5] Add component building tests for JS and TS --- tests/build-tests/components.test.ts | 106 ++++++++++++++++++ .../dist/components/co-located.js | 13 +++ .../dist/components/no-template.js | 10 ++ .../src/components/co-located.hbs | 1 + .../src/components/co-located.js | 7 ++ .../src/components/no-template.js | 7 ++ .../declarations/components/co-located.d.ts | 12 ++ .../declarations/components/no-template.d.ts | 10 ++ .../dist/components/co-located.js | 15 +++ .../dist/components/no-template.js | 10 ++ .../src/components/co-located.hbs | 3 + .../src/components/co-located.ts | 12 ++ .../src/components/no-template.ts | 12 ++ 13 files changed, 218 insertions(+) create mode 100644 tests/build-tests/components.test.ts create mode 100644 tests/fixtures/addon-only-js/dist/components/co-located.js create mode 100644 tests/fixtures/addon-only-js/dist/components/no-template.js create mode 100644 tests/fixtures/addon-only-js/src/components/co-located.hbs create mode 100644 tests/fixtures/addon-only-js/src/components/co-located.js create mode 100644 tests/fixtures/addon-only-js/src/components/no-template.js create mode 100644 tests/fixtures/addon-only-ts/declarations/components/co-located.d.ts create mode 100644 tests/fixtures/addon-only-ts/declarations/components/no-template.d.ts create mode 100644 tests/fixtures/addon-only-ts/dist/components/co-located.js create mode 100644 tests/fixtures/addon-only-ts/dist/components/no-template.js create mode 100644 tests/fixtures/addon-only-ts/src/components/co-located.hbs create mode 100644 tests/fixtures/addon-only-ts/src/components/co-located.ts create mode 100644 tests/fixtures/addon-only-ts/src/components/no-template.ts diff --git a/tests/build-tests/components.test.ts b/tests/build-tests/components.test.ts new file mode 100644 index 00000000..e6a22a65 --- /dev/null +++ b/tests/build-tests/components.test.ts @@ -0,0 +1,106 @@ +import { execa } from 'execa'; +import fs from 'node:fs/promises'; +import path from 'node:path'; +import { afterEach, beforeEach, describe, it } from 'vitest'; + +import { AddonFixtureHelper } from '../fixture-helper.js'; +import { createAddon, createTmp, install } from '../utils.js'; + +let packageManager = 'pnpm'; + +describe('components (build)', () => { + describe('co-located JS', () => { + let cwd = ''; + let tmpDir = ''; + let addonOnlyJS: AddonFixtureHelper; + + beforeEach(async () => { + tmpDir = await createTmp(); + + console.debug(`Debug test repo at ${tmpDir}`); + + let { name } = await createAddon({ + args: [`--pnpm=true`, '--addon-only'], + options: { cwd: tmpDir }, + }); + + cwd = path.join(tmpDir, name); + + addonOnlyJS = new AddonFixtureHelper({ + cwd, + packageManager: 'pnpm', + scenario: 'addon-only-js', + }); + + await install({ cwd, packageManager, skipPrepare: true }); + + // NOTE: This isn't needed to make the tests pass atm, but it would be + // required when consumers try to use these compiled components + await execa('pnpm', ['add', '--save-peer', '@glimmer/component'], { cwd }); + }); + + afterEach(async () => { + fs.rm(tmpDir, { recursive: true, force: true }); + }); + + it('generates correct files with no template', async () => { + await addonOnlyJS.use('src/components/no-template.js'); + await addonOnlyJS.build(); + await addonOnlyJS.matches('dist/components/no-template.js'); + }); + + it('generates correct files with a template', async () => { + await addonOnlyJS.use('src/components/co-located.js'); + await addonOnlyJS.use('src/components/co-located.hbs'); + await addonOnlyJS.build(); + await addonOnlyJS.matches('dist/components/co-located.js'); + }); + }); + + describe('co-located TS', () => { + let cwd = ''; + let tmpDir = ''; + let addonOnlyTS: AddonFixtureHelper; + + beforeEach(async () => { + tmpDir = await createTmp(); + + console.debug(`Debug test repo at ${tmpDir}`); + + let { name } = await createAddon({ + args: [`--pnpm=true`, '--addon-only', '--typescript'], + options: { cwd: tmpDir }, + }); + + cwd = path.join(tmpDir, name); + + addonOnlyTS = new AddonFixtureHelper({ + cwd, + packageManager: 'pnpm', + scenario: 'addon-only-ts', + }); + + await install({ cwd, packageManager, skipPrepare: true }); + await execa('pnpm', ['add', '--save-peer', '@glimmer/component'], { cwd }); + }); + + afterEach(async () => { + fs.rm(tmpDir, { recursive: true, force: true }); + }); + + it('generates correct files with no template', async () => { + await addonOnlyTS.use('src/components/no-template.ts'); + await addonOnlyTS.build(); + await addonOnlyTS.matches('dist/components/no-template.js'); + await addonOnlyTS.matches('declarations/components/no-template.d.ts'); + }); + + it('generates correct files with a template', async () => { + await addonOnlyTS.use('src/components/co-located.ts'); + await addonOnlyTS.use('src/components/co-located.hbs'); + await addonOnlyTS.build(); + await addonOnlyTS.matches('dist/components/co-located.js'); + await addonOnlyTS.matches('declarations/components/co-located.d.ts'); + }); + }); +}); diff --git a/tests/fixtures/addon-only-js/dist/components/co-located.js b/tests/fixtures/addon-only-js/dist/components/co-located.js new file mode 100644 index 00000000..dd0566e5 --- /dev/null +++ b/tests/fixtures/addon-only-js/dist/components/co-located.js @@ -0,0 +1,13 @@ +import { precompileTemplate } from '@ember/template-compilation'; +import Component from '@glimmer/component'; + +precompileTemplate("{{this.someGetter}}\n"); + +class CoLocated extends Component { + get someGetter() { + return 'someGetter'; + } +} + +export { CoLocated }; +//# sourceMappingURL=co-located.js.map diff --git a/tests/fixtures/addon-only-js/dist/components/no-template.js b/tests/fixtures/addon-only-js/dist/components/no-template.js new file mode 100644 index 00000000..166df4a8 --- /dev/null +++ b/tests/fixtures/addon-only-js/dist/components/no-template.js @@ -0,0 +1,10 @@ +import Component from '@glimmer/component'; + +class NoTemplate extends Component { + get someGetter() { + return 'someGetter'; + } +} + +export { NoTemplate }; +//# sourceMappingURL=no-template.js.map diff --git a/tests/fixtures/addon-only-js/src/components/co-located.hbs b/tests/fixtures/addon-only-js/src/components/co-located.hbs new file mode 100644 index 00000000..4684ee69 --- /dev/null +++ b/tests/fixtures/addon-only-js/src/components/co-located.hbs @@ -0,0 +1 @@ +{{this.someGetter}} diff --git a/tests/fixtures/addon-only-js/src/components/co-located.js b/tests/fixtures/addon-only-js/src/components/co-located.js new file mode 100644 index 00000000..8e983716 --- /dev/null +++ b/tests/fixtures/addon-only-js/src/components/co-located.js @@ -0,0 +1,7 @@ +import Component from '@glimmer/component'; + +export class CoLocated extends Component { + get someGetter() { + return 'someGetter'; + } +} diff --git a/tests/fixtures/addon-only-js/src/components/no-template.js b/tests/fixtures/addon-only-js/src/components/no-template.js new file mode 100644 index 00000000..3ba91920 --- /dev/null +++ b/tests/fixtures/addon-only-js/src/components/no-template.js @@ -0,0 +1,7 @@ +import Component from '@glimmer/component'; + +export class NoTemplate extends Component { + get someGetter() { + return 'someGetter'; + } +} diff --git a/tests/fixtures/addon-only-ts/declarations/components/co-located.d.ts b/tests/fixtures/addon-only-ts/declarations/components/co-located.d.ts new file mode 100644 index 00000000..9b4c9b05 --- /dev/null +++ b/tests/fixtures/addon-only-ts/declarations/components/co-located.d.ts @@ -0,0 +1,12 @@ +import Component from '@glimmer/component'; +interface Signature { + Args: {}; + Blocks: { + default: []; + }; +} +export default class CoLocated extends Component { + get someGetter(): string; +} +export {}; +//# sourceMappingURL=co-located.d.ts.map diff --git a/tests/fixtures/addon-only-ts/declarations/components/no-template.d.ts b/tests/fixtures/addon-only-ts/declarations/components/no-template.d.ts new file mode 100644 index 00000000..36582422 --- /dev/null +++ b/tests/fixtures/addon-only-ts/declarations/components/no-template.d.ts @@ -0,0 +1,10 @@ +import Component from '@glimmer/component'; +interface Signature { + Args: {}; + Blocks: {}; +} +export declare class NoTemplate extends Component { + get someGetter(): string; +} +export {}; +//# sourceMappingURL=no-template.d.ts.map diff --git a/tests/fixtures/addon-only-ts/dist/components/co-located.js b/tests/fixtures/addon-only-ts/dist/components/co-located.js new file mode 100644 index 00000000..d1574846 --- /dev/null +++ b/tests/fixtures/addon-only-ts/dist/components/co-located.js @@ -0,0 +1,15 @@ +import { setComponentTemplate } from '@ember/component'; +import { precompileTemplate } from '@ember/template-compilation'; +import Component from '@glimmer/component'; + +var TEMPLATE = precompileTemplate("{{this.someGetter}}\n\n{{yield}}\n"); + +class CoLocated extends Component { + get someGetter() { + return 'someGetter'; + } +} +setComponentTemplate(TEMPLATE, CoLocated); + +export { CoLocated as default }; +//# sourceMappingURL=co-located.js.map diff --git a/tests/fixtures/addon-only-ts/dist/components/no-template.js b/tests/fixtures/addon-only-ts/dist/components/no-template.js new file mode 100644 index 00000000..166df4a8 --- /dev/null +++ b/tests/fixtures/addon-only-ts/dist/components/no-template.js @@ -0,0 +1,10 @@ +import Component from '@glimmer/component'; + +class NoTemplate extends Component { + get someGetter() { + return 'someGetter'; + } +} + +export { NoTemplate }; +//# sourceMappingURL=no-template.js.map diff --git a/tests/fixtures/addon-only-ts/src/components/co-located.hbs b/tests/fixtures/addon-only-ts/src/components/co-located.hbs new file mode 100644 index 00000000..397cf929 --- /dev/null +++ b/tests/fixtures/addon-only-ts/src/components/co-located.hbs @@ -0,0 +1,3 @@ +{{this.someGetter}} + +{{yield}} diff --git a/tests/fixtures/addon-only-ts/src/components/co-located.ts b/tests/fixtures/addon-only-ts/src/components/co-located.ts new file mode 100644 index 00000000..41ccc5e5 --- /dev/null +++ b/tests/fixtures/addon-only-ts/src/components/co-located.ts @@ -0,0 +1,12 @@ +import Component from '@glimmer/component'; + +interface Signature { + Args: {}, + Blocks: { default: [] } +} + +export default class CoLocated extends Component { + get someGetter() { + return 'someGetter'; + } +} diff --git a/tests/fixtures/addon-only-ts/src/components/no-template.ts b/tests/fixtures/addon-only-ts/src/components/no-template.ts new file mode 100644 index 00000000..2493be76 --- /dev/null +++ b/tests/fixtures/addon-only-ts/src/components/no-template.ts @@ -0,0 +1,12 @@ +import Component from '@glimmer/component'; + +interface Signature { + Args: {}, + Blocks: {} +} + +export class NoTemplate extends Component { + get someGetter() { + return 'someGetter'; + } +} From ac4cb2a1bf6c5feb8a4ad2c8bc3725d303e75577 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Sat, 15 Jul 2023 15:04:48 -0400 Subject: [PATCH 4/5] Enable component tests in CI --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d5467423..33c26903 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,6 +47,8 @@ jobs: # so we could be sure we don't miss anything # and then generate this list from a previous C.I. job slow-test: + - components + - defaults with npm - defaults with yarn - defaults with pnpm From e20f37ae85f0f4078bcc4a43e13492499fc0a6d9 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Sat, 15 Jul 2023 15:07:25 -0400 Subject: [PATCH 5/5] Like with prettier, we also need to tell tsc to ignore the fixtures directory --- tests/tsconfig.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/tsconfig.json b/tests/tsconfig.json index 076f2a3e..13c97cd2 100644 --- a/tests/tsconfig.json +++ b/tests/tsconfig.json @@ -7,5 +7,6 @@ // Vite's internal types aren't relevant to us "skipLibCheck": true - } + }, + "exclude": ["fixtures/"] }