-
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
- Loading branch information
1 parent
6ea52bc
commit aa1bb47
Showing
7 changed files
with
212 additions
and
61 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
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,115 @@ | ||
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. | ||
* tl;dr: | ||
* it's a wrapper around ember addon -b (so we can pass our flags with less duplication) | ||
* it lets us set compare against a fixture set / scenario | ||
* | ||
* 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[]; | ||
#fixtures: AddonFixtureHelper | undefined; | ||
|
||
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 is the project root | ||
this.#cwd = path.join(this.#tmpDir, name); | ||
|
||
this.#fixtures = new AddonFixtureHelper({ cwd: this.#cwd, scenario: this.#scenario }); | ||
} | ||
|
||
async run(scriptName: string) { | ||
return await runScript({ | ||
cwd: this.cwd, | ||
script: scriptName, | ||
packageManager: this.#packageManager, | ||
}); | ||
} | ||
|
||
async build() { | ||
return this.run('build'); | ||
} | ||
|
||
async clean() { | ||
if (DEBUG) return; | ||
|
||
assert( | ||
this.#tmpDir, | ||
"Cannot clean without a tmpDir. Was the Addon 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 Addon Helper's `setup` method called?"); | ||
|
||
return this.#cwd; | ||
} | ||
|
||
get fixtures() { | ||
assert(this.#fixtures, 'Cannot get fixtures-helper. Was the Addon Helper `setup`?'); | ||
|
||
return this.#fixtures; | ||
} | ||
} | ||
|
||
export class AddonFixtureHelper { | ||
#cwd: string; | ||
#scenario: string; | ||
|
||
constructor(options: { cwd: string; scenario?: string }) { | ||
this.#cwd = options.cwd; | ||
this.#scenario = options.scenario || 'default'; | ||
} | ||
|
||
async use(file: string) { | ||
await copyFixture(file, { scenario: this.#scenario, cwd: this.#cwd }); | ||
} | ||
|
||
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