Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add some fixture utils ... #151

Merged
merged 10 commits into from
Jul 17, 2023
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
files/
tests/fixtures/
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tests/fixtures/
51 changes: 50 additions & 1 deletion tests/assertions.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import fse from 'fs-extra';
import fs from 'node:fs/promises';
import path from 'node:path';
import { expect } from 'vitest';

import { packageJsonAt } from './utils.js';
import { fixture, packageJsonAt } from './utils.js';

interface AssertGeneratedOptions {
projectRoot: string;
Expand Down Expand Up @@ -50,4 +51,52 @@ export async function assertGeneratedCorrectly({

expect(await fse.pathExists(pathToFile), `${pathToFile} exists`).toBe(true);
}

await matchesFixture('.prettierrc.js', { cwd: projectRoot });
}

export async function matchesFixture(
/**
* Project-relative file to test against
*/
testFilePath: string,
options?: {
/**
* Which fixture set to use
*/
scenario?: string;
NullVoxPopuli marked this conversation as resolved.
Show resolved Hide resolved
/**
* 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;
NullVoxPopuli marked this conversation as resolved.
Show resolved Hide resolved
}
) {
let scenario = options?.scenario ?? 'default';
let fixtureFile = options?.file ?? testFilePath;

if (options?.cwd) {
testFilePath = path.join(options.cwd, testFilePath);
}

let sourceContents = (await fs.readFile(testFilePath)).toString();
let fixtureContents = await fixture(fixtureFile, { scenario });

/**
* We trim because whether or not the source or fixture has
* leading / trailing invisible characters is of no significance
* and is mostly a bother to get correct in testing
*/
expect(sourceContents.trim()).to.equal(
fixtureContents.trim(),
`${testFilePath} matches ${fixtureFile}`
);
}
5 changes: 5 additions & 0 deletions tests/fixtures/default/.prettierrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use strict';

module.exports = {
singleQuote: true,
};
3 changes: 2 additions & 1 deletion tests/smoke-tests/--typescript.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import fs from 'node:fs/promises';
import path from 'node:path';
import { afterAll, beforeAll, describe, expect, it } from 'vitest';

Expand Down Expand Up @@ -34,7 +35,7 @@ for (let packageManager of SUPPORTED_PACKAGE_MANAGERS) {
});

afterAll(async () => {
// await fs.rm(tmpDir, { recursive: true, force: true });
await fs.rm(tmpDir, { recursive: true, force: true });
});

it('was generated correctly', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,10 @@ import path from 'node:path';
import { afterAll, beforeAll, describe, expect, it } from 'vitest';

import { assertGeneratedCorrectly } from '../../assertions.js';
import { createAddon, createTmp, install, runScript } from '../../utils.js';
import { createAddon, createTmp, fixture, install, runScript } from '../../utils.js';

let commonFixtures = {
'.prettierrc.js':
// prettier-ignore
'module.exports = {' +
' singleQuote: true,' +
'};',
'.prettierrc.js': await fixture('.prettierrc.js'),
};

describe('custom locations', () => {
Expand Down
7 changes: 2 additions & 5 deletions tests/smoke-tests/within-existing-monorepo/defaults.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,14 @@ import { assertGeneratedCorrectly } from '../../assertions.js';
import {
createAddon,
createTmp,
fixture,
install,
runScript,
SUPPORTED_PACKAGE_MANAGERS,
} from '../../utils.js';

let commonFixtures = {
'.prettierrc.js':
// prettier-ignore
'module.exports = {' +
' singleQuote: true,' +
'};',
'.prettierrc.js': await fixture('.prettierrc.js'),
};

for (let packageManager of SUPPORTED_PACKAGE_MANAGERS) {
Expand Down
29 changes: 29 additions & 0 deletions tests/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { type Options, execa } from 'execa';
import fse from 'fs-extra';
import assert from 'node:assert';
import fs from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
Expand All @@ -8,9 +9,37 @@ import { fileURLToPath } from 'node:url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));

const blueprintPath = path.join(__dirname, '..');
const fixturesPath = path.join(__dirname, 'fixtures');

export const SUPPORTED_PACKAGE_MANAGERS = ['npm', 'yarn', 'pnpm'] as const;

export async function fixture(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was not sure what this is doing when seeing it used in code, like generating a fixture, asserting against one, or reading it (which is happening here). Maybe rename to 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';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like that the default is the default value for scenario here, because it matters what folder you put the test file in. I feel like you could make this just a plain argument of the function and make it required, rather than part of the options and making it optional

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, I don't find default being the default too surprising 🙃

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);
NullVoxPopuli marked this conversation as resolved.
Show resolved Hide resolved

return contents.toString();
}

export async function createTmp() {
let prefix = 'v2-addon-blueprint--';
let prefixPath = path.join(os.tmpdir(), prefix);
Expand Down