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

test(cli): migrate sandbox to verdaccio #279

Merged
merged 43 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
5b3b9a2
test(e2e): setup e2e base
ChristopherPHolder Apr 27, 2024
a1bc17f
test(e2e): setup e2e exec process base
ChristopherPHolder Apr 27, 2024
2df8c1c
test(e2e): setup local registry
ChristopherPHolder Apr 27, 2024
0b063b0
fix(workspace): migrate nx
ChristopherPHolder Aug 23, 2024
adbed43
fix(workspace): migrate nx
ChristopherPHolder Aug 23, 2024
2189443
fix(workspace): migrate e2e test
ChristopherPHolder Aug 24, 2024
f70944c
fix(workspace): remove migration file
ChristopherPHolder Aug 24, 2024
51c691a
fix(workspace): upgrade packages
ChristopherPHolder Aug 24, 2024
e7ce539
fix(workspace): fix build nx-plugin-integration
ChristopherPHolder Aug 25, 2024
51f5ca3
fix(workspace): remove source build issue
ChristopherPHolder Aug 25, 2024
9686b25
fix(workspace): remove source build issue
ChristopherPHolder Aug 25, 2024
653d5cc
fix(workspace): reset lock
ChristopherPHolder Aug 25, 2024
3d6e410
fix(workspace): upgrade vite
ChristopherPHolder Aug 25, 2024
3f8dad6
fix(workspace): lock fixing
ChristopherPHolder Aug 25, 2024
7c0ddb4
fix(workspace): lock fixing
ChristopherPHolder Aug 25, 2024
c95cd01
fix(workspace): fix build issue
ChristopherPHolder Aug 25, 2024
0d41c57
fix(workspace): remove budgets
ChristopherPHolder Aug 25, 2024
841b22b
fix(workspace): allow mts format
ChristopherPHolder Aug 25, 2024
db59173
fix(workspace): migrate init test
ChristopherPHolder Aug 25, 2024
d741f8b
fix(workspace): migrate init rc-config test
ChristopherPHolder Aug 25, 2024
cdc99dd
fix(workspace): migrate init rc-config test
ChristopherPHolder Aug 25, 2024
aedde71
fix(workspace): migrate test
ChristopherPHolder Aug 25, 2024
c5a6b53
fix(workspace): migrate test
ChristopherPHolder Aug 25, 2024
1a87553
fix(workspace): migrate test
ChristopherPHolder Aug 25, 2024
dc1ac39
fix(workspace): migrate test
ChristopherPHolder Aug 25, 2024
e6245ca
fix(workspace): migrate test
ChristopherPHolder Aug 25, 2024
54d3b52
fix(workspace): migrate test
ChristopherPHolder Aug 25, 2024
633869a
fix(workspace): migrate test
ChristopherPHolder Aug 25, 2024
a6403c0
fix(workspace): migrate test
ChristopherPHolder Aug 25, 2024
c39117f
fix(workspace): migrate test
ChristopherPHolder Aug 25, 2024
1e11849
fix(workspace): migrate test
ChristopherPHolder Aug 26, 2024
78d6839
fix(workspace): migrate test
ChristopherPHolder Aug 26, 2024
d3be6f8
fix(workspace): migrate test
ChristopherPHolder Aug 26, 2024
d099694
fix(workspace): migrate test
ChristopherPHolder Aug 26, 2024
4eb5fd1
fix(workspace): migrate test
ChristopherPHolder Aug 26, 2024
727934c
fix(workspace): e2e target to test
ChristopherPHolder Aug 26, 2024
3502f27
fix(workspace): remove unnecessry config
ChristopherPHolder Aug 26, 2024
67e2d76
fix(workspace): fix headless bug
ChristopherPHolder Aug 26, 2024
81df6fe
fix(workspace): fix e2e preset issues
ChristopherPHolder Aug 26, 2024
7d90f8e
fix(workspace): fix gh e2e
ChristopherPHolder Aug 26, 2024
5c3cd5a
fix(workspace): remove unused test
ChristopherPHolder Aug 26, 2024
9145527
fix(workspace): remove unused test
ChristopherPHolder Aug 26, 2024
d3bb69e
fix(workspace): remove unused test
ChristopherPHolder Aug 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ testem.log
.DS_Store
Thumbs.db

.nx/cache
.nx

.env
.code-pushup
3 changes: 2 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
/dist
/coverage

/.nx/cache
/.nx/cache
/.nx/workspace-data
28 changes: 28 additions & 0 deletions .verdaccio/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# path to a directory with all packages
storage: ../tmp/local-registry/storage

# a list of other known repositories we can talk to
uplinks:
npmjs:
url: https://registry.npmjs.org/
maxage: 60m

packages:
'**':
# give all users (including non-authenticated users) full access
# because it is a local registry
access: $all
publish: $all
unpublish: $all

# if package is not available locally, proxy requests to npm registry
proxy: npmjs

# log settings
log:
type: stdout
format: pretty
level: warn

