diff --git a/index.ts b/index.ts index 0068dad..8762ab3 100644 --- a/index.ts +++ b/index.ts @@ -32,6 +32,8 @@ export type CallbackMutateProject = (project: Project) => void | Promise; */ export type CallbackDefineTests = (scenario: Scenario) => void; +type SkippableVariant = { status: 'active' | 'skipped', project: CallbackMutateProject[]}; + export { Project }; type State = @@ -42,7 +44,7 @@ type State = | { type: 'derived'; parent: Scenarios; - variants: Record; + variants: Record; }; /** @@ -167,7 +169,7 @@ export class Scenarios { type: 'derived', parent: this, variants: Object.fromEntries( - Object.entries(variants).map(([variantName, mutator]) => [variantName, [mutator]]) + Object.entries(variants).map(([variantName, mutator]) => [variantName, { status: 'active', project: [mutator]}]) ), }); } @@ -189,7 +191,7 @@ export class Scenarios { ); } let variants = Object.assign({}, this.state.variants); - delete variants[variantName]; + variants[variantName].status = 'skipped'; return new Scenarios({ type: 'derived', parent: this.state.parent, @@ -255,7 +257,7 @@ export class Scenarios { type: 'derived', parent: this, variants: { - [name]: [callbackMutateProject], + [name]: { status: 'active', project: [callbackMutateProject]}, }, }); } else { @@ -263,9 +265,9 @@ export class Scenarios { type: 'derived', parent: this.state.parent, variants: Object.fromEntries( - Object.entries(this.state.variants).map(([variantName, mutators]) => [ + Object.entries(this.state.variants).map(([variantName, variant]) => [ `${variantName}-${name}`, - [...mutators, callbackMutateProject], + { status: variant.status, project: [...variant.project, callbackMutateProject]}, ]) ), }); @@ -284,12 +286,15 @@ export class Scenarios { } else { let state = this.state; this.state.parent.iterate((parent) => { - for (let [variantName, mutators] of Object.entries(state.variants)) { + for (let [variantName, variant] of Object.entries(state.variants)) { + if(variant.status === 'skipped') { + continue; + } let combinedName = parent.name ? `${parent.name}-${variantName}` : variantName; fn({ name: combinedName, callbackCreateProject: parent.callbackCreateProject, - mutators: [...parent.mutators, ...mutators], + mutators: [...parent.mutators, ...variant.project], }); } }); diff --git a/list.ts b/list.ts index 3422f31..2383004 100644 --- a/list.ts +++ b/list.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ import { Scenario } from './index.js'; import glob from 'glob'; import { resolve } from 'path'; @@ -15,8 +16,11 @@ export interface ListParams { export async function list(params: ListParams): Promise { if (params.require) { for (let r of params.require) { + // @ts-ignore this doesn't actually fail since we're checking before using it if(import.meta.url) { + // @ts-ignore const require = createRequire(import.meta.url); + // @ts-ignore this will only happen if we have import.meta.url await import(require.resolve(r, { paths: [process.cwd()]})); } else { require(require.resolve(r, { paths: [process.cwd()]})); @@ -25,7 +29,9 @@ export async function list(params: ListParams): Promise { } for (let pattern of params.files) { for (let file of globSync(pattern)) { + // @ts-ignore if(import.meta.url) { + // @ts-ignore await import(resolve(file)); } else { require(resolve(file)); diff --git a/package.json b/package.json index c5fff59..dc2f155 100644 --- a/package.json +++ b/package.json @@ -31,13 +31,13 @@ "dist/" ], "scripts": { - "build": "yarn tsup cli.ts index.ts list.ts output.ts --tsconfig tsconfig.esm.json --dts --format esm,cjs", + "build": "pnpm tsup cli.ts index.ts list.ts output.ts --tsconfig tsconfig.esm.json --dts --format esm,cjs", "docs": "typedoc --tsconfig tsconfig.esm.json index.ts --out typedoc/", - "docs:dev": "concurrently \"yarn docs:watch\" \"yarn docs:serve\"", + "docs:dev": "concurrently \"pnpm docs:watch\" \"pnpm docs:serve\"", "docs:serve": "browser-sync start --server \"typedoc/\" --files \"**/*.html\"", - "docs:watch": "yarn docs -- --watch", + "docs:watch": "pnpm docs -- --watch", "lint": "eslint '*.ts'", - "prepare": "yarn build", + "prepare": "pnpm build", "start": "tsc --watch", "test": "concurrently --no-color \"npm:test:*\" --names \"test:\"", "test:cjs": "qunit tests/test.cjs", @@ -79,8 +79,7 @@ "typescript": "^5.1.6" }, "volta": { - "node": "18.17.0", - "yarn": "1.22.18" + "node": "18.17.0" }, "publishConfig": { "registry": "https://registry.npmjs.org" diff --git a/test-modules.mjs b/test-modules.mjs deleted file mode 100644 index 1257fd6..0000000 --- a/test-modules.mjs +++ /dev/null @@ -1,89 +0,0 @@ -import { Project } from 'fixturify-project'; -import { Scenarios } from './index.js'; -import Qunit from 'qunit'; -import child_process from 'child_process'; - -function hello1(project) { - project.linkDependency('hello', { - baseDir: './fixtures', - resolveName: 'hello1', - }); -} - -function hello2(project) { - project.linkDependency('hello', { - baseDir: './fixtures', - resolveName: 'hello', - }); -} - -const scenarios = Scenarios.fromDir('./fixtures/app').expand({ - hello1, - hello2, -}); - -scenarios.forEachScenario((scenario) => { - Qunit.module(scenario.name, (hooks) => { - hooks.before(async function ({ app }) { - this.app = await scenario.prepare(); - }); - - Qunit.test( - 'yarn test', - async function (assert) { - const result = await this.app.execute('yarn --silent test'); - assert.equal( - result.stdout, - `TAP version 13 -ok 1 project > createHello -1..1 -# pass 1 -# skip 0 -# todo 0 -# fail 0 -` - ); - } - ); - - Qunit.test( - 'yarn bin inside app', - async function (assert) { - let result = await this.app.execute('yarn --silent bin'); - const yarnBin = result.stdout.trimRight(); - assert.ok(yarnBin.startsWith(this.app.dir)); - result = await this.app.execute('yarn --silent exec which qunit'); - assert.ok(result.stdout.startsWith(yarnBin)); - } - ); - - Qunit.test( - 'check scenario', - async function (assert) { - let result = await this.app.execute( - `node -p 'require("./index").polyfilled'` - ); - assert.equal( - result.stdout.trim(), - ('hello1' === scenario.name).toString() - ); - } - ); - }); -}); - -Qunit.module('cli', () => { - Qunit.test('list', (assert) => { - assert.deepEqual( - child_process - .execFileSync( - process.execPath, - ['cli.js', 'list', '--files', 'test-modules.mjs', '--matrix'], - { encoding: 'utf8' } - ) - .trimRight() - .split('\n'), - ['hello1', 'hello2'] - ); - }); -}); diff --git a/tests/test.cjs b/tests/test.cjs index b3e5c69..61ed724 100644 --- a/tests/test.cjs +++ b/tests/test.cjs @@ -17,17 +17,27 @@ function hello2(project) { resolveName: 'hello', }); } + +function skipMe(project) { + // do nothing +} + const scenarios = Scenarios.fromDir('./tests/fixtures/app').expand({ hello1, hello2, + skipMe, }); -scenarios.forEachScenario((scenario) => { + +scenarios + .skip('skipMe') + .skip('skipMe') // show that skipping twice doesn't crash + .forEachScenario((scenario) => { qunit.module(scenario.name, (hooks) => { hooks.before(async function () { this.app = await scenario.prepare(); }); - qunit.test('yarn test', async function (assert) { - const result = await this.app.execute('yarn --silent test'); + qunit.test('pnpm test', async function (assert) { + const result = await this.app.execute('pnpm --silent test'); assert.equal(result.stdout, `TAP version 13 ok 1 project > createHello 1..1 @@ -37,13 +47,6 @@ ok 1 project > createHello # fail 0 `); }); - qunit.test('yarn bin inside app', async function (assert) { - let result = await this.app.execute('yarn --silent bin'); - const yarnBin = result.stdout.trimRight(); - assert.ok(yarnBin.startsWith(this.app.dir)); - result = await this.app.execute('yarn --silent exec which qunit'); - assert.ok(result.stdout.startsWith(yarnBin)); - }); qunit.test('check scenario', async function (assert) { let result = await this.app.execute(`node -p 'require("./index").polyfilled'`); assert.equal(result.stdout.trim(), ('hello1' === scenario.name).toString()); diff --git a/tests/test.mjs b/tests/test.mjs index c88c28b..6b99b20 100644 --- a/tests/test.mjs +++ b/tests/test.mjs @@ -16,22 +16,30 @@ function hello2(project) { }); } +function skipMe(project) { + // do nothing +} + const scenarios = Scenarios.fromDir('./tests/fixtures/app').expand({ hello1, hello2, + skipMe, }); -scenarios.forEachScenario((scenario) => { +scenarios + .skip('skipMe') + .skip('skipMe') // show that skipping twice doesn't crash + .forEachScenario((scenario) => { Qunit.module(scenario.name, (hooks) => { hooks.before(async function () { this.app = await scenario.prepare(); }); Qunit.test( - 'yarn test', + 'pnpm test', async function (assert) { - const result = await this.app.execute('yarn --silent test'); + const result = await this.app.execute('pnpm --silent test'); assert.equal( result.stdout, `TAP version 13 @@ -46,16 +54,6 @@ ok 1 project > createHello } ); - Qunit.test( - 'yarn bin inside app', - async function (assert) { - let result = await this.app.execute('yarn --silent bin'); - const yarnBin = result.stdout.trimRight(); - assert.ok(yarnBin.startsWith(this.app.dir)); - result = await this.app.execute('yarn --silent exec which qunit'); - assert.ok(result.stdout.startsWith(yarnBin)); - } - ); Qunit.test( 'check scenario', diff --git a/tests/test.ts b/tests/test.ts index 38b18cd..ec29a9e 100644 --- a/tests/test.ts +++ b/tests/test.ts @@ -18,23 +18,31 @@ function hello2(project: Project) { }); } +function skipMe(/* project: Project */) { + // do nothing +} + const scenarios = Scenarios.fromDir('./tests/fixtures/app').expand({ hello1, hello2, + skipMe, }); type TestContext = { app: PreparedApp }; -scenarios.forEachScenario((scenario) => { +scenarios + .skip('skipMe') + .skip('skipMe') // show that skipping twice doesn't crash + .forEachScenario((scenario) => { Qunit.module(scenario.name, (hooks) => { hooks.before(async function (this: TestContext) { this.app = await scenario.prepare(); }); Qunit.test( - 'yarn test', + 'pnpm test', async function (this: TestContext, assert) { - const result = await this.app.execute('yarn --silent test'); + const result = await this.app.execute('pnpm --silent test'); assert.equal( result.stdout, `TAP version 13 @@ -49,17 +57,6 @@ ok 1 project > createHello } ); - Qunit.test( - 'yarn bin inside app', - async function (this: TestContext, assert) { - let result = await this.app.execute('yarn --silent bin'); - const yarnBin = result.stdout.trimRight(); - assert.ok(yarnBin.startsWith(this.app.dir)); - result = await this.app.execute('yarn --silent exec which qunit'); - assert.ok(result.stdout.startsWith(yarnBin)); - } - ); - Qunit.test( 'check scenario', async function (this: TestContext, assert) {