Skip to content

Commit

Permalink
fix: rsbuild doctor add e2e tests
Browse files Browse the repository at this point in the history
fix: rsbuild doctor add e2e tests

fix: rsbuild doctor add e2e tests

fix: rsbuild doctor add e2e tests

fix: rsbuild doctor add e2e tests

fix: rsbuild doctor add e2e tests

fix: rsbuild doctor add e2e tests

fix: rsbuild doctor add e2e tests

fix: rsbuild doctor add e2e tests
  • Loading branch information
easy1090 committed Nov 21, 2023
1 parent 375d3aa commit 7b525a9
Show file tree
Hide file tree
Showing 36 changed files with 931 additions and 893 deletions.
59 changes: 59 additions & 0 deletions .github/workflows/test-ubuntu-doctor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Doctor E2E (Ubuntu)

# Controls when the action will run.
on:
# Triggers the workflow on pull request events but only for the main branch
pull_request:
branches: [main]

push:
branches: [main]
paths:
- "packages/doctor-*"

merge_group:

# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# ===== e2e for doctor =======
e2e-ubuntu-doctor:
runs-on: ubuntu-latest
strategy:
matrix:
# Rsbuild need to compat Node.js 16
node-version: [16.x]

# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 10

- name: Install Pnpm
run: corepack enable

- name: Check skip CI
run: echo "RESULT=$(node ./scripts/skipCI.js)" >> "$GITHUB_OUTPUT"
id: skip-ci

- name: Log skip CI result
run: echo "${{steps.skip-ci.outputs.RESULT}}"

- name: Setup Node.js ${{ matrix.node-version }}
if: ${{steps.skip-ci.outputs.RESULT != 'true'}}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'

- name: Install Dependencies
if: ${{steps.skip-ci.outputs.RESULT != 'true'}}
run: pnpm install && cd ./e2e && npx playwright install

- name: E2E Test
if: ${{steps.skip-ci.outputs.RESULT != 'true'}}
run: pnpm run e2e:doctor
File renamed without changes.
File renamed without changes.
82 changes: 82 additions & 0 deletions e2e/cases/doctor-rspack/tests/plugin.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { expect, test } from '@playwright/test';
import { getSDK } from '@rsbuild/doctor-core/plugins';
import { compileByRspack } from '@rsbuild/test-helper';
import { Compiler } from '@rspack/core';
import os from 'os';
import path from 'path';
import { createDoctorPlugin } from './test-utils';

async function rspackCompile(tapName: string, compile: typeof compileByRspack) {
const file = path.resolve(__dirname, './fixtures/a.js');
const loader = path.resolve(__dirname, './fixtures/loaders/comment.js');
const res = await compile(file, {
module: {
rules: [
{
test: /\.js/,
use: loader,
},
],
},
plugins: [
// @ts-ignore
createDoctorPlugin({}),
{
name: tapName,
apply(compiler: Compiler) {
compiler.hooks.done.tapPromise(tapName, async () => {
// nothing
});
compiler.hooks.thisCompilation.tap(tapName, (compilation) => {
compilation.hooks.processAssets.tap(tapName, () => {
return 'processAssets end';
});
});
},
},
],
});

return res;
}

test('rspack plugin intercept', async () => {
const tapName = 'XXX';
await rspackCompile(tapName, compileByRspack);
const sdk = getSDK();
const { done, thisCompilation } = sdk.getStoreData().plugin;
const doneData = done.filter((e) => e.tapName === tapName);
expect(doneData).toHaveLength(1);
expect(doneData[0].type).toEqual('promise');
expect(doneData[0].result).toBeNull();

const sealData = thisCompilation.filter((e) => e.tapName === tapName);
expect(sealData).toHaveLength(1);
expect(sealData[0].type).toEqual('sync');
expect(sealData[0].result).toBeNull();
});

test('rspack data store', async () => {
const tapName = 'XXX';
await rspackCompile(tapName, compileByRspack);
const sdk = getSDK();
const datas = sdk.getStoreData();
expect(datas.errors.length).toBe(0);
const graphData = datas.moduleGraph;

os.EOL === '\n'
? expect(
graphData.modules[0].webpackId.indexOf('tests/fixtures/a.js'),
).toBeGreaterThan(0)
: expect(
graphData.modules[0].webpackId.indexOf('\\tests\\fixtures\\a.js'),
).toBeGreaterThan(0);

graphData.modules.forEach((mod) => (mod.webpackId = ''));
expect(graphData.modules[0].size).toEqual({
sourceSize: 33,
transformedSize: 33,
parsedSize: 0,
});
expect(graphData.modules[0].path).toMatch('tests/fixtures/a.js');
});
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { DoctorRspackPluginOptions } from '@rsbuild/doctor-core/types';
import { RsbuildDoctorRspackPlugin } from '@rsbuild/doctor-rspack-plugin';
import { Linter } from '@rsbuild/doctor-types';
import { File } from '@rsbuild/doctor-utils/build';
import { tmpdir } from 'os';
import path from 'path';
import { RsbuildDoctorRspackPlugin } from '../src';

export function createDoctorPlugin<T extends Linter.ExtendRuleData[]>(
options: DoctorRspackPluginOptions<T>,
Expand All @@ -20,10 +20,14 @@ export function createDoctorPlugin<T extends Linter.ExtendRuleData[]>(
tmpdir(),
`./${Date.now()}/rsbuild_doctor_rspack_plugin_test`,
);
plugin.sdk.setOutputDir(outdir);

plugin.sdk.hooks.afterSaveManifest.tapPromise('REMOVE_TMP_DIR', async () => {
await File.fse.remove(plugin.sdk.outputDir);
plugin.sdk.setOutputDir(outdir);
try {
await File.fse.remove(plugin.sdk.outputDir);
} catch (e) {
console.error(e);
}
});

return plugin;
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
227 changes: 227 additions & 0 deletions e2e/cases/doctor-webpack/loaders/proxy.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
import { expect, test } from '@playwright/test';
import { getSDK, setSDK } from '@rsbuild/doctor-core/plugins';
import { DoctorWebpackSDK } from '@rsbuild/doctor-sdk/sdk';
import { SDK } from '@rsbuild/doctor-types';
import { compileByWebpack5 } from '@rsbuild/test-helper';
import os from 'os';
import path from 'path';
import { Compiler } from 'webpack';
import { createRsbuildDoctorPlugin } from '../test-utils';

const file = path.resolve(__dirname, '../fixtures/a.js');
const loaderPath = path.resolve(__dirname, '../fixtures/loaders/comment.js');
const codeTransformed = `console.log('a');\n\n// hello world`;

async function webpack5(mode: 'async' | 'callback' | 'sync', pitchResult = '') {
const res = await compileByWebpack5(file, {
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: loaderPath,
options: {
mode,
pitchResult,
},
},
],
},
],
},
// @ts-ignore
plugins: [createRsbuildDoctorPlugin()],
});
return res;
}

test('webpack5', async () => {
const mode = 'sync';
const { modules } = await webpack5(mode);

expect(modules!.length).toEqual(1);
expect(getSDK()).toBeInstanceOf(DoctorWebpackSDK);

const { loader } = getSDK().getStoreData();

expect(loader).toHaveLength(1);
expect(loader[0].resource).toStrictEqual({
path: file,
query: {},
queryRaw: '',
ext: 'js',
} as SDK.ResourceData);
expect(loader[0].loaders[0].isPitch).toBeFalsy();
expect(loader[0].loaders[0].loaderIndex).toEqual(0);
expect(loader[0].loaders[0].path).toEqual(loaderPath);
os.EOL === '\n' &&
expect(loader[0].loaders[0].result).toEqual(codeTransformed);
expect(loader[0].loaders[0].options).toStrictEqual({
mode,
pitchResult: '',
});
expect(loader[0].loaders[0].errors).toHaveLength(0);
});

test('test async', async () => {
const mode = 'async';
const { modules } = await webpack5(mode);

expect(modules!.length).toEqual(1);
expect(getSDK()).toBeInstanceOf(DoctorWebpackSDK);

const { loader } = getSDK().getStoreData();

expect(loader).toHaveLength(1);
expect(loader[0].resource).toStrictEqual({
path: file,
query: {},
queryRaw: '',
ext: 'js',
} as SDK.ResourceData);
expect(loader[0].loaders[0].isPitch).toBeFalsy();
expect(loader[0].loaders[0].loaderIndex).toEqual(0);
expect(loader[0].loaders[0].path).toEqual(loaderPath);
os.EOL === '\n' &&
expect(loader[0].loaders[0].result).toEqual(codeTransformed);
expect(loader[0].loaders[0].options).toStrictEqual({
mode,
pitchResult: '',
});
expect(loader[0].loaders[0].errors).toHaveLength(0);
});

test('test callback', async () => {
const mode = 'callback';
const { modules } = await webpack5(mode);

expect(modules!.length).toEqual(1);
expect(getSDK()).toBeInstanceOf(DoctorWebpackSDK);

const { loader } = getSDK().getStoreData();

expect(loader).toHaveLength(1);
expect(loader[0].resource).toStrictEqual({
path: file,
query: {},
queryRaw: '',
ext: 'js',
} as SDK.ResourceData);
expect(loader[0].loaders[0].isPitch).toBeFalsy();
expect(loader[0].loaders[0].loaderIndex).toEqual(0);
expect(loader[0].loaders[0].path).toEqual(loaderPath);
os.EOL === '\n' &&
expect(loader[0].loaders[0].result).toEqual(codeTransformed);
expect(loader[0].loaders[0].options).toStrictEqual({
mode,
pitchResult: '',
});
expect(loader[0].loaders[0].errors).toHaveLength(0);
});

test('test pitch', async () => {
const mode = 'callback';
const pitchResult = '// pitch success';
const { modules } = await webpack5(mode, pitchResult);

expect(modules!.length).toEqual(1);
expect(getSDK()).toBeInstanceOf(DoctorWebpackSDK);

const { loader } = getSDK().getStoreData();

expect(loader).toHaveLength(1);
expect(loader[0].resource).toStrictEqual({
path: file,
query: {},
queryRaw: '',
ext: 'js',
} as SDK.ResourceData);
expect(loader[0].loaders[0].isPitch).toBeTruthy();
expect(loader[0].loaders[0].loaderIndex).toEqual(0);
expect(loader[0].loaders[0].path).toEqual(loaderPath);
expect(loader[0].loaders[0].result).toEqual(pitchResult);
expect(loader[0].loaders[0].options).toStrictEqual({ mode, pitchResult });
expect(loader[0].loaders[0].errors).toHaveLength(0);
});

test('set sdk.reportLoader as null to mock this scene', async () => {
const mode = 'sync';
const plugin = createRsbuildDoctorPlugin();
const { modules } = await compileByWebpack5(file, {
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: loaderPath,
options: {
mode,
pitchResult: '',
},
},
],
},
],
},
plugins: [
// @ts-ignore
plugin,
// @ts-ignore
{
name: 'XXX',
apply(compiler: Compiler) {
compiler.hooks.beforeRun.tapPromise(
{ name: 'XXX', stage: 99999 },
async () => {
const sdk = getSDK();
setSDK(
new Proxy(sdk, {
get(target, key, receiver) {
switch (key) {
case 'reportLoader':
return null;
default:
return Reflect.get(target, key, receiver);
}
},
set(target, key, value, receiver) {
return Reflect.set(target, key, value, receiver);
},
defineProperty(target, p, attrs) {
return Reflect.defineProperty(target, p, attrs);
},
}),
);
},
);
},
},
],
});

expect(modules!.length).toEqual(1);
expect(getSDK().reportLoader).toEqual(null);

// @ts-ignore
const { loader } = plugin.sdk.getStoreData();

expect(loader).toHaveLength(1);
expect(loader[0].resource).toStrictEqual({
path: file,
query: {},
queryRaw: '',
ext: 'js',
} as SDK.ResourceData);
expect(loader[0].loaders[0].isPitch).toBeFalsy();
expect(loader[0].loaders[0].loaderIndex).toEqual(0);
expect(loader[0].loaders[0].path).toEqual(loaderPath);
os.EOL === '\n' &&
expect(loader[0].loaders[0].result).toEqual(codeTransformed);
expect(loader[0].loaders[0].options).toStrictEqual({
mode,
pitchResult: '',
});
expect(loader[0].loaders[0].errors).toHaveLength(0);
});
Loading

0 comments on commit 7b525a9

Please sign in to comment.