From 83e9be3acef8f6271bcdd80c27035fe8eb6c3b0c Mon Sep 17 00:00:00 2001 From: mato533 Date: Fri, 13 Jun 2025 10:15:39 +0900 Subject: [PATCH 1/9] feat: module separation of temp conf creation for windows --- packages/vscode-wdio-worker/package.json | 3 +++ packages/vscode-wdio-worker/src/test.ts | 5 ++-- packages/vscode-wdio-worker/src/utils.ts | 25 +++++++++++++++++++ .../vscode-wdio-worker/tests/test.test.ts | 14 +++++++---- packages/vscode-webdriverio/package.json | 4 +++ packages/vscode-webdriverio/src/parser/ast.ts | 1 + 6 files changed, 45 insertions(+), 7 deletions(-) create mode 100644 packages/vscode-wdio-worker/src/utils.ts create mode 100644 packages/vscode-webdriverio/src/parser/ast.ts diff --git a/packages/vscode-wdio-worker/package.json b/packages/vscode-wdio-worker/package.json index 47b6c5e..956b1e0 100644 --- a/packages/vscode-wdio-worker/package.json +++ b/packages/vscode-wdio-worker/package.json @@ -6,6 +6,9 @@ "exports": { ".": { "import": "./dist/index.js" + }, + "./windows": { + "import": "./dist/config.js" } }, "scripts": { diff --git a/packages/vscode-wdio-worker/src/test.ts b/packages/vscode-wdio-worker/src/test.ts index 824d832..f71b055 100644 --- a/packages/vscode-wdio-worker/src/test.ts +++ b/packages/vscode-wdio-worker/src/test.ts @@ -3,7 +3,7 @@ import * as os from 'node:os' import { dirname, isAbsolute, join, resolve } from 'node:path' import { getLauncherInstance } from './cli.js' -import { createTempConfigFile, isWindows } from './config.js' +import { getTempConfigCreator, isWindows } from './utils.js' import type { RunTestOptions, TestResultData } from '@vscode-wdio/types/api' import type { ResultSet } from '@vscode-wdio/types/reporter' import type { LoggerInterface } from '@vscode-wdio/types/utils' @@ -43,7 +43,8 @@ export async function runTest(this: WorkerMetaContext, options: RunTestOptions): } if (isWindows()) { - configFile = await createTempConfigFile(options.configPath, outputDir.json!) + const creator = await getTempConfigCreator(this) + configFile = await creator(options.configPath, outputDir.json!) options.configPath = configFile wdioArgs.configPath = configFile } diff --git a/packages/vscode-wdio-worker/src/utils.ts b/packages/vscode-wdio-worker/src/utils.ts new file mode 100644 index 0000000..72899ae --- /dev/null +++ b/packages/vscode-wdio-worker/src/utils.ts @@ -0,0 +1,25 @@ +import path from 'node:path' + +import type { WorkerMetaContext } from '@vscode-wdio/types' +import type { createTempConfigFile } from './config.js' + +export type TempConfigFileCreator = typeof createTempConfigFile + +const VSCODE_WINDOWS_CONFIG_CREATOR_PATH = path.resolve(__dirname, 'parser/ast.cjs') + +let tempConfigCreator: TempConfigFileCreator | undefined + +export async function getTempConfigCreator(context: WorkerMetaContext): Promise { + if (tempConfigCreator){ + context.log.debug('Use cached TempConfigFileCreator') + return tempConfigCreator + } + context.log.debug('Import TempConfigFileCreator') + tempConfigCreator =((await import(VSCODE_WINDOWS_CONFIG_CREATOR_PATH)).createTempConfigFile as TempConfigFileCreator) + return tempConfigCreator + +} + +export function isWindows() { + return process.platform === 'win32' +} diff --git a/packages/vscode-wdio-worker/tests/test.test.ts b/packages/vscode-wdio-worker/tests/test.test.ts index 0b1d098..6a2f2bd 100644 --- a/packages/vscode-wdio-worker/tests/test.test.ts +++ b/packages/vscode-wdio-worker/tests/test.test.ts @@ -5,8 +5,8 @@ import { join } from 'node:path' import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest' import { getLauncherInstance } from '../src/cli.js' -import { createTempConfigFile, isWindows } from '../src/config.js' import { runTest } from '../src/test.js' +import { getTempConfigCreator, isWindows } from '../src/utils.js' import type { Dirent } from 'node:fs' import type { WorkerMetaContext } from '@vscode-wdio/types/worker' @@ -21,10 +21,11 @@ vi.mock('../src/cli.js', () => { ) return { getLauncherInstance } }) -vi.mock('../src/config.js', () => { + +vi.mock('../src/utils.js', () => { return { - createTempConfigFile: vi.fn(async (config) => config), isWindows: vi.fn(() => false), + getTempConfigCreator: vi.fn(), } }) @@ -52,6 +53,7 @@ describe('runTest', () => { const mockResultDir = '/mock/tmp/dir/result-xyz123' const mockResultFile = 'wdio-0-0.json' const mockResultData = JSON.stringify({ some: 'test result' }) + const mockTempConfigCreator = vi.fn(async () => '/path/to/customized/wdio.conf.ts') beforeEach(() => { // Reset mocks @@ -63,10 +65,13 @@ describe('runTest', () => { vi.mocked(fs.mkdir).mockResolvedValue(undefined) vi.mocked(fs.mkdtemp).mockResolvedValue(mockResultDir) vi.mocked(fs.access).mockResolvedValue(undefined) + // @ts-ignore vi.mocked(fs.readdir).mockResolvedValue([mockResultFile as unknown as Dirent]) vi.mocked(fs.readFile).mockResolvedValue(Buffer.from(mockResultData)) vi.mocked(fs.rm).mockResolvedValue(undefined) + vi.mocked(getTempConfigCreator).mockResolvedValue(mockTempConfigCreator) + // Mock console methods vi.spyOn(console, 'log').mockImplementation(() => {}) vi.spyOn(console, 'error').mockImplementation(() => {}) @@ -104,7 +109,6 @@ describe('runTest', () => { it('should run tests successfully and return results on the windows', async () => { vi.mocked(isWindows).mockReturnValue(true) - vi.mocked(createTempConfigFile).mockResolvedValue('/path/to/customized/wdio.conf.ts') // Act const result = await runTest.call(mockContext, mockOptions) @@ -122,7 +126,7 @@ describe('runTest', () => { expect(fs.mkdtemp).toHaveBeenCalledWith(join(mockTmpDir, 'vscode-webdriverio', 'result-')) // Verify createTempConfigFile were called - expect(createTempConfigFile).toHaveBeenCalledWith(mockConfigFile, mockResultDir) + expect(mockTempConfigCreator).toHaveBeenCalledWith(mockConfigFile, mockResultDir) // Verify result files were read expect(fs.readdir).toHaveBeenCalledWith(mockResultDir) diff --git a/packages/vscode-webdriverio/package.json b/packages/vscode-webdriverio/package.json index 11daea3..aa673e0 100644 --- a/packages/vscode-webdriverio/package.json +++ b/packages/vscode-webdriverio/package.json @@ -19,6 +19,10 @@ "./reporter": { "requireSource": "./src/reporter.ts", "require": "./dist/reporter.cjs" + }, + "./parser/ast": { + "requireSource": "./src/parser/ast.ts", + "require": "./dist/parser/ast.cjs" } }, "scripts": { diff --git a/packages/vscode-webdriverio/src/parser/ast.ts b/packages/vscode-webdriverio/src/parser/ast.ts new file mode 100644 index 0000000..9a89e96 --- /dev/null +++ b/packages/vscode-webdriverio/src/parser/ast.ts @@ -0,0 +1 @@ +export { createTempConfigFile } from '@vscode-wdio/worker/windows' From 7870758b1fd4256ba7409d3cdc88911dbe104a54 Mon Sep 17 00:00:00 2001 From: mato533 Date: Fri, 13 Jun 2025 10:34:09 +0900 Subject: [PATCH 2/9] feat: module separation of Cucumber parser --- packages/vscode-wdio-worker/package.json | 3 +++ .../src/parsers/cucumber.ts | 2 +- .../vscode-wdio-worker/src/parsers/index.ts | 9 ++++++-- .../vscode-wdio-worker/src/parsers/utils.ts | 20 ++++++++++++++++++ .../tests/parsers/cucumber.test.ts | 4 +++- .../tests/parsers/index.test.ts | 21 ++++++++++--------- packages/vscode-webdriverio/package.json | 4 ++++ .../vscode-webdriverio/src/parser/cucumber.ts | 1 + 8 files changed, 50 insertions(+), 14 deletions(-) create mode 100644 packages/vscode-wdio-worker/src/parsers/utils.ts create mode 100644 packages/vscode-webdriverio/src/parser/cucumber.ts diff --git a/packages/vscode-wdio-worker/package.json b/packages/vscode-wdio-worker/package.json index 956b1e0..2d094eb 100644 --- a/packages/vscode-wdio-worker/package.json +++ b/packages/vscode-wdio-worker/package.json @@ -9,6 +9,9 @@ }, "./windows": { "import": "./dist/config.js" + }, + "./parser/cucumber": { + "import": "./dist/parsers/cucumber.js" } }, "scripts": { diff --git a/packages/vscode-wdio-worker/src/parsers/cucumber.ts b/packages/vscode-wdio-worker/src/parsers/cucumber.ts index 30df3e3..f34280d 100644 --- a/packages/vscode-wdio-worker/src/parsers/cucumber.ts +++ b/packages/vscode-wdio-worker/src/parsers/cucumber.ts @@ -12,7 +12,7 @@ import type { CucumberTestData, StepType, WorkerMetaContext } from '@vscode-wdio * @returns Array of test case information */ export function parseCucumberFeature(this: WorkerMetaContext, fileContent: string, uri: string) { - this.log.debug('Cucumber parser is used.') + this.log.debug(`Start parsing the cucumber feature file: ${uri}`) try { // Initialize the parser components const builder = new AstBuilder(IdGenerator.uuid()) diff --git a/packages/vscode-wdio-worker/src/parsers/index.ts b/packages/vscode-wdio-worker/src/parsers/index.ts index 2eb3efe..3f3936b 100644 --- a/packages/vscode-wdio-worker/src/parsers/index.ts +++ b/packages/vscode-wdio-worker/src/parsers/index.ts @@ -1,11 +1,16 @@ import * as fs from 'node:fs/promises' import path from 'node:path' -import { parseCucumberFeature } from './cucumber.js' import { parseTestCases } from './js.js' +import { getCucumberParser } from './utils.js' import type { ReadSpecsOptions } from '@vscode-wdio/types/api' import type { WorkerMetaContext } from '@vscode-wdio/types/worker' +async function parseFeatureFile(context: WorkerMetaContext, contents: string, normalizeSpecPath: string) { + const p = await getCucumberParser(context) + return p.call(context, contents, normalizeSpecPath) +} + export async function parse(this: WorkerMetaContext, options: ReadSpecsOptions) { return await Promise.all( options.specs.map(async (spec) => { @@ -14,7 +19,7 @@ export async function parse(this: WorkerMetaContext, options: ReadSpecsOptions) const contents = await fs.readFile(normalizeSpecPath, { encoding: 'utf8' }) try { const testCases = isCucumberFeatureFile(normalizeSpecPath) - ? parseCucumberFeature.call(this, contents, normalizeSpecPath) // Parse Cucumber feature file + ? await parseFeatureFile(this, contents, normalizeSpecPath) // Parse Cucumber feature file : parseTestCases.call(this, contents, normalizeSpecPath) // Parse JavaScript/TypeScript test file this.log.debug(`Successfully parsed: ${normalizeSpecPath}`) diff --git a/packages/vscode-wdio-worker/src/parsers/utils.ts b/packages/vscode-wdio-worker/src/parsers/utils.ts new file mode 100644 index 0000000..e40cbfc --- /dev/null +++ b/packages/vscode-wdio-worker/src/parsers/utils.ts @@ -0,0 +1,20 @@ +import path from 'node:path' + +import type { WorkerMetaContext } from '@vscode-wdio/types/worker' +import type { parseCucumberFeature } from './cucumber.js' + +export type CucumberParser = typeof parseCucumberFeature + +const CUCUMBER_PARSER_PATH = path.resolve(__dirname, 'parser/cucumber.cjs') + +let cucumberParser: CucumberParser | undefined + +export async function getCucumberParser(context: WorkerMetaContext): Promise { + if (cucumberParser) { + context.log.debug('Use cached Cucumber parser') + return cucumberParser + } + context.log.debug('Import Cucumber parser') + cucumberParser = (await import(CUCUMBER_PARSER_PATH)).parseCucumberFeature as CucumberParser + return cucumberParser +} diff --git a/packages/vscode-wdio-worker/tests/parsers/cucumber.test.ts b/packages/vscode-wdio-worker/tests/parsers/cucumber.test.ts index 9da49a0..c47758b 100644 --- a/packages/vscode-wdio-worker/tests/parsers/cucumber.test.ts +++ b/packages/vscode-wdio-worker/tests/parsers/cucumber.test.ts @@ -340,7 +340,9 @@ describe('Cucumber Parser', () => { parseCucumberFeature.call(mockContext, basicFeatureContent, 'basic-feature.feature') // Verify debug log was called - expect(mockContext.log.debug).toHaveBeenCalledWith('Cucumber parser is used.') + expect(mockContext.log.debug).toHaveBeenCalledWith( + 'Start parsing the cucumber feature file: basic-feature.feature' + ) }) it('should include proper source ranges for each element', () => { diff --git a/packages/vscode-wdio-worker/tests/parsers/index.test.ts b/packages/vscode-wdio-worker/tests/parsers/index.test.ts index 4f0d2cb..2ce2475 100644 --- a/packages/vscode-wdio-worker/tests/parsers/index.test.ts +++ b/packages/vscode-wdio-worker/tests/parsers/index.test.ts @@ -5,9 +5,9 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest' // Import parse function from parsers -import { parseCucumberFeature } from '../../src/parsers/cucumber.js' import { parse } from '../../src/parsers/index.js' import { parseTestCases } from '../../src/parsers/js.js' +import { getCucumberParser } from '../../src/parsers/utils.js' import type { ReadSpecsOptions } from '@vscode-wdio/types/api' import type { WorkerMetaContext, TestData, CucumberTestData } from '@vscode-wdio/types/worker' @@ -18,8 +18,8 @@ vi.mock('node:fs/promises', () => ({ })) // Mock the parsers -vi.mock('../../src/parsers/cucumber.js', () => ({ - parseCucumberFeature: vi.fn(), +vi.mock('../../src/parsers/utils.js', () => ({ + getCucumberParser: vi.fn(), })) vi.mock('../../src/parsers/js.js', () => ({ @@ -87,13 +87,14 @@ describe('Parser Index', () => { metadata: {}, }, ] + const mockCucumberParser = vi.fn(()=>cucumberMockTestData) beforeEach(() => { vi.resetAllMocks() // Mock the parseTestCases and parseCucumberFeature functions vi.mocked(parseTestCases).mockReturnValue(jsMockTestData) - vi.mocked(parseCucumberFeature).mockReturnValue(cucumberMockTestData) + vi.mocked(getCucumberParser).mockResolvedValue(mockCucumberParser) }) afterEach(() => { @@ -120,7 +121,7 @@ describe('Parser Index', () => { // Verify the correct parser was called expect(parseTestCases).toHaveBeenCalledWith(jsTestContent, path.normalize('/path/to/test.js')) - expect(parseCucumberFeature).not.toHaveBeenCalled() + expect(mockCucumberParser).not.toHaveBeenCalled() // Verify logging expect(mockContext.log.debug).toHaveBeenCalledWith(`Parse spec file: ${path.normalize('/path/to/test.js')}`) @@ -148,7 +149,7 @@ describe('Parser Index', () => { // Verify the correct parser was called expect(parseTestCases).toHaveBeenCalledWith(jsTestContent, path.normalize('/path/to/test.ts')) - expect(parseCucumberFeature).not.toHaveBeenCalled() + expect(mockCucumberParser).not.toHaveBeenCalled() }) it('should parse Cucumber feature files correctly', async () => { @@ -169,7 +170,7 @@ describe('Parser Index', () => { expect(result[0].tests).toEqual(cucumberMockTestData) // Verify the correct parser was called - expect(parseCucumberFeature).toHaveBeenCalledWith( + expect(mockCucumberParser).toHaveBeenCalledWith( cucumberFeatureContent, path.normalize('/path/to/test.feature') ) @@ -194,7 +195,7 @@ describe('Parser Index', () => { expect(result[0].tests).toEqual(cucumberMockTestData) // Verify the correct parser was called - expect(parseCucumberFeature).toHaveBeenCalledWith( + expect(mockCucumberParser).toHaveBeenCalledWith( cucumberFeatureContent, path.normalize('/path/to/test.FEATURE') ) @@ -232,7 +233,7 @@ describe('Parser Index', () => { // Verify the correct parsers were called expect(parseTestCases).toHaveBeenCalledWith(jsTestContent, path.normalize('/path/to/test.js')) - expect(parseCucumberFeature).toHaveBeenCalledWith( + expect(mockCucumberParser).toHaveBeenCalledWith( cucumberFeatureContent, path.normalize('/path/to/test.feature') ) @@ -284,7 +285,7 @@ describe('Parser Index', () => { expect(result).toEqual([]) expect(fs.readFile).not.toHaveBeenCalled() expect(parseTestCases).not.toHaveBeenCalled() - expect(parseCucumberFeature).not.toHaveBeenCalled() + expect(mockCucumberParser).not.toHaveBeenCalled() }) }) }) diff --git a/packages/vscode-webdriverio/package.json b/packages/vscode-webdriverio/package.json index aa673e0..36ec3d6 100644 --- a/packages/vscode-webdriverio/package.json +++ b/packages/vscode-webdriverio/package.json @@ -23,6 +23,10 @@ "./parser/ast": { "requireSource": "./src/parser/ast.ts", "require": "./dist/parser/ast.cjs" + }, + "./parser/cucumber": { + "requireSource": "./src/parser/cucumber.ts", + "require": "./dist/parser/cucumber.cjs" } }, "scripts": { diff --git a/packages/vscode-webdriverio/src/parser/cucumber.ts b/packages/vscode-webdriverio/src/parser/cucumber.ts new file mode 100644 index 0000000..7e3711d --- /dev/null +++ b/packages/vscode-webdriverio/src/parser/cucumber.ts @@ -0,0 +1 @@ +export { parseCucumberFeature } from '@vscode-wdio/worker/parser/cucumber' From 5aaab74251717104406a50ae77fb2d60858fa7a1 Mon Sep 17 00:00:00 2001 From: mato533 Date: Fri, 13 Jun 2025 10:56:02 +0900 Subject: [PATCH 3/9] feat: module separation of AST parser --- packages/vscode-wdio-worker/package.json | 3 ++ .../vscode-wdio-worker/src/parsers/index.ts | 10 +++++-- .../vscode-wdio-worker/src/parsers/utils.ts | 14 +++++++++ .../tests/parsers/index.test.ts | 29 ++++++++----------- packages/vscode-webdriverio/src/parser/ast.ts | 1 + 5 files changed, 37 insertions(+), 20 deletions(-) diff --git a/packages/vscode-wdio-worker/package.json b/packages/vscode-wdio-worker/package.json index 2d094eb..192eb30 100644 --- a/packages/vscode-wdio-worker/package.json +++ b/packages/vscode-wdio-worker/package.json @@ -10,6 +10,9 @@ "./windows": { "import": "./dist/config.js" }, + "./parser/ast": { + "import": "./dist/parsers/js.js" + }, "./parser/cucumber": { "import": "./dist/parsers/cucumber.js" } diff --git a/packages/vscode-wdio-worker/src/parsers/index.ts b/packages/vscode-wdio-worker/src/parsers/index.ts index 3f3936b..b39340f 100644 --- a/packages/vscode-wdio-worker/src/parsers/index.ts +++ b/packages/vscode-wdio-worker/src/parsers/index.ts @@ -1,8 +1,7 @@ import * as fs from 'node:fs/promises' import path from 'node:path' -import { parseTestCases } from './js.js' -import { getCucumberParser } from './utils.js' +import { getAstParser, getCucumberParser } from './utils.js' import type { ReadSpecsOptions } from '@vscode-wdio/types/api' import type { WorkerMetaContext } from '@vscode-wdio/types/worker' @@ -11,6 +10,11 @@ async function parseFeatureFile(context: WorkerMetaContext, contents: string, no return p.call(context, contents, normalizeSpecPath) } +async function parseJsFile(context: WorkerMetaContext, contents: string, normalizeSpecPath: string) { + const p = await getAstParser(context) + return p.call(context, contents, normalizeSpecPath) +} + export async function parse(this: WorkerMetaContext, options: ReadSpecsOptions) { return await Promise.all( options.specs.map(async (spec) => { @@ -20,7 +24,7 @@ export async function parse(this: WorkerMetaContext, options: ReadSpecsOptions) try { const testCases = isCucumberFeatureFile(normalizeSpecPath) ? await parseFeatureFile(this, contents, normalizeSpecPath) // Parse Cucumber feature file - : parseTestCases.call(this, contents, normalizeSpecPath) // Parse JavaScript/TypeScript test file + : await parseJsFile(this, contents, normalizeSpecPath) // Parse JavaScript/TypeScript test file this.log.debug(`Successfully parsed: ${normalizeSpecPath}`) return { diff --git a/packages/vscode-wdio-worker/src/parsers/utils.ts b/packages/vscode-wdio-worker/src/parsers/utils.ts index e40cbfc..bad91af 100644 --- a/packages/vscode-wdio-worker/src/parsers/utils.ts +++ b/packages/vscode-wdio-worker/src/parsers/utils.ts @@ -2,12 +2,16 @@ import path from 'node:path' import type { WorkerMetaContext } from '@vscode-wdio/types/worker' import type { parseCucumberFeature } from './cucumber.js' +import type { parseTestCases } from './js.js' export type CucumberParser = typeof parseCucumberFeature +export type AstParser = typeof parseTestCases const CUCUMBER_PARSER_PATH = path.resolve(__dirname, 'parser/cucumber.cjs') +const AST_PARSER_PATH = path.resolve(__dirname, 'parser/ast.cjs') let cucumberParser: CucumberParser | undefined +let astParser: AstParser | undefined export async function getCucumberParser(context: WorkerMetaContext): Promise { if (cucumberParser) { @@ -18,3 +22,13 @@ export async function getCucumberParser(context: WorkerMetaContext): Promise { + if (astParser) { + context.log.debug('Use cached Ast parser') + return astParser + } + context.log.debug('Import Ast parser') + astParser = (await import(AST_PARSER_PATH)).parseTestCases as AstParser + return astParser +} diff --git a/packages/vscode-wdio-worker/tests/parsers/index.test.ts b/packages/vscode-wdio-worker/tests/parsers/index.test.ts index 2ce2475..dc1af90 100644 --- a/packages/vscode-wdio-worker/tests/parsers/index.test.ts +++ b/packages/vscode-wdio-worker/tests/parsers/index.test.ts @@ -6,12 +6,10 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest' // Import parse function from parsers import { parse } from '../../src/parsers/index.js' -import { parseTestCases } from '../../src/parsers/js.js' -import { getCucumberParser } from '../../src/parsers/utils.js' +import { getAstParser, getCucumberParser } from '../../src/parsers/utils.js' import type { ReadSpecsOptions } from '@vscode-wdio/types/api' import type { WorkerMetaContext, TestData, CucumberTestData } from '@vscode-wdio/types/worker' -// Import the types // Mock fs module vi.mock('node:fs/promises', () => ({ readFile: vi.fn(), @@ -20,14 +18,9 @@ vi.mock('node:fs/promises', () => ({ // Mock the parsers vi.mock('../../src/parsers/utils.js', () => ({ getCucumberParser: vi.fn(), + getAstParser: vi.fn(), })) -vi.mock('../../src/parsers/js.js', () => ({ - parseTestCases: vi.fn(), -})) - -// Import mocked modules - describe('Parser Index', () => { // Create mock context const mockContext: WorkerMetaContext = { @@ -59,6 +52,7 @@ describe('Parser Index', () => { ], }, ] + const mockAstParser = vi.fn(()=>jsMockTestData) const cucumberMockTestData: CucumberTestData[] = [ { @@ -93,8 +87,9 @@ describe('Parser Index', () => { vi.resetAllMocks() // Mock the parseTestCases and parseCucumberFeature functions - vi.mocked(parseTestCases).mockReturnValue(jsMockTestData) + // vi.mocked(parseTestCases).mockReturnValue(jsMockTestData) vi.mocked(getCucumberParser).mockResolvedValue(mockCucumberParser) + vi.mocked(getAstParser).mockResolvedValue(mockAstParser) }) afterEach(() => { @@ -120,7 +115,7 @@ describe('Parser Index', () => { expect(result[0].tests).toEqual(jsMockTestData) // Verify the correct parser was called - expect(parseTestCases).toHaveBeenCalledWith(jsTestContent, path.normalize('/path/to/test.js')) + expect(mockAstParser).toHaveBeenCalledWith(jsTestContent, path.normalize('/path/to/test.js')) expect(mockCucumberParser).not.toHaveBeenCalled() // Verify logging @@ -148,7 +143,7 @@ describe('Parser Index', () => { expect(result[0].tests).toEqual(jsMockTestData) // Verify the correct parser was called - expect(parseTestCases).toHaveBeenCalledWith(jsTestContent, path.normalize('/path/to/test.ts')) + expect(mockAstParser).toHaveBeenCalledWith(jsTestContent, path.normalize('/path/to/test.ts')) expect(mockCucumberParser).not.toHaveBeenCalled() }) @@ -174,7 +169,7 @@ describe('Parser Index', () => { cucumberFeatureContent, path.normalize('/path/to/test.feature') ) - expect(parseTestCases).not.toHaveBeenCalled() + expect(mockAstParser).not.toHaveBeenCalled() }) it('should handle uppercase feature file extensions', async () => { @@ -199,7 +194,7 @@ describe('Parser Index', () => { cucumberFeatureContent, path.normalize('/path/to/test.FEATURE') ) - expect(parseTestCases).not.toHaveBeenCalled() + expect(mockAstParser).not.toHaveBeenCalled() }) it('should parse multiple spec files', async () => { @@ -232,7 +227,7 @@ describe('Parser Index', () => { expect(result[1].tests).toEqual(cucumberMockTestData) // Verify the correct parsers were called - expect(parseTestCases).toHaveBeenCalledWith(jsTestContent, path.normalize('/path/to/test.js')) + expect(mockAstParser).toHaveBeenCalledWith(jsTestContent, path.normalize('/path/to/test.js')) expect(mockCucumberParser).toHaveBeenCalledWith( cucumberFeatureContent, path.normalize('/path/to/test.feature') @@ -269,7 +264,7 @@ describe('Parser Index', () => { expect(result[0].spec).toBe(path.normalize('C:\\path\\to\\test.js')) // Verify the parser was called with the normalized path - expect(parseTestCases).toHaveBeenCalledWith(jsTestContent, path.normalize('C:\\path\\to\\test.js')) + expect(mockAstParser).toHaveBeenCalledWith(jsTestContent, path.normalize('C:\\path\\to\\test.js')) }) it('should handle empty specs array', async () => { @@ -284,7 +279,7 @@ describe('Parser Index', () => { // Verify expect(result).toEqual([]) expect(fs.readFile).not.toHaveBeenCalled() - expect(parseTestCases).not.toHaveBeenCalled() + expect(mockAstParser).not.toHaveBeenCalled() expect(mockCucumberParser).not.toHaveBeenCalled() }) }) diff --git a/packages/vscode-webdriverio/src/parser/ast.ts b/packages/vscode-webdriverio/src/parser/ast.ts index 9a89e96..dd3275d 100644 --- a/packages/vscode-webdriverio/src/parser/ast.ts +++ b/packages/vscode-webdriverio/src/parser/ast.ts @@ -1 +1,2 @@ export { createTempConfigFile } from '@vscode-wdio/worker/windows' +export { parseTestCases } from '@vscode-wdio/worker/parser/ast' From 7fc54a335e095d78d9e4eb0bb0279529ac074db6 Mon Sep 17 00:00:00 2001 From: mato533 Date: Fri, 13 Jun 2025 11:26:38 +0900 Subject: [PATCH 4/9] chore: update esbuild config to write meta data only non-production --- infra/compiler/src/index.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/infra/compiler/src/index.ts b/infra/compiler/src/index.ts index 661f99d..2097fdc 100644 --- a/infra/compiler/src/index.ts +++ b/infra/compiler/src/index.ts @@ -60,6 +60,8 @@ if (entryPoints.length < 1) { throw new Error(`No export module found to build at: ${absWorkingDir}`) } +const outdir = path.resolve(absWorkingDir, 'dist') + const ctx = await context({ sourceRoot: absWorkingDir, entryPoints, @@ -69,10 +71,11 @@ const ctx = await context({ sourcemap: !options.production, sourcesContent: false, platform: 'node', - outdir: path.resolve(absWorkingDir, 'dist'), + outdir, outExtension: { '.js': '.cjs' }, external: ['vscode'], logLevel: 'silent', + metafile: true, plugins: [ /* add to the end of plugins array */ esbuildProblemMatcherPlugin, @@ -81,6 +84,10 @@ const ctx = await context({ if (options.watch) { await ctx.watch() } else { - await ctx.rebuild() + const result = await ctx.rebuild() await ctx.dispose() + + if (!options.production) { + fss.writeFileSync(path.join(outdir, 'meta.json'), JSON.stringify(result.metafile)) + } } From 93e1f2d8644a9d23273e39cfd209477b5f305fd9 Mon Sep 17 00:00:00 2001 From: mato533 Date: Fri, 13 Jun 2025 11:37:19 +0900 Subject: [PATCH 5/9] fix: formatting --- packages/vscode-wdio-worker/src/utils.ts | 5 ++--- packages/vscode-wdio-worker/tests/parsers/index.test.ts | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/vscode-wdio-worker/src/utils.ts b/packages/vscode-wdio-worker/src/utils.ts index 72899ae..b004258 100644 --- a/packages/vscode-wdio-worker/src/utils.ts +++ b/packages/vscode-wdio-worker/src/utils.ts @@ -10,14 +10,13 @@ const VSCODE_WINDOWS_CONFIG_CREATOR_PATH = path.resolve(__dirname, 'parser/ast.c let tempConfigCreator: TempConfigFileCreator | undefined export async function getTempConfigCreator(context: WorkerMetaContext): Promise { - if (tempConfigCreator){ + if (tempConfigCreator) { context.log.debug('Use cached TempConfigFileCreator') return tempConfigCreator } context.log.debug('Import TempConfigFileCreator') - tempConfigCreator =((await import(VSCODE_WINDOWS_CONFIG_CREATOR_PATH)).createTempConfigFile as TempConfigFileCreator) + tempConfigCreator = (await import(VSCODE_WINDOWS_CONFIG_CREATOR_PATH)).createTempConfigFile as TempConfigFileCreator return tempConfigCreator - } export function isWindows() { diff --git a/packages/vscode-wdio-worker/tests/parsers/index.test.ts b/packages/vscode-wdio-worker/tests/parsers/index.test.ts index dc1af90..2a11eb6 100644 --- a/packages/vscode-wdio-worker/tests/parsers/index.test.ts +++ b/packages/vscode-wdio-worker/tests/parsers/index.test.ts @@ -52,7 +52,7 @@ describe('Parser Index', () => { ], }, ] - const mockAstParser = vi.fn(()=>jsMockTestData) + const mockAstParser = vi.fn(() => jsMockTestData) const cucumberMockTestData: CucumberTestData[] = [ { @@ -81,7 +81,7 @@ describe('Parser Index', () => { metadata: {}, }, ] - const mockCucumberParser = vi.fn(()=>cucumberMockTestData) + const mockCucumberParser = vi.fn(() => cucumberMockTestData) beforeEach(() => { vi.resetAllMocks() From f77ed9071517adc92098fedcd2737bf3027f398f Mon Sep 17 00:00:00 2001 From: mato533 Date: Fri, 13 Jun 2025 12:02:31 +0900 Subject: [PATCH 6/9] fix: format url when execute dynamic import --- .../vscode-wdio-worker/src/parsers/utils.ts | 22 +++++--------- packages/vscode-wdio-worker/src/utils.ts | 29 ++++++++++++++----- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/packages/vscode-wdio-worker/src/parsers/utils.ts b/packages/vscode-wdio-worker/src/parsers/utils.ts index bad91af..e27bbaf 100644 --- a/packages/vscode-wdio-worker/src/parsers/utils.ts +++ b/packages/vscode-wdio-worker/src/parsers/utils.ts @@ -1,5 +1,6 @@ import path from 'node:path' +import { dynamicLoader } from '../utils.js' import type { WorkerMetaContext } from '@vscode-wdio/types/worker' import type { parseCucumberFeature } from './cucumber.js' import type { parseTestCases } from './js.js' @@ -14,21 +15,14 @@ let cucumberParser: CucumberParser | undefined let astParser: AstParser | undefined export async function getCucumberParser(context: WorkerMetaContext): Promise { - if (cucumberParser) { - context.log.debug('Use cached Cucumber parser') - return cucumberParser - } - context.log.debug('Import Cucumber parser') - cucumberParser = (await import(CUCUMBER_PARSER_PATH)).parseCucumberFeature as CucumberParser - return cucumberParser + return (await dynamicLoader( + context, + cucumberParser, + CUCUMBER_PARSER_PATH, + 'parseCucumberFeature' + )) as CucumberParser } export async function getAstParser(context: WorkerMetaContext): Promise { - if (astParser) { - context.log.debug('Use cached Ast parser') - return astParser - } - context.log.debug('Import Ast parser') - astParser = (await import(AST_PARSER_PATH)).parseTestCases as AstParser - return astParser + return (await dynamicLoader(context, astParser, AST_PARSER_PATH, 'parseTestCases')) as AstParser } diff --git a/packages/vscode-wdio-worker/src/utils.ts b/packages/vscode-wdio-worker/src/utils.ts index b004258..b447e37 100644 --- a/packages/vscode-wdio-worker/src/utils.ts +++ b/packages/vscode-wdio-worker/src/utils.ts @@ -1,4 +1,5 @@ import path from 'node:path' +import { pathToFileURL } from 'node:url' import type { WorkerMetaContext } from '@vscode-wdio/types' import type { createTempConfigFile } from './config.js' @@ -10,15 +11,29 @@ const VSCODE_WINDOWS_CONFIG_CREATOR_PATH = path.resolve(__dirname, 'parser/ast.c let tempConfigCreator: TempConfigFileCreator | undefined export async function getTempConfigCreator(context: WorkerMetaContext): Promise { - if (tempConfigCreator) { - context.log.debug('Use cached TempConfigFileCreator') - return tempConfigCreator - } - context.log.debug('Import TempConfigFileCreator') - tempConfigCreator = (await import(VSCODE_WINDOWS_CONFIG_CREATOR_PATH)).createTempConfigFile as TempConfigFileCreator - return tempConfigCreator + return (await dynamicLoader( + context, + tempConfigCreator, + VSCODE_WINDOWS_CONFIG_CREATOR_PATH, + 'createTempConfigFile' + )) as TempConfigFileCreator } export function isWindows() { return process.platform === 'win32' } + +export async function dynamicLoader( + context: WorkerMetaContext, + libModule: unknown, + modulePath: string, + fnName: string +): Promise { + if (libModule) { + context.log.debug(`Use cached ${path.dirname(modulePath)}`) + return libModule + } + context.log.debug(`Import ${path.basename(modulePath)}`) + libModule = (await import(pathToFileURL(modulePath).href))[fnName] + return libModule +} From 3252a7796741871f95e8548b9895bd1b86371bc1 Mon Sep 17 00:00:00 2001 From: mato533 Date: Fri, 13 Jun 2025 12:21:57 +0900 Subject: [PATCH 7/9] fix: reporter path for windows platform --- packages/vscode-wdio-worker/src/config.ts | 5 ++++- packages/vscode-wdio-worker/tests/config.test.ts | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/vscode-wdio-worker/src/config.ts b/packages/vscode-wdio-worker/src/config.ts index f5ade77..8d099dd 100644 --- a/packages/vscode-wdio-worker/src/config.ts +++ b/packages/vscode-wdio-worker/src/config.ts @@ -7,7 +7,10 @@ import * as t from '@babel/types' import recast from 'recast' const reporterIdentifierName = 'VscodeJsonReporter' -const VSCODE_REPORTER_PATH = path.resolve(__dirname, 'reporter.cjs') + +// This file is bundle as parser/ats.js at the package of vscode-webdriverio +// So, the correct reporter path is parent directory +const VSCODE_REPORTER_PATH = path.resolve(__dirname, '../reporter.cjs') /** * Since Windows cannot import by reporter file path due to issues with * the `initializePlugin` method of wdio-utils, the policy is to create a temporary configuration file. diff --git a/packages/vscode-wdio-worker/tests/config.test.ts b/packages/vscode-wdio-worker/tests/config.test.ts index cf2ac0e..de901f5 100644 --- a/packages/vscode-wdio-worker/tests/config.test.ts +++ b/packages/vscode-wdio-worker/tests/config.test.ts @@ -26,13 +26,13 @@ vi.mock('node:path', async (importOriginal) => { return { default: { ...actual, - resolve: vi.fn((_, f) => `/path/to/${f}`), + resolve: vi.fn((_, f) => actual.resolve(`/path/to/parser/${f}`)), }, } }) describe('config.ts', () => { - const VSCODE_REPORTER_PATH = path.resolve(__dirname, 'reporter.cjs') + const VSCODE_REPORTER_PATH = path.resolve(__dirname, '../reporter.cjs') const reporterPathUrl = pathToFileURL(VSCODE_REPORTER_PATH).href beforeEach(() => { From a8381fc495b2cd485f407daee6c38fa0e202fc83 Mon Sep 17 00:00:00 2001 From: mato533 Date: Fri, 13 Jun 2025 03:15:03 +0900 Subject: [PATCH 8/9] fix: failed to snapshot test on windows --- packages/vscode-wdio-worker/tests/config.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/vscode-wdio-worker/tests/config.test.ts b/packages/vscode-wdio-worker/tests/config.test.ts index de901f5..8403702 100644 --- a/packages/vscode-wdio-worker/tests/config.test.ts +++ b/packages/vscode-wdio-worker/tests/config.test.ts @@ -1,5 +1,6 @@ import fs from 'node:fs/promises' import path from 'node:path' +import { resolve as winResolve } from 'node:path/posix' import { pathToFileURL } from 'node:url' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' @@ -26,7 +27,7 @@ vi.mock('node:path', async (importOriginal) => { return { default: { ...actual, - resolve: vi.fn((_, f) => actual.resolve(`/path/to/parser/${f}`)), + resolve: vi.fn((_, f) => winResolve(`/path/to/parser/${f}`)), }, } }) From c58cae154cea6a64b8eda7196694fcc6a5973de9 Mon Sep 17 00:00:00 2001 From: mato533 Date: Fri, 13 Jun 2025 12:46:18 +0900 Subject: [PATCH 9/9] fix: improve test for config.ts --- packages/vscode-wdio-worker/tests/config.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/vscode-wdio-worker/tests/config.test.ts b/packages/vscode-wdio-worker/tests/config.test.ts index 8403702..4e52b73 100644 --- a/packages/vscode-wdio-worker/tests/config.test.ts +++ b/packages/vscode-wdio-worker/tests/config.test.ts @@ -1,6 +1,5 @@ import fs from 'node:fs/promises' import path from 'node:path' -import { resolve as winResolve } from 'node:path/posix' import { pathToFileURL } from 'node:url' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' @@ -27,7 +26,7 @@ vi.mock('node:path', async (importOriginal) => { return { default: { ...actual, - resolve: vi.fn((_, f) => winResolve(`/path/to/parser/${f}`)), + resolve: vi.fn((_, f) => path.posix.resolve(`/path/to/parser/${f}`)), }, } })