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(esbuild-meta): add e2e test to pipeline #94

Merged
merged 12 commits into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
118 changes: 57 additions & 61 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,35 +73,34 @@ jobs:
- name: Lint Affected
run: npx nx affected --target=lint --parallel=3

# Commented out because its hanging
# test:
# name: Test Affected
# needs: setup
# runs-on: ubuntu-latest
#
# steps:
# - uses: actions/checkout@v4
# with:
# # We need to fetch all branches and commits so that Nx affected has a base to compare against.
# fetch-depth: 0
# # Derive appropriate SHAs for base and head for `nx affected` commands
# - uses: nrwl/nx-set-shas@v3
# - uses: actions/setup-node@v4
# with:
# node-version: ${{ env.NODE_VERSION }}
# cache: 'npm'
#
# - name: Cache NPM Dependencies
# uses: actions/cache@v4
# with:
# path: |
# node_modules
# ~/.cache
# dist
# key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }}
#
# - name: Test Affected
# run: npx nx affected --target=test --parallel=3
test:
name: Test Affected
needs: setup
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
with:
# We need to fetch all branches and commits so that Nx affected has a base to compare against.
fetch-depth: 0
# Derive appropriate SHAs for base and head for `nx affected` commands
- uses: nrwl/nx-set-shas@v3
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'

- name: Cache NPM Dependencies
uses: actions/cache@v4
with:
path: |
node_modules
~/.cache
dist
key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }}

- name: Test Affected
run: npx nx affected --target=test --parallel=3

build:
name: Build Affected
Expand Down Expand Up @@ -132,6 +131,33 @@ jobs:
- name: Build Affected
run: npx nx affected -t build build-storybook --parallel=3

e2e:
name: E2E Affected
needs: [build]
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: nrwl/nx-set-shas@v3
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'

- name: Cache NPM Dependencies
uses: actions/cache@v4
with:
path: |
node_modules
~/.cache
dist
key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }}

- name: E2E Affected
run: npx nx affected --target=e2e --parallel=3

# publish-storybook:
# name: Publish Storybook
# needs: [build, lint]
Expand Down Expand Up @@ -161,7 +187,7 @@ jobs:

deploy-front-end:
name: Deploy Front-End
needs: [build, lint]
needs: [test, build, lint, e2e]
runs-on: ubuntu-latest

steps:
Expand Down Expand Up @@ -203,7 +229,7 @@ jobs:

deploy-server:
name: Deploy Server
needs: [build, lint]
needs: [test, build, lint, e2e]
runs-on: ubuntu-latest

steps:
Expand Down Expand Up @@ -239,33 +265,3 @@ jobs:
- name: Deploy Prod Server
if: ${{ env.is-main-branch == 'true' }}
run: npx nx affected --target=deploy --exclude='*,!tag:backend' --configuration=production

# release:
# name: Release Affected
# needs: [build, lint]
# runs-on: ubuntu-latest
#
# steps:
# - uses: actions/checkout@v4
# with:
# # We need to fetch all branches and commits so that Nx affected has a base to compare against.
# fetch-depth: 0
# # Derive appropriate SHAs for base and head for `nx affected` commands
# - uses: nrwl/nx-set-shas@v3
# - uses: actions/setup-node@v4
# with:
# node-version: 20
# cache: 'npm'
#
# - name: Cache NPM Dependencies
# uses: actions/cache@v4
# with:
# path: |
# node_modules
# ~/.cache
# dist
# key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }}
#
# - name: Release Affected
## if: ${{ env.is-main-branch == 'true' }}
# run: npx nx affected -t nx-release-publish --parallel=3
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,6 @@ dist

# Nx Cache
.nx

# Temporaty files
tmp
13 changes: 13 additions & 0 deletions global-setup.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { execSync } from 'child_process';
import startLocalRegistry from './tools/scripts/start-local-registry';
import stopLocalRegistry from './tools/scripts/stop-local-registry';

export async function setup() {
await startLocalRegistry();
execSync('npm install -D @app-speed/esbuild-meta@e2e --force');
}

