diff --git a/files/babel.config.cjs b/files/babel.config.cjs index 8cd58ac..ce930e9 100644 --- a/files/babel.config.cjs +++ b/files/babel.config.cjs @@ -1,3 +1,8 @@ +/** + * This babel.config is not used for publishing. + * It's only for the local editing experience + * (and linting) + */ const { buildMacros } = require('@embroider/macros/babel'); const { @@ -12,11 +17,14 @@ const isCompat = Boolean(process.env.ENABLE_COMPAT_BUILD); module.exports = { plugins: [<% if (typescript) { %> - ['@babel/plugin-transform-typescript', { - allExtensions: true, - allowDeclareFields: true, - onlyRemoveTypeImports: true, - }],<% } %> + [ + '@babel/plugin-transform-typescript', + { + allExtensions: true, + allowDeclareFields: true, + onlyRemoveTypeImports: true, + }, + ],<% } %> [ 'babel-plugin-ember-template-compilation', { diff --git a/files/babel.publish.config.cjs b/files/babel.publish.config.cjs index f8bcf11..d5f2900 100644 --- a/files/babel.publish.config.cjs +++ b/files/babel.publish.config.cjs @@ -1,3 +1,8 @@ +/** + * This babel.config is only used for publishing. + * + * For local dev experience, see the babel.config + */ module.exports = { plugins: [<% if (typescript) { %> [ diff --git a/files/package.json b/files/package.json index f8e28ca..4deb4e8 100644 --- a/files/package.json +++ b/files/package.json @@ -38,19 +38,22 @@ "@babel/plugin-transform-typescript": "^7.25.2",<% } %> "@babel/runtime": "^7.25.6", "@ember/test-helpers": "^5.2.1", - "@embroider/addon-dev": "^8.0.1", + "@embroider/addon-dev": "^8.1.0", "@embroider/core": "^4.1.0", "@embroider/compat": "^4.1.0", "@embroider/macros": "^1.18.0", "@embroider/vite": "^1.1.5", "@eslint/js": "^9.17.0", "@glimmer/component": "^2.0.0",<% if (typescript) { %> - "@glint/core": "^1.4.0", - "@glint/environment-ember-loose": "^1.4.0", - "@glint/environment-ember-template-imports": "^1.4.0", - "@glint/template": "^1.4.0", + "@glint/core": "^2.0.0-alpha.2", + "@glint/environment-ember-loose": "^2.0.0-alpha.2", + "@glint/environment-ember-template-imports": "^2.0.0-alpha.2", + "@glint/tsserver-plugin": "^2.0.0-alpha.2", + "@glint/template": "^1.6.0-alpha.1", + "@ember/app-tsconfig": "^1.0.0", "@ember/library-tsconfig": "^1.0.0",<% } %> - "@rollup/plugin-babel": "^6.0.4", + "@rollup/plugin-babel": "^6.0.4",<% if (typescript) { %> + "@types/qunit": "^2.19.12",<% } %> "babel-plugin-ember-template-compilation": "^2.2.5", "concurrently": "^9.0.1", "ember-qunit": "^9.0.2", @@ -70,7 +73,7 @@ "rollup": "^4.22.5", "testem": "^3.15.1",<% if (typescript) { %> "typescript-eslint": "^8.19.1", - "typescript": "~5.6.0",<% } %> + "typescript": "~5.8.3",<% } %> "vite": "^6.2.4" }, "ember": { diff --git a/files/rollup.config.mjs b/files/rollup.config.mjs index 291fbb6..29576ce 100644 --- a/files/rollup.config.mjs +++ b/files/rollup.config.mjs @@ -8,6 +8,10 @@ const addon = new Addon({ destDir: 'dist', }); +const rootDirectory = dirname(fileURLToPath(import.meta.url)); +const babelConfig = resolve(rootDirectory, './babel.publish.config.cjs');<% if (typescript) { %> +const tsConfig = resolve(rootDirectory, './tsconfig.publish.json');<% } %> + export default { // This provides defaults that work well alongside `publicEntrypoints` below. // You can augment this if you need to. @@ -47,10 +51,7 @@ export default { babel({ extensions: ['.js', '.gjs'<% if (typescript) { %>, '.ts', '.gts'<% } %>], babelHelpers: 'bundled', - configFile: resolve( - dirname(fileURLToPath(import.meta.url)), - './babel.publish.config.cjs', - ), + configFile: babelConfig, }), // Ensure that standalone .hbs files are properly integrated as Javascript. @@ -60,7 +61,10 @@ export default { addon.gjs(),<% if (typescript) { %> // Emit .d.ts declaration files - addon.declarations('declarations'),<% } %> + addon.declarations( + 'declarations', + `npx glint --declaration --project ${tsConfig}`, + ),<% } %> // addons are allowed to contain imports of .css files, which we want rollup // to leave alone and keep in the published output. diff --git a/files/tests/test-helper.js b/files/tests/test-helper.__ext__ similarity index 100% rename from files/tests/test-helper.js rename to files/tests/test-helper.__ext__ diff --git a/files/tsconfig.json b/files/tsconfig.json index ea272ea..04f8ab7 100644 --- a/files/tsconfig.json +++ b/files/tsconfig.json @@ -1,25 +1,16 @@ +/** + * This tsconfig is not used for publishing. + * It's only for the local editing experience + * (and linting) + */ { - "extends": "@ember/library-tsconfig", - "include": ["src/**/*", "unpublished-development-types/**/*"], + "extends": "@ember/app-tsconfig", "glint": { "environment": ["ember-loose", "ember-template-imports"] }, + "include": ["src/**/*", "tests/**/*", "unpublished-development-types/**/*"], "compilerOptions": { - "allowJs": true, - "declarationDir": "declarations", - - /** - https://www.typescriptlang.org/tsconfig#rootDir - "Default: The longest common path of all non-declaration input files." - - Because we want our declarations' structure to match our rollup output, - we need this "rootDir" to match the "srcDir" in the rollup.config.mjs. - - This way, we can have simpler `package.json#exports` that matches - imports to files on disk - */ - "rootDir": "./src", - - "types": ["ember-source/types"] + "rootDir": ".", + "types": ["ember-source/types", "vite/client", "@embroider/core/virtual"] } } diff --git a/files/tsconfig.publish.json b/files/tsconfig.publish.json new file mode 100644 index 0000000..e100b77 --- /dev/null +++ b/files/tsconfig.publish.json @@ -0,0 +1,30 @@ +/** + * This tsconfig is only used for publishing. + * + * For local dev experience, see the tsconfig.json + */ +{ + "extends": "@ember/library-tsconfig", + "include": ["./src/**/*", "./unpublished-development-types/**/*"], + "glint": { + "environment": ["ember-loose", "ember-template-imports"] + }, + "compilerOptions": { + "allowJs": true, + "declarationDir": "declarations", + + /** + https://www.typescriptlang.org/tsconfig#rootDir + "Default: The longest common path of all non-declaration input files." + + Because we want our declarations' structure to match our rollup output, + we need this "rootDir" to match the "srcDir" in the rollup.config.mjs. + + This way, we can have simpler `package.json#exports` that matches + imports to files on disk + */ + "rootDir": "./src", + + "types": ["ember-source/types"] + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a994e79..620ac20 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -38,6 +38,9 @@ importers: fs-extra: specifier: ^10.0.0 version: 10.1.0 + globby: + specifier: ^14.1.0 + version: 14.1.0 tmp-promise: specifier: ^3.0.3 version: 3.0.3 @@ -607,6 +610,10 @@ packages: '@sec-ant/readable-stream@0.4.1': resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} + '@sindresorhus/merge-streams@2.3.0': + resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==} + engines: {node: '>=18'} + '@sindresorhus/merge-streams@4.0.0': resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} engines: {node: '>=18'} @@ -2140,6 +2147,10 @@ packages: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} + globby@14.1.0: + resolution: {integrity: sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==} + engines: {node: '>=18'} + gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} @@ -2289,6 +2300,10 @@ packages: ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} + imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -3113,6 +3128,10 @@ packages: path-to-regexp@0.1.12: resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} + path-type@6.0.0: + resolution: {integrity: sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==} + engines: {node: '>=18'} + pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} @@ -3501,6 +3520,10 @@ packages: resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} engines: {node: '>= 10'} + slash@5.1.0: + resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} + engines: {node: '>=14.16'} + smart-buffer@4.2.0: resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} @@ -4675,6 +4698,8 @@ snapshots: '@sec-ant/readable-stream@0.4.1': {} + '@sindresorhus/merge-streams@2.3.0': {} + '@sindresorhus/merge-streams@4.0.0': {} '@socket.io/component-emitter@3.1.2': {} @@ -6533,6 +6558,15 @@ snapshots: globals@11.12.0: {} + globby@14.1.0: + dependencies: + '@sindresorhus/merge-streams': 2.3.0 + fast-glob: 3.3.3 + ignore: 7.0.5 + path-type: 6.0.0 + slash: 5.1.0 + unicorn-magic: 0.3.0 + gopd@1.2.0: {} graceful-fs@4.2.10: {} @@ -6704,6 +6738,8 @@ snapshots: ieee754@1.2.1: {} + ignore@7.0.5: {} + imurmurhash@0.1.4: {} indent-string@4.0.0: {} @@ -7505,6 +7541,8 @@ snapshots: path-to-regexp@0.1.12: {} + path-type@6.0.0: {} + pathe@2.0.3: {} pathval@2.0.0: {} @@ -7934,6 +7972,8 @@ snapshots: mrmime: 2.0.1 totalist: 3.0.1 + slash@5.1.0: {} + smart-buffer@4.2.0: {} snapdragon-node@2.1.1: diff --git a/tests/fixtures/typescript/my-addon/src/components/co-located-ts.hbs b/tests/fixtures/typescript/my-addon/src/components/co-located-ts.hbs deleted file mode 100644 index af543d6..0000000 --- a/tests/fixtures/typescript/my-addon/src/components/co-located-ts.hbs +++ /dev/null @@ -1,3 +0,0 @@ -Hello, -{{this.whereAmI}} -(in TypeScript) diff --git a/tests/fixtures/typescript/my-addon/src/components/co-located-ts.ts b/tests/fixtures/typescript/my-addon/src/components/co-located-ts.ts deleted file mode 100644 index c250674..0000000 --- a/tests/fixtures/typescript/my-addon/src/components/co-located-ts.ts +++ /dev/null @@ -1,9 +0,0 @@ -import Component from '@glimmer/component'; -import { service } from '@ember/service'; -import type Example from '../services/example.ts'; - -export default class CoLocatedTs extends Component { - @service declare example: Example; - - whereAmI = 'from a co-located TS component'; -} diff --git a/tests/fixtures/typescript/my-addon/src/components/co-located.hbs b/tests/fixtures/typescript/my-addon/src/components/co-located.hbs deleted file mode 100644 index 22fe19c..0000000 --- a/tests/fixtures/typescript/my-addon/src/components/co-located.hbs +++ /dev/null @@ -1 +0,0 @@ -Hello, {{this.whereAmI}} diff --git a/tests/fixtures/typescript/my-addon/src/components/co-located.js b/tests/fixtures/typescript/my-addon/src/components/co-located.js deleted file mode 100644 index 77f1391..0000000 --- a/tests/fixtures/typescript/my-addon/src/components/co-located.js +++ /dev/null @@ -1,5 +0,0 @@ -import Component from '@glimmer/component'; - -export default class CoLocated extends Component { - whereAmI = 'from a co-located component'; -} diff --git a/tests/fixtures/typescript/my-addon/src/components/template-only.hbs b/tests/fixtures/typescript/my-addon/src/components/template-only.hbs deleted file mode 100644 index fc5daef..0000000 --- a/tests/fixtures/typescript/my-addon/src/components/template-only.hbs +++ /dev/null @@ -1 +0,0 @@ -Hello from a template-only component diff --git a/tests/fixtures/typescript/my-addon/src/components/template-only.ts b/tests/fixtures/typescript/my-addon/src/components/template-only.ts deleted file mode 100644 index fa85053..0000000 --- a/tests/fixtures/typescript/my-addon/src/components/template-only.ts +++ /dev/null @@ -1,3 +0,0 @@ -import templateOnly from '@ember/component/template-only'; - -export default templateOnly(); diff --git a/tests/fixtures/typescript/my-addon/src/components/another-gts.gts b/tests/fixtures/typescript/src/components/another-gts.gts similarity index 100% rename from tests/fixtures/typescript/my-addon/src/components/another-gts.gts rename to tests/fixtures/typescript/src/components/another-gts.gts diff --git a/tests/fixtures/typescript/my-addon/src/components/template-import.gts b/tests/fixtures/typescript/src/components/template-import.gts similarity index 77% rename from tests/fixtures/typescript/my-addon/src/components/template-import.gts rename to tests/fixtures/typescript/src/components/template-import.gts index 443f08e..65ac867 100644 --- a/tests/fixtures/typescript/my-addon/src/components/template-import.gts +++ b/tests/fixtures/typescript/src/components/template-import.gts @@ -1,5 +1,4 @@ import Component from '@glimmer/component'; -import TemplateOnly from './template-only.ts'; import AnotherGts from './another-gts.gts'; // N.B. relative imports inside a v2 addon should have explicit file extensions (this is consistent with how node treats ES modules) import { on } from '@ember/modifier'; import { action } from '@ember/object'; @@ -15,9 +14,9 @@ interface Signature { export default class TemplateImport extends Component { diff --git a/tests/fixtures/typescript/my-addon/src/services/example.ts b/tests/fixtures/typescript/src/services/example.ts similarity index 100% rename from tests/fixtures/typescript/my-addon/src/services/example.ts rename to tests/fixtures/typescript/src/services/example.ts diff --git a/tests/fixtures/typescript/test-app/tests/rendering/co-located-test.ts b/tests/fixtures/typescript/test-app/tests/rendering/co-located-test.ts deleted file mode 100644 index cbb1681..0000000 --- a/tests/fixtures/typescript/test-app/tests/rendering/co-located-test.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -import { render } from '@ember/test-helpers'; -import { hbs } from 'ember-cli-htmlbars'; - -module('Rendering | co-located', function (hooks) { - setupRenderingTest(hooks); - - test('it renders a JS component', async function (assert) { - await render(hbs``); - - assert.dom().hasText('Hello, from a co-located component'); - }); - - test('it renders a TS component', async function (assert) { - await render(hbs``); - - assert.dom().containsText('Hello, from a co-located TS component (in TypeScript)'); - }); -}); diff --git a/tests/fixtures/typescript/test-app/tests/rendering/template-only-test.ts b/tests/fixtures/typescript/test-app/tests/rendering/template-only-test.ts deleted file mode 100644 index ab20ed3..0000000 --- a/tests/fixtures/typescript/test-app/tests/rendering/template-only-test.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -import { render } from '@ember/test-helpers'; -import { hbs } from 'ember-cli-htmlbars'; - -module('Rendering | template-only', function(hooks) { - setupRenderingTest(hooks); - - test('it renders', async function(assert) { - await render(hbs``); - - assert.dom().hasText('Hello from a template-only component'); - }) -}); diff --git a/tests/fixtures/typescript/test-app/tests/rendering/template-import-test.ts b/tests/fixtures/typescript/tests/rendering/template-import-test.gts similarity index 67% rename from tests/fixtures/typescript/test-app/tests/rendering/template-import-test.ts rename to tests/fixtures/typescript/tests/rendering/template-import-test.gts index ebf1822..5693569 100644 --- a/tests/fixtures/typescript/test-app/tests/rendering/template-import-test.ts +++ b/tests/fixtures/typescript/tests/rendering/template-import-test.gts @@ -1,14 +1,15 @@ import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; import { render } from '@ember/test-helpers'; -import { hbs } from 'ember-cli-htmlbars'; + +import TemplateImport from '#src/components/template-import.gts'; module('Rendering | template-import', function(hooks) { setupRenderingTest(hooks); test('it renders', async function(assert) { - await render(hbs``); + await render(); - assert.dom().hasText('Hello from a GTS file but also Hello from a template-only component and Hello from another GTS file!'); + assert.dom().hasText('Hello from a GTS file but also Hello from another GTS file!'); }) }); diff --git a/tests/fixtures/typescript/tests/unit/ember-types-test.ts b/tests/fixtures/typescript/tests/unit/ember-types-test.ts new file mode 100644 index 0000000..9c29af1 --- /dev/null +++ b/tests/fixtures/typescript/tests/unit/ember-types-test.ts @@ -0,0 +1,12 @@ +import { tracked, cached } from '@glimmer/tracking'; +import Component from '@glimmer/component'; +import Route from '@ember/routing/route'; +import { isPresent } from '@ember/utils'; + +console.log({ + tracked, + cached, + Component, + Route, + isPresent, +}); diff --git a/tests/helpers/utils.ts b/tests/helpers/utils.ts index 5b33eb0..6322f79 100644 --- a/tests/helpers/utils.ts +++ b/tests/helpers/utils.ts @@ -4,6 +4,7 @@ import assert from 'node:assert'; import path from 'node:path'; import { $ } from 'execa'; import { fileURLToPath } from 'node:url'; +import { globby } from 'globby'; import { execa, type Options } from 'execa'; @@ -106,6 +107,18 @@ export async function runScript({ } } +export async function filesMatching(glob: string, dirPath: string) { + try { + let files = await globby(glob, { cwd: dirPath }); + + return files; + } catch (e) { + console.error('error', e); + + return []; + } +} + export async function dirContents(dirPath: string) { try { let files = await fs.readdir(dirPath); diff --git a/tests/package.json b/tests/package.json index e7bd42f..e42c56c 100644 --- a/tests/package.json +++ b/tests/package.json @@ -13,6 +13,7 @@ "execa": "^9.5.2", "fixturify": "^3.0.0", "fs-extra": "^10.0.0", + "globby": "^14.1.0", "tmp-promise": "^3.0.3", "typescript": "^4.7.4", "vite": "^3.0.0", diff --git a/tests/smoke-tests/--typescript.test.ts b/tests/smoke-tests/--typescript.test.ts index 8639c60..b0ec7ec 100644 --- a/tests/smoke-tests/--typescript.test.ts +++ b/tests/smoke-tests/--typescript.test.ts @@ -1,42 +1,66 @@ -import path from 'node:path'; - +import path, { join } from 'node:path'; +import tmp from 'tmp-promise'; +import fs from 'node:fs/promises'; +import fixturify from 'fixturify'; import { execa } from 'execa'; -import { afterAll, beforeAll, describe, expect, it } from 'vitest'; +import { beforeAll, beforeEach, describe, expect, it } from 'vitest'; import { - AddonHelper, assertGeneratedCorrectly, dirContents, + filesMatching, SUPPORTED_PACKAGE_MANAGERS, } from '../helpers.js'; +const blueprintPath = path.join(__dirname, '../..'); +let localEmberCli = require.resolve('ember-cli/bin/ember'); for (let packageManager of SUPPORTED_PACKAGE_MANAGERS) { - describe.skip(`--typescript with ${packageManager}`, () => { - let distDir = ''; - let declarationsDir = ''; - let helper = new AddonHelper({ - packageManager, - args: ['--typescript'], - scenario: 'typescript', - }); + describe(`--typescript with ${packageManager}`, () => { + let tmpDir: string; + let addonDir: string; + let addonName = 'my-addon'; + + async function commandSucceeds(command: string) { + let result = await execa({ + cwd: addonDir, + shell: true, + preferLocal: true, + // Allows us to not fail yet when the command fails + // but we'd still fail appropriately with the exitCode check below. + // When we fail, we want to check for git diffs for debugging purposes. + reject: false, + })(command); + + if (result.exitCode !== 0) { + console.log(result); + console.log(`\n\n${command} exited with code ${result.exitCode}\n\n`); + console.log(result.stdout); + console.log(result.stderr); + console.log(`\n\n git diff \n\n`); + await execa({ cwd: addonDir, stdio: 'inherit' })`git diff`; + } + + expect(result.exitCode, `\`${command}\` succeeds`).toEqual(0); + + return result; + } beforeAll(async () => { - await helper.setup(); - await helper.installDeps(); - - distDir = path.join(helper.addonFolder, 'dist'); - declarationsDir = path.join(helper.addonFolder, 'declarations'); - }); - - afterAll(async () => { - await helper.clean(); + tmpDir = (await tmp.dir()).path; + addonDir = join(tmpDir, addonName); + await execa({ + cwd: tmpDir, + })`${localEmberCli} addon ${addonName} -b ${blueprintPath} --skip-npm --prefer-local true --${packageManager} --typescript`; + // Have to use --force because NPM is *stricter* when you use tags in package.json + // than pnpm (in that tags don't match any specified stable version) + await execa({ + cwd: addonDir, + })`${packageManager} install ${packageManager === 'npm' ? '--force' : ''}`; }); it('was generated correctly', async () => { - await helper.build(); - assertGeneratedCorrectly({ - projectRoot: helper.projectRoot, + projectRoot: addonDir, packageManager, typeScript: true, }); @@ -44,69 +68,80 @@ for (let packageManager of SUPPORTED_PACKAGE_MANAGERS) { // Tests are additive, so when running them in order, we want to check linting // before we add files from fixtures - it('lints all pass', async () => { - let { exitCode } = await helper.run('lint'); - - expect(exitCode).toEqual(0); + it('lints pass', async () => { + await commandSucceeds(`${packageManager} run lint`); }); - it('build and test', async () => { - // Copy over fixtures - await helper.fixtures.use('./my-addon/src'); - await helper.fixtures.use('./test-app/tests'); - // Sync fixture with project's lint / formatting configuration - // (controlled by ember-cli) - // - // Ensure that we have no lint errors. - // It's important to keep this along with the tests, - // so that we can have confidence that the lints aren't destructively changing - // the files in a way that would break consumers - await helper.run('lint:fix'); - - /** - * In order to use build with components, we need to add more dependencies - * We may want to consider making these default - */ - await execa('pnpm', ['add', '--save-peer', '@glimmer/component'], { - cwd: helper.addonFolder, + describe('with fixture', () => { + beforeEach(async () => { + let addonFixture = fixturify.readSync('./fixtures/typescript'); + fixturify.writeSync(addonDir, addonFixture); + + // It's important that we ensure that dist directory is empty for these tests, + // troll-y things can happen with shared dists + await fs.rm(join(addonDir, 'dist'), { recursive: true, force: true }); + }); + + it('lint:fix', async () => { + await commandSucceeds(`${packageManager} run lint:fix`); }); - let buildResult = await helper.build(); - - expect(buildResult.exitCode).toEqual(0); - - let distContents = await dirContents(distDir); - let declarationsContents = await dirContents(declarationsDir); - - expect(distContents).toMatchInlineSnapshot(` - [ - "_app_", - "components", - "index.js", - "index.js.map", - "services", - "template-registry.js", - "template-registry.js.map", - ] - `); - - expect(declarationsContents).toMatchInlineSnapshot(` - [ - "components", - "index.d.ts", - "index.d.ts.map", - "services", - "template-registry.d.ts", - "template-registry.d.ts.map", - ] - `); - - let testResult = await helper.run('test'); - - expect(testResult.exitCode).toEqual(0); - expect(testResult.stdout).to.include('# tests 5'); - expect(testResult.stdout).to.include('# pass 5'); - expect(testResult.stdout).to.include('# fail 0'); + it('build', async () => { + await commandSucceeds(`${packageManager} run build`); + + expect( + await filesMatching('src/**', addonDir), + `ensure we don't pollute the src dir with declarations and emit the js and .d.ts to the correct folders -- this should be the same as the input files (no change from the fixture + default files)`, + ).toMatchInlineSnapshot(` + [ + "src/index.ts", + "src/template-registry.ts", + "src/components/another-gts.gts", + "src/components/template-import.gts", + "src/services/example.ts", + ] + `); + + expect( + await filesMatching('{dist,declarations}/**/*', addonDir), + `ensure we emit the correct files out of the box to the correct folders`, + ).toMatchInlineSnapshot(` + [ + "dist/index.js", + "dist/index.js.map", + "dist/template-registry.js", + "dist/template-registry.js.map", + "dist/components/another-gts.js", + "dist/components/another-gts.js.map", + "dist/components/template-import.js", + "dist/components/template-import.js.map", + "dist/services/example.js", + "dist/services/example.js.map", + "dist/_app_/components/another-gts.js", + "dist/_app_/components/template-import.js", + "dist/_app_/services/example.js", + "declarations/index.d.ts", + "declarations/index.d.ts.map", + "declarations/template-registry.d.ts", + "declarations/template-registry.d.ts.map", + "declarations/components/another-gts.gts.d.ts", + "declarations/components/another-gts.gts.d.ts.map", + "declarations/components/template-import.gts.d.ts", + "declarations/components/template-import.gts.d.ts.map", + "declarations/services/example.d.ts", + "declarations/services/example.d.ts.map", + ] + `); + }); + + it('test', async () => { + let testResult = await commandSucceeds(`${packageManager} run test`); + + console.log(testResult.stdout); + expect(testResult.stdout).to.include('# tests 2'); + expect(testResult.stdout).to.include('# pass 2'); + expect(testResult.stdout).to.include('# fail 0'); + }); }); }); }