publish:
allow_offline: true # set offline to true to allow publish offline
File renamed without changes.
21 changes: 21 additions & 0 deletions e2e/cli-e2e/mocks/user-flows/basic-navigation.uf.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// @ts-ignore // This is a mock file!
import { UserFlowContext, UserFlowInteractionsFn, UserFlowProvider } from '@push-based/user-flow';

const interactions: UserFlowInteractionsFn = async (ctx: UserFlowContext): Promise<any> => {
const { flow, collectOptions } = ctx;
const { url } = collectOptions;

await flow.navigate(url, {
name: `Navigate to ${url}`,
});

// ℹ Tip:
// Read more about the other measurement modes here:
// https://github.com/push-based/user-flow/blob/main/packages/cli/docs/writing-basic-user-flows.md

};

export default {
flowOptions: {name: 'Basic Navigation Example'},
interactions
} satisfies UserFlowProvider;
25 changes: 25 additions & 0 deletions e2e/cli-e2e/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "cli-e2e",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "examples/cli-e2e/src",
"projectType": "application",
"targets": {
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["e2e/cli-e2e/**/*.ts"]
}
},
"test": {
"executor": "@nx/vite:test",
"options": {
"config": "e2e/cli-e2e/vite.config.e2e.mts"
}
}
},
"implicitDependencies": [
"cli"
],
"tags": ["type:e2e"]
}
135 changes: 135 additions & 0 deletions e2e/cli-e2e/setup.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import { afterAll, beforeAll, beforeEach, afterEach } from 'vitest';

import { cpSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
import { join, normalize, sep } from 'node:path';

import { CliTest, E2E_DIR, normalizePath } from './utils/setup';
import { spawn } from 'node:child_process';

const ANSI_ESCAPE_REGEX = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;

function filePath(p: string): string {
const paths = normalizePath(p).split(sep);
return paths.splice(0, paths.length - 1).join();
}

beforeAll((ctx) => {
mkdirSync(join(E2E_DIR, filePath(ctx.name)), { recursive: true });
});

beforeEach<CliTest>((ctx) => {
ctx.root = join(E2E_DIR, filePath(ctx.task.file.name), normalizePath(join(ctx.task.suite.name, ctx.task.name)));

ctx.setupFns = {
setupRcJson: (rc: {}, rcName= `.user-flowrc.json`) => {
writeFileSync(
join(ctx.root, rcName),
JSON.stringify(rc, null, 4),
{ encoding: 'utf8' }
);
},
setupUserFlows: (mockUserFlow: string, userFlowDir = 'user-flows') => {
cpSync(mockUserFlow, join(ctx.root, userFlowDir, normalize(mockUserFlow).split(sep).at(-1)))
}
}

mkdirSync(ctx.root, { recursive: true });
});

export type CliProcessResult = {
stdout: string;
stderr: string;
code: number | null;
}

beforeEach<CliTest>((ctx) => {
ctx.cli = {} as any;
ctx.cli.stdout = '';
ctx.cli.stderr = '';
ctx.cli.code = null;


ctx.cli.run = (command: string, args: string[] = [], waitForClose = true) => new Promise<CliProcessResult>((resolve) => {
ctx.cli.process = spawn(command, args, { stdio: 'pipe', shell: true, cwd: ctx.root });

ctx.cli.process.stdout.on('data', (data) => {
const stdout = String(data).replace(ANSI_ESCAPE_REGEX, '');

if (ctx.cli.verbose) {
console.log(stdout);
}

ctx.cli.stdout += stdout;
});


ctx.cli.process.stderr.on('data', (data) => {
const stderr = String(data).replace(ANSI_ESCAPE_REGEX, '');

if (ctx.cli.verbose) {
console.log(stderr);
}

ctx.cli.stderr += stderr;
});


ctx.cli.process.on('close', code => {
ctx.cli.code = code;

if (ctx.cli.verbose) {
console.log(code);
}

resolve({
stdout: ctx.cli.stdout,
stderr: ctx.cli.stderr,
code: ctx.cli.code
});
});

if (!waitForClose) {
resolve({
stdout: ctx.cli.stdout,
stderr: ctx.cli.stderr,
code: ctx.cli.code
});
}
});

ctx.cli.waitForStdout = (expectedStdout: string) => {
return new Promise((resolve) => {
ctx.cli.process.stdout.on('data', (data) => {
const stdout = String(data).replace(ANSI_ESCAPE_REGEX, '');
if (stdout.includes(expectedStdout)) {
resolve();
}
});
});
};

ctx.cli.waitForClose = () => {
return new Promise((resolve) => {
ctx.cli.process.on('close', (code) => {
ctx.cli.code = code;
resolve({
stdout: ctx.cli.stdout,
stderr: ctx.cli.stderr,
code: ctx.cli.code
});
});
});
};

ctx.cli.type = (inputs: string) => {
ctx.cli.process.stdin.write(inputs);
};
});

afterEach<CliTest>((ctx) => {
rmSync(ctx.root, { recursive: true });
});

afterAll((ctx) => {
rmSync(join(E2E_DIR, filePath(ctx.name)), { recursive: true });
});
47 changes: 47 additions & 0 deletions e2e/cli-e2e/tests/__snapshots__/help.e2e.test.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`user-flow help > should print global help 1`] = `
"cli.js

Run a set of user flows and save the result

Commands:
cli.js init Setup .user-flowrc.json
cli.js collect Run a set of user flows and save the result
cli.js Run a set of user flows and save the result [default]
cli.js assert Setup .user-flowrc.json

Options:
--version Show version number [boolean]
-v, --verbose Run with verbose logging [boolean] [default: false]
-p, --rcPath Path to user-flow.config.json. e.g.
\`./user-flowrc.json\`
[string] [default: ".user-flowrc.json"]
-i, --interactive When false questions are skipped with the values from
the suggestions. This is useful for CI integrations.
[boolean] [default: true]
-t, --url URL to analyze [string]
-u, --ufPath folder containing user-flow files to run. (\`*.uf.ts\`
or \`*.uf.js\`) [string]
-l, --config Lighthouse configuration (RC file only) [string]
-c, --configPath Path to Lighthouse configuration e.g config.json
[string]
-s, --serveCommand The npm command to serve your application. e.g. "npm
run serve:prod" [string]
-w, --awaitServeStdout A string in stdout resulting from serving the app, to
be awaited before start running the tests. e.g.
"server running..." [string]
-d, --dryRun Execute commands without effects [boolean]
-o, --outPath output folder for the user-flow reports [string]
-f, --format Report output formats e.g. JSON
[array] [choices: "html", "json", "md", "stdout"]
-e, --openReport Opens browser automatically after the user-flow is
collected. (true by default) [boolean] [default: true]
-k, --budgetPath Path to budgets.json [string]
-j, --budgets Performance budgets (RC file only) [array]
-h, --help Show help [boolean]

Examples:
init Setup user-flows over prompts
"
`;
52 changes: 52 additions & 0 deletions e2e/cli-e2e/tests/collect/config.e2e.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { describe, expect } from 'vitest';
import { CliTest, DEFAULT_RC, USER_FLOW_MOCKS } from '../../utils/setup';
import { writeFileSync } from 'node:fs';
import { join } from 'node:path';

describe('collect config', () => {

it<CliTest>('should log LH config from a user flow', async ({ setupFns, cli }) => {
setupFns.setupRcJson(DEFAULT_RC);
setupFns.setupUserFlows(USER_FLOW_MOCKS.BASIC);

const { code, stdout, stderr } = await cli.run('user-flow', ['collect', '--verbose', '--dry-run'])

expect(stdout).toContain('LH Configuration is used from a user flow file');
expect(stderr).toBe('');
expect(code).toBe(0);
});

it<CliTest>('should throw is invalid path to LH config', async ({ setupFns, cli }) => {
setupFns.setupRcJson(DEFAULT_RC);
setupFns.setupUserFlows(USER_FLOW_MOCKS.BASIC);

const { code, stdout, stderr } = await cli.run('user-flow', [
'collect',
'--configPath ./invalid/path/to/config.json',
'--verbose',
'--dry-run'
]);

expect(stderr).toContain('Error: ./invalid/path/to/config.json does not exist.');
expect(code).toBe(1);
});

it<CliTest>('should load configPath from RC file', async ({ root, setupFns, cli }) => {
const rc = structuredClone(DEFAULT_RC);
// @ts-ignore
rc.collect['configPath'] = './lh-config.json';
setupFns.setupRcJson(rc);
setupFns.setupUserFlows(USER_FLOW_MOCKS.BASIC);

writeFileSync(join(root, './lh-config.json'), JSON.stringify({
extends: 'lighthouse:default',
settings: { onlyAudits: ['lcp-lazy-loaded'] }
}));

const { code, stdout, stderr } = await cli.run('user-flow', ['collect', '--verbose']);

expect(stdout).toContain('LH Configuration ./lh-config.json is used from CLI param or .user-flowrc.json');
expect(stderr).toBe('');
expect(code).toBe(0);
});
});
31 changes: 31 additions & 0 deletions e2e/cli-e2e/tests/collect/dry-run.e2e.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { describe, expect, it } from 'vitest';

import { CliTest, DEFAULT_RC, USER_FLOW_MOCKS } from '../../utils/setup';

describe('collect --dry-run', () => {

it<CliTest>('should run user-flow', async ({ cli, setupFns }) => {
setupFns.setupRcJson(DEFAULT_RC);
setupFns.setupUserFlows(USER_FLOW_MOCKS.BASIC);

const { code, stdout, stderr } = await cli.run('user-flow', ['collect', '--dry-run']);

expect(stderr).toBe('');
expect(stdout).toBe('');
expect(code).toBe(0);
});
});

describe('collect --dry-run --verbose', () => {

it<CliTest>('should run user-flow and log', async ({ cli, setupFns }) => {
setupFns.setupRcJson(DEFAULT_RC);
setupFns.setupUserFlows(USER_FLOW_MOCKS.BASIC);

const { code, stdout, stderr } = await cli.run('user-flow', ['collect', '--dry-run', '--verbose']);

expect(stderr).toBe('');
expect(stdout).not.toBe('');
expect(code).toBe(0);
});
});
Loading
Loading