export async function teardown() {
stopLocalRegistry();
execSync('npm uninstall @app-speed/esbuild-meta');
}
6 changes: 5 additions & 1 deletion packages/esbuild-meta/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@
"@nx/dependency-checks": [
"error",
{
"ignoredFiles": ["{projectRoot}/vite.config.{js,ts,mjs,mts}"]
"ignoredFiles": [
"{projectRoot}/e2e/**/*",
"{projectRoot}/vitest.config.e2e.{js,ts,mjs,mts}",
"{projectRoot}/vite.config.{js,ts,mjs,mts}"
]
}
]
}
Expand Down
16 changes: 16 additions & 0 deletions packages/esbuild-meta/e2e/__snapshots__/filter.test.e2e.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`filter command > should have a help option 1`] = `
"esbuild-meta filter

Filters the meta file to only include chunks required by specified entry points

Options:
-s, --statsPath The path to the stats.json file [string] [required]
-o, --outPath The path where the new file should be saved [string] [default: "initial-stats.json"]
--excludeDynamicImports, --eDI Should the dynamic imports be filtered out of the output chunk imports [boolean] [default: false]
-e, --entryPoints Entry points that should be considered for the bundle [array] [default: ["main-","polyfills-"]]
-v, --version Show version number [boolean]
-h, --help Show help [boolean]
"
`;
13 changes: 13 additions & 0 deletions packages/esbuild-meta/e2e/__snapshots__/root.test.e2e.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`--help > should show help 1`] = `
"esbuild-meta [command]

Commands:
esbuild-meta filter Filters the meta file to only include chunks required by specified entry points [aliases: f]

Options:
-v, --version Show version number [boolean]
-h, --help Show help [boolean]
"
`;
28 changes: 28 additions & 0 deletions packages/esbuild-meta/e2e/filter.test.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { describe, expect, it } from 'vitest';
import { cliProcess } from './utils.js';
import { DEMAND_STATS_PATH } from '../src/lib/filter-meta.js';
import { INVALID_FILE_PATH_ERROR_MSG } from '../src/lib/utils.js';

describe('filter command', () => {
it('should have a help option', async () => {
const { stdout, stderr, code } = await cliProcess('esbuild-meta filter --help');
expect(stdout).toMatchSnapshot();
expect(stderr).toBeFalsy();
expect(code).toBe(0);
});

it('should demand stats path option', async () => {
const { stdout, stderr, code } = await cliProcess('esbuild-meta filter');
expect(stderr).toContain(DEMAND_STATS_PATH);
expect(stdout).toBeFalsy();
expect(code).toBe(1);
});

it('should throw if stats path does not point to a file', async () => {
const INVALID_STATS_FILE = 'invalid-path.json';
const { stdout, stderr, code } = await cliProcess(`esbuild-meta filter --statsPath ${INVALID_STATS_FILE}`);
expect(stderr).toContain(INVALID_FILE_PATH_ERROR_MSG('invalid-path.json'));
expect(stdout).toBeFalsy();
expect(code).toBe(1);
});
});
32 changes: 32 additions & 0 deletions packages/esbuild-meta/e2e/root.test.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { describe, it, expect, beforeAll } from 'vitest';
import { version } from '../package.json';

import { cliProcess, CliProcessOutput } from './utils.js';

describe('--help', () => {
let output: CliProcessOutput;

beforeAll(async () => {
output = await cliProcess('esbuild-meta --help');
});

it('should show help', async () => {
const { stdout, stderr, code } = output;
expect(stdout).toMatchSnapshot();
expect(stderr).toBeFalsy();
expect(code).toBe(0);
});

it('should alias to -h', async () => {
expect(await cliProcess('esbuild-meta --help')).toEqual(output);
});
});

describe('--version', () => {
it('should show version', async () => {
const {stdout, stderr, code} = await cliProcess('esbuild-meta --version');
expect(stdout).toContain(version);
expect(stderr).toBeFalsy();
expect(code).toBe(0);
});
});
19 changes: 19 additions & 0 deletions packages/esbuild-meta/e2e/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { spawn } from 'node:child_process';

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

export const cliProcess = (command: string) => {
return new Promise<CliProcessOutput>((resolve) => {
const process = spawn(command, [], { stdio: 'pipe', shell: true });

let stdout = '';
let stderr = '';
process.stdout.on('data', (data) => stdout += String(data));
process.stderr.on('data', (data) => stderr += String(data));
process.on('close', code => resolve({ stdout, stderr, code }));
})
}
17 changes: 13 additions & 4 deletions packages/esbuild-meta/project.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"name": "esbuild-meta",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"root": "packages/esbuild-meta",
"sourceRoot": "packages/esbuild-meta/src",
"projectType": "library",
"tags": [],
"projectType": "app",
"targets": {
"build": {
"executor": "@nx/esbuild:esbuild",
Expand All @@ -17,16 +17,25 @@
"format": ["esm"],
"minify": true,
"platform": "node",
"bundle": true,
"thirdParty": true
"bundle": true
}
},
"lint": {
"executor": "@nx/eslint:lint",
"outputs": ["{options.outputFile}"]
},
"test": {
"executor": "@nx/vite:test",
"outputs": ["{options.reportsDirectory}"],
"options": {
"reportsDirectory": "../../coverage/packages/esbuild-meta"
}
},
"e2e": {
"executor": "@nx/vite:test",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}-e2e"],
"options": { "config": "packages/esbuild-meta/vitest.config.e2e.ts" },
"dependsOn": ["build"]
}
}
}
14 changes: 8 additions & 6 deletions packages/esbuild-meta/src/lib/filter-meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import {
makeJson,
} from './utils.js';

const distPath = {
alias: 'd',
export const DEMAND_STATS_PATH = 'The path to a stats.json file is required';

const statsPath = {
alias: 's',
type: 'string',
default: 'dist',
description: 'The path to the stats.json file'
description: 'The path to the stats.json file',
demandOption: DEMAND_STATS_PATH,
} as const satisfies Options;

const outPath = {
Expand All @@ -37,7 +39,7 @@ const entryPoints = {
description: 'Entry points that should be considered for the bundle',
} as const satisfies Options;

const filterMetaOptions = { distPath, outPath, excludeDynamicImports, entryPoints };
const filterMetaOptions = { statsPath, outPath, excludeDynamicImports, entryPoints };

type FilterMetaOptions = InferredOptionTypes<typeof filterMetaOptions>;
type FilterMetaCommandModule = CommandModule<unknown, FilterMetaOptions>;
Expand All @@ -47,7 +49,7 @@ const filterMetaBuilder: CommandBuilder<unknown, FilterMetaOptions> = (argv: Arg
}

const filterMetaHandler: FilterMetaCommandModule['handler'] = (argv: FilterMetaOptions) => {
const meta = getJson<Metafile>([argv.distPath]);
const meta = getJson<Metafile>(argv.statsPath);
const entryPoints = extractEntryPoints(meta, argv.entryPoints);
filterMetaFromEntryPoints(meta, entryPoints);
if (argv.excludeDynamicImports) {
Expand Down
14 changes: 11 additions & 3 deletions packages/esbuild-meta/src/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import { readFileSync, writeFileSync } from 'node:fs';
import { join } from 'node:path';
import { join, normalize } from 'node:path';
import { Metafile } from 'esbuild';

export function getJson<T = any>(path: string[]) {
return JSON.parse(readFileSync(join(...path), {encoding: 'utf-8'})) as T;
export const INVALID_FILE_PATH_ERROR_MSG = (path: string) => `No file found at ${path}`;

export function getJson<T = any>(path: string) {
const normalizedPath = normalize(path);
try {
return JSON.parse(readFileSync(normalizedPath, {encoding: 'utf-8'})) as T;
}
catch (e) {
throw new Error(INVALID_FILE_PATH_ERROR_MSG(normalizedPath));
}
}

export function makeJson(path: string, file: any) {
Expand Down
Loading
Loading