diff --git a/.github/workflows/test-ubuntu.yml b/.github/workflows/test-ubuntu.yml index f1e529e0..ebfe1edd 100644 --- a/.github/workflows/test-ubuntu.yml +++ b/.github/workflows/test-ubuntu.yml @@ -99,11 +99,13 @@ jobs: if: steps.changes.outputs.changed == 'true' run: pnpm install && cd ./e2e && pnpx playwright install - - name: E2E Test + - name: E2E Artifact Test (Vitest) if: steps.changes.outputs.changed == 'true' - run: | - pnpm run test:artifact - pnpm run test:e2e + run: pnpm run test:artifact + + - name: E2E Test (Playwright) + if: steps.changes.outputs.changed == 'true' + run: pnpm run test:e2e - name: Examples Test if: steps.changes.outputs.changed == 'true' diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index 61b4b4ba..f90097f5 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -108,13 +108,14 @@ jobs: if: steps.changes.outputs.changed == 'true' run: pnpm install && cd ./e2e && npx playwright install - - name: E2E Test + - name: E2E Artifact Test (Vitest) if: steps.changes.outputs.changed == 'true' - run: | - pnpm run test:artifact - pnpm run test:e2e + run: pnpm run test:artifact + + - name: E2E Test (Playwright) + if: steps.changes.outputs.changed == 'true' + run: pnpm run test:e2e - name: Examples Test if: steps.changes.outputs.changed == 'true' - run: | - pnpm run build:examples + run: pnpm run build:examples diff --git a/e2e/cases/bundle-false/index.test.ts b/e2e/cases/bundle-false/index.test.ts index d08751dd..48fb66de 100644 --- a/e2e/cases/bundle-false/index.test.ts +++ b/e2e/cases/bundle-false/index.test.ts @@ -8,18 +8,18 @@ test('basic', async () => { expect(files.esm).toMatchInlineSnapshot(` [ - "./dist/esm/index.js", - "./dist/esm/sum.js", - "./dist/esm/utils/numbers.js", - "./dist/esm/utils/strings.js", + "/e2e/cases/bundle-false/basic/dist/esm/index.js", + "/e2e/cases/bundle-false/basic/dist/esm/sum.js", + "/e2e/cases/bundle-false/basic/dist/esm/utils/numbers.js", + "/e2e/cases/bundle-false/basic/dist/esm/utils/strings.js", ] `); expect(files.cjs).toMatchInlineSnapshot(` [ - "./dist/cjs/index.js", - "./dist/cjs/sum.js", - "./dist/cjs/utils/numbers.js", - "./dist/cjs/utils/strings.js", + "/e2e/cases/bundle-false/basic/dist/cjs/index.js", + "/e2e/cases/bundle-false/basic/dist/cjs/sum.js", + "/e2e/cases/bundle-false/basic/dist/cjs/utils/numbers.js", + "/e2e/cases/bundle-false/basic/dist/cjs/utils/strings.js", ] `); }); @@ -30,12 +30,12 @@ test('single file', async () => { expect(files.esm).toMatchInlineSnapshot(` [ - "./dist/esm/index.js", + "/e2e/cases/bundle-false/single-file/dist/esm/index.js", ] `); expect(files.cjs).toMatchInlineSnapshot(` [ - "./dist/cjs/index.js", + "/e2e/cases/bundle-false/single-file/dist/cjs/index.js", ] `); }); diff --git a/e2e/cases/dts/__snapshots__/index.test.ts.snap b/e2e/cases/dts/__snapshots__/index.test.ts.snap index 4bce88be..353e92c9 100644 --- a/e2e/cases/dts/__snapshots__/index.test.ts.snap +++ b/e2e/cases/dts/__snapshots__/index.test.ts.snap @@ -2,25 +2,25 @@ exports[`dts when bundle: false > basic 2`] = ` { - "./dist/esm/index.d.ts": "export * from './utils/numbers'; + "/e2e/cases/dts/bundle-false/basic/dist/esm/index.d.ts": "export * from './utils/numbers'; export * from './utils/strings'; export * from './sum'; ", - "./dist/esm/sum.d.ts": "export declare const numSum: number; + "/e2e/cases/dts/bundle-false/basic/dist/esm/sum.d.ts": "export declare const numSum: number; export declare const strSum: string; ", - "./dist/esm/utils/numbers.d.ts": "export declare const num1 = 1; + "/e2e/cases/dts/bundle-false/basic/dist/esm/utils/numbers.d.ts": "export declare const num1 = 1; export declare const num2 = 2; export declare const num3 = 3; ", - "./dist/esm/utils/strings.d.ts": "export declare const str1 = "str1"; + "/e2e/cases/dts/bundle-false/basic/dist/esm/utils/strings.d.ts": "export declare const str1 = "str1"; export declare const str2 = "str2"; export declare const str3 = "str3"; ", } `; -exports[`dts when bundle: true > basic 1`] = ` +exports[`dts when bundle: true > basic 2`] = ` { "esm": "export declare const num1 = 1; diff --git a/e2e/cases/dts/index.test.ts b/e2e/cases/dts/index.test.ts index 979218c5..bd16c95d 100644 --- a/e2e/cases/dts/index.test.ts +++ b/e2e/cases/dts/index.test.ts @@ -9,10 +9,10 @@ describe('dts when bundle: false', () => { expect(files.esm).toMatchInlineSnapshot(` [ - "./dist/esm/index.d.ts", - "./dist/esm/sum.d.ts", - "./dist/esm/utils/numbers.d.ts", - "./dist/esm/utils/strings.d.ts", + "/e2e/cases/dts/bundle-false/basic/dist/esm/index.d.ts", + "/e2e/cases/dts/bundle-false/basic/dist/esm/sum.d.ts", + "/e2e/cases/dts/bundle-false/basic/dist/esm/utils/numbers.d.ts", + "/e2e/cases/dts/bundle-false/basic/dist/esm/utils/strings.d.ts", ] `); expect(contents.esm).toMatchSnapshot(); @@ -22,7 +22,7 @@ describe('dts when bundle: false', () => { const fixturePath = join(__dirname, 'bundle-false', 'false'); const { files } = await buildAndGetResults(fixturePath, 'dts'); - expect(files.esm).toBe(undefined); + expect(files.esm).toMatchInlineSnapshot('undefined'); }); test('distPath', async () => { @@ -31,10 +31,10 @@ describe('dts when bundle: false', () => { expect(files.esm).toMatchInlineSnapshot(` [ - "./dist/custom/index.d.ts", - "./dist/custom/sum.d.ts", - "./dist/custom/utils/numbers.d.ts", - "./dist/custom/utils/strings.d.ts", + "/e2e/cases/dts/bundle-false/dist-path/dist/custom/index.d.ts", + "/e2e/cases/dts/bundle-false/dist-path/dist/custom/sum.d.ts", + "/e2e/cases/dts/bundle-false/dist-path/dist/custom/utils/numbers.d.ts", + "/e2e/cases/dts/bundle-false/dist-path/dist/custom/utils/strings.d.ts", ] `); }); @@ -52,10 +52,10 @@ describe('dts when bundle: false', () => { expect(files.cjs).toMatchInlineSnapshot(` [ - "./dist/cjs/index.d.cts", - "./dist/cjs/sum.d.cts", - "./dist/cjs/utils/numbers.d.cts", - "./dist/cjs/utils/strings.d.cts", + "/e2e/cases/dts/bundle-false/auto-extension/dist/cjs/index.d.cts", + "/e2e/cases/dts/bundle-false/auto-extension/dist/cjs/sum.d.cts", + "/e2e/cases/dts/bundle-false/auto-extension/dist/cjs/utils/numbers.d.cts", + "/e2e/cases/dts/bundle-false/auto-extension/dist/cjs/utils/strings.d.cts", ] `); }); @@ -69,7 +69,9 @@ describe('dts when bundle: true', () => { 'dts', ); - expect(entryFiles.esm).toEqual('./dist/esm/main.d.ts'); + expect(entryFiles.esm).toMatchInlineSnapshot( + `"/e2e/cases/dts/bundle/basic/dist/esm/main.d.ts"`, + ); expect(entries).toMatchSnapshot(); }); @@ -77,14 +79,16 @@ describe('dts when bundle: true', () => { const fixturePath = join(__dirname, 'bundle', 'false'); const { entryFiles } = await buildAndGetResults(fixturePath, 'dts'); - expect(entryFiles.esm).toEqual(undefined); + expect(entryFiles.esm).toMatchInlineSnapshot('undefined'); }); test('distPath', async () => { const fixturePath = join(__dirname, 'bundle', 'dist-path'); const { entryFiles } = await buildAndGetResults(fixturePath, 'dts'); - expect(entryFiles.esm).toEqual('./dist/custom/main.d.ts'); + expect(entryFiles.esm).toMatchInlineSnapshot( + `"/e2e/cases/dts/bundle/dist-path/dist/custom/main.d.ts"`, + ); }); test('abortOnError: false', async () => { @@ -98,13 +102,17 @@ describe('dts when bundle: true', () => { const fixturePath = join(__dirname, 'bundle', 'auto-extension'); const { entryFiles } = await buildAndGetResults(fixturePath, 'dts'); - expect(entryFiles.cjs).toEqual('./dist/cjs/main.d.cts'); + expect(entryFiles.cjs).toMatchInlineSnapshot( + `"/e2e/cases/dts/bundle/auto-extension/dist/cjs/main.d.cts"`, + ); }); test('bundleName -- set source.entry', async () => { const fixturePath = join(__dirname, 'bundle', 'bundle-name'); const { entryFiles } = await buildAndGetResults(fixturePath, 'dts'); - expect(entryFiles.esm).toEqual('./dist/esm/bundleName.d.ts'); + expect(entryFiles.esm).toMatchInlineSnapshot( + `"/e2e/cases/dts/bundle/bundle-name/dist/esm/bundleName.d.ts"`, + ); }); }); diff --git a/e2e/scripts/helper.ts b/e2e/scripts/helper.ts index 9b16b7fc..fe2cd7ff 100644 --- a/e2e/scripts/helper.ts +++ b/e2e/scripts/helper.ts @@ -6,8 +6,6 @@ import fg, { } from 'fast-glob'; import fse from 'fs-extra'; -export const getFiles = async (_pattern: string) => {}; - // fast-glob only accepts posix path // https://github.com/mrmlnc/fast-glob#convertpathtopatternpath const convertPath = (path: string) => { @@ -17,7 +15,10 @@ const convertPath = (path: string) => { return path; }; -export const globContentJSON = async (path: string, options?: GlobOptions) => { +export const globContentJSON = async ( + path: string, + options?: GlobOptions, +): Promise> => { const files = await fg(convertPath(join(path, '**/*')), options); const ret: Record = {}; diff --git a/e2e/scripts/shared.ts b/e2e/scripts/shared.ts index c0a53503..fa328c6c 100644 --- a/e2e/scripts/shared.ts +++ b/e2e/scripts/shared.ts @@ -1,4 +1,4 @@ -import { join } from 'node:path'; +import { isAbsolute, join } from 'node:path'; import { type InspectConfigResult, mergeRsbuildConfig as mergeConfig, @@ -39,11 +39,25 @@ export function generateBundleCjsConfig( return mergeConfig(cjsBasicConfig, config)!; } +type FormatType = 'esm' | 'cjs'; +type FilePath = string; + +type BuildResult = { + files: Record; + contents: Record>; + entries: Record; + entryFiles: Record; + + rspackConfig: InspectConfigResult['origin']['bundlerConfigs']; + rsbuildConfig: InspectConfigResult['origin']['rsbuildConfig']; + isSuccess: boolean; +}; + export async function getResults( rslibConfig: RslibConfig, fixturePath: string, type: 'js' | 'dts', -) { +): Promise> { const files: Record = {}; const contents: Record> = {}; const entries: Record = {}; @@ -62,18 +76,11 @@ export async function getResults( const regex = type === 'dts' ? /\.d.(ts|cts|mts)$/ : /\.(js|cjs|mjs)$/; - const rawContent = await globContentJSON(globFolder, { + const content: Record = await globContentJSON(globFolder, { absolute: true, - ignore: ['/**/*.map'], + ignore: ['**/*.map'], }); - const content: Record = {}; - - for (const key of Object.keys(rawContent)) { - const newKey = key.replace(fixturePath, '.'); - content[newKey] = rawContent[key]!; - } - const fileSet = Object.keys(content).filter((file) => regex.test(file)); const filterContent: Record = {}; for (const key of fileSet) { @@ -102,16 +109,6 @@ export async function getResults( }; } -type BuildResult = { - contents: Record>; - files: Record; - entries: Record; - entryFiles: Record; - rspackConfig: InspectConfigResult['origin']['bundlerConfigs']; - rsbuildConfig: InspectConfigResult['origin']['rsbuildConfig']; - isSuccess: boolean; -}; - export async function buildAndGetResults( fixturePath: string, type: 'all', diff --git a/packages/core/src/utils/helper.ts b/packages/core/src/utils/helper.ts index ca36e081..b4d43352 100644 --- a/packages/core/src/utils/helper.ts +++ b/packages/core/src/utils/helper.ts @@ -78,7 +78,12 @@ async function calcLongestCommonPath( return null; } - const splitPaths = absPaths.map((p) => p.split(path.sep)); + // we support two cases + // 1. /packages-a/src/index.ts + // 2. D:/packages-a/src/index.ts + const sep = path.posix.sep as '/'; + + const splitPaths = absPaths.map((p) => p.split(sep)); let lcaFragments = splitPaths[0]!; for (let i = 1; i < splitPaths.length; i++) { const currentPath = splitPaths[i]!; @@ -92,7 +97,7 @@ async function calcLongestCommonPath( lcaFragments = lcaFragments.slice(0, j); } - let lca = lcaFragments.length > 0 ? lcaFragments.join(path.sep) : '/'; + let lca = lcaFragments.length > 0 ? lcaFragments.join(sep) : sep; const stats = await fsP.stat(lca); if (stats?.isFile()) { diff --git a/packages/core/tests/lcp.test.ts b/packages/core/tests/lcp.test.ts index 065a0f79..8283538c 100644 --- a/packages/core/tests/lcp.test.ts +++ b/packages/core/tests/lcp.test.ts @@ -29,11 +29,11 @@ describe('LCP calculate correctly', () => { expect(result).toEqual('/Users/Someone/project-a/src'); } else { const result = await calcLongestCommonPath([ - 'D:\\Users\\Someone\\project-a\\src\\helpers', - 'D:\\Users\\Someone\\project-a\\src', - 'D:\\Users\\Someone\\project-a\\src\\utils', + 'D:/Users/Someone/project-a/src/helpers', + 'D:/Users/Someone/project-a/src', + 'D:/Users/Someone/project-a/src/utils', ]); - expect(result).toEqual('D:\\Users\\Someone\\project-a\\src'); + expect(result).toEqual('D:/Users/Someone/project-a/src'); } }); @@ -49,11 +49,11 @@ describe('LCP calculate correctly', () => { expect(result).toEqual('/Users/Someone/project-monorepo'); } else { const result = await calcLongestCommonPath([ - 'D:\\Users\\Someone\\project-monorepo\\packages-a\\src\\index.ts', - 'D:\\Users\\Someone\\project-monorepo\\packages-util\\src\\index.js', - 'D:\\Users\\Someone\\project-monorepo\\script.js', + 'D:/Users/Someone/project-monorepo/packages-a/src/index.ts', + 'D:/Users/Someone/project-monorepo/packages-util/src/index.js', + 'D:/Users/Someone/project-monorepo/script.js', ]); - expect(result).toEqual('D:\\Users\\Someone\\project-monorepo'); + expect(result).toEqual('D:/Users/Someone/project-monorepo'); } }); @@ -68,9 +68,9 @@ describe('LCP calculate correctly', () => { expect(result).toEqual('/Users/Someone/project/src'); } else { const result = await calcLongestCommonPath([ - 'D:\\Users\\Someone\\project\\src\\index.js', + 'D:/Users/Someone/project/src/index.js', ]); - expect(result).toEqual('D:\\Users\\Someone\\project\\src'); + expect(result).toEqual('D:/Users/Someone/project/src'); } }); }); diff --git a/packages/plugin-dts/src/utils.ts b/packages/plugin-dts/src/utils.ts index b0e2a3ae..1a3bc6d9 100644 --- a/packages/plugin-dts/src/utils.ts +++ b/packages/plugin-dts/src/utils.ts @@ -1,12 +1,15 @@ import fs from 'node:fs'; import fsP from 'node:fs/promises'; -import path from 'node:path'; +import { platform } from 'node:os'; +import path, { join } from 'node:path'; import { type RsbuildConfig, logger } from '@rsbuild/core'; import fg from 'fast-glob'; import color from 'picocolors'; import type { DtsEntry } from 'src'; import * as ts from 'typescript'; +const { convertPathToPattern } = fg; + export function loadTsconfig(tsconfigPath: string): ts.ParsedCommandLine { const configFile = ts.readConfigFile(tsconfigPath, ts.sys.readFile); const configFileContent = ts.parseJsonConfigFileContent( @@ -30,7 +33,7 @@ export function ensureTempDeclarationDir(cwd: string): string { fs.mkdirSync(dirPath, { recursive: true }); - const gitIgnorePath = path.join(cwd, `${TEMP_FOLDER}/.gitignore`); + const gitIgnorePath = path.join(cwd, TEMP_FOLDER, '.gitignore'); fs.writeFileSync(gitIgnorePath, '**/*\n'); return dirPath; @@ -64,6 +67,15 @@ export const prettyTime = (seconds: number): string => { return `${format(minutes.toFixed(2))} m`; }; +// fast-glob only accepts posix path +// https://github.com/mrmlnc/fast-glob#convertpathtopatternpath +const convertPath = (path: string) => { + if (platform() === 'win32') { + return convertPathToPattern(path); + } + return path; +}; + export function getTimeCost(start: number): string { const second = (Date.now() - start) / 1000; return prettyTime(second); @@ -78,7 +90,7 @@ export async function processDtsFiles( return; } - const dtsFiles = await fg(`${dir}/**/*.d.ts`); + const dtsFiles = await fg(convertPath(join(dir, '/**/*.d.ts'))); for (const file of dtsFiles) { try { @@ -124,7 +136,12 @@ export async function calcLongestCommonPath( return null; } - const splitPaths = absPaths.map((p) => p.split(path.sep)); + // we support two cases + // 1. /packages-a/src/index.ts + // 2. D:/packages-a/src/index.ts + const sep = path.posix.sep as '/'; + + const splitPaths = absPaths.map((p) => p.split(sep)); let lcaFragments = splitPaths[0]!; for (let i = 1; i < splitPaths.length; i++) { const currentPath = splitPaths[i]!; @@ -138,7 +155,7 @@ export async function calcLongestCommonPath( lcaFragments = lcaFragments.slice(0, j); } - let lca = lcaFragments.length > 0 ? lcaFragments.join(path.sep) : '/'; + let lca = lcaFragments.length > 0 ? lcaFragments.join(sep) : sep; const stats = await fsP.stat(lca); if (stats?.isFile()) {