-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
setting up an addon-creating helper so we can more easily manage the …
…creation of addons will need to propagate through the existing tests but that can happen in other PRs
1 parent
6ea52bc
commit e524cc5
Showing
6 changed files
with
194 additions
and
57 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import fse from 'fs-extra'; | ||
import assert from 'node:assert'; | ||
import fs from 'node:fs/promises'; | ||
import path from 'node:path'; | ||
import { fileURLToPath } from 'node:url'; | ||
|
||
const __dirname = path.dirname(fileURLToPath(import.meta.url)); | ||
|
||
const fixturesPath = path.join(__dirname, 'fixtures'); | ||
|
||
/** | ||
* Returns the contents of a file from the "tests/fixtures" directory. | ||
* The "tests/fixtures" directory contains sub-directories, "scenarios". | ||
* This is we can have different sets of fixtures, depending on what we're testing. | ||
* | ||
* The default scenario is "default", and represents the the file contents when we provide | ||
* no arguments to the blueprint | ||
*/ | ||
export async function readFixture( | ||
/** | ||
* Which file within in the fixture-set / scenario to read | ||
*/ | ||
file: string, | ||
options?: { | ||
/** | ||
* Which fixture set to use | ||
*/ | ||
scenario?: string; | ||
} | ||
) { | ||
let scenario = options?.scenario ?? 'default'; | ||
let fixtureFilePath = path.isAbsolute(file) ? file : path.join(fixturesPath, scenario, file); | ||
|
||
let exists = await fse.pathExists(fixtureFilePath); | ||
|
||
assert( | ||
exists, | ||
`Fixture file '${file}' does not exist. To make this work, place a new file '${file}' in the 'tests/fixtures/${scenario}' directory. Checked the absolute path: '${fixtureFilePath}'.` | ||
); | ||
|
||
let contents = await fs.readFile(fixtureFilePath); | ||
|
||
return contents.toString(); | ||
} | ||
|
||
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 readFixture(fixtureFile, { scenario }); | ||
|
||
await fse.mkdir(path.dirname(newFile), { recursive: true }); | ||
await fs.writeFile(newFile, fixtureContents); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
import assert from 'node:assert'; | ||
import fs from 'node:fs/promises'; | ||
import path from 'node:path'; | ||
|
||
import { matchesFixture } from './assertions.js'; | ||
import { copyFixture } from './fixtures.js'; | ||
import { createAddon, createTmp, install, runScript } from './utils.js'; | ||
|
||
const DEBUG = process.env.DEBUG === 'true'; | ||
|
||
/** | ||
* Helps with common addon testing concerns. | ||
* | ||
* To DEBUG the intermediate output (in tmp), | ||
* re-start your tests with `DEBUG=true`, and the tmpdir will be printed | ||
* as well as the `clean` function will not run so that if a test finishes, | ||
* you can still inspect the folder contents | ||
* | ||
*/ | ||
export class AddonHelper { | ||
#cwd?: string; | ||
#tmpDir?: string; | ||
#scenario: string; | ||
#packageManager: 'npm' | 'pnpm' | 'yarn'; | ||
#args: string[]; | ||
|
||
constructor(options: { | ||
args?: string[]; | ||
scenario?: string; | ||
packageManager: 'pnpm' | 'npm' | 'yarn'; | ||
}) { | ||
this.#args = options.args || []; | ||
this.#scenario = options.scenario || 'default'; | ||
this.#packageManager = options.packageManager; | ||
} | ||
|
||
async setup() { | ||
this.#tmpDir = await createTmp(); | ||
|
||
if (DEBUG) { | ||
console.debug(`Debug test repo at ${this.#tmpDir}`); | ||
} | ||
|
||
let { name } = await createAddon({ | ||
args: this.#args, | ||
options: { cwd: this.#tmpDir }, | ||
}); | ||
|
||
this.#cwd = path.join(this.#tmpDir, name); | ||
} | ||
|
||
async clean() { | ||
if (DEBUG) return; | ||
|
||
assert( | ||
this.#tmpDir, | ||
"Cannot clean without a tmpDir. Was the Helper's `setup` method called to generate the addon?" | ||
); | ||
|
||
await fs.rm(this.#tmpDir, { recursive: true, force: true }); | ||
} | ||
|
||
async installDeps() { | ||
await install({ cwd: this.cwd, packageManager: this.#packageManager, skipPrepare: true }); | ||
} | ||
|
||
get cwd() { | ||
assert(this.#cwd, "Cannot get cwd. Was the Helper's `setup` method called?"); | ||
|
||
return this.#cwd; | ||
} | ||
} | ||
|
||
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 }); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters