Skip to content

Commit a0d374d

Browse files
authored
refactor(electron): move esm / cjs testing from e2es to package tests (#38)
* refactor: move esm / cjs testing from e2es to package tests * chore: fix workflow * chore: update workspace * chore: use matrix for package tests * chore: update lockfile * fix: update vite confs
1 parent 3dec067 commit a0d374d

File tree

137 files changed

+2538
-1293
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

137 files changed

+2538
-1293
lines changed

.github/workflows/_ci-e2e.reusable.yml

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: E2E Tests
2-
description: 'Runs end-to-end tests across different scenarios and JavaScript module types'
2+
description: 'Runs end-to-end tests across different scenarios (ESM only)'
33

44
on:
55
workflow_call:
@@ -22,10 +22,6 @@ on:
2222
description: 'Test scenario (forge, builder, or no-binary)'
2323
required: true
2424
type: string
25-
type:
26-
description: 'JavaScript module type (esm, cjs, or * for both)'
27-
type: string
28-
default: '*'
2925
build_id:
3026
description: 'Build ID from the build job'
3127
type: string
@@ -47,7 +43,7 @@ jobs:
4743
# This job runs E2E tests for a specific combination of:
4844
# - Operating system (Linux, Windows, macOS)
4945
# - Test scenario (builder, forge, no-binary)
50-
# - Module type (ESM, CJS, or both)
46+
# - E2E tests use ESM only (CJS/ESM testing is done in package tests)
5147
e2e:
5248
name: E2E Tests
5349
runs-on: ${{ inputs.os }}
@@ -86,20 +82,20 @@ jobs:
8682
echo "::notice::Build artifact: ID=${{ inputs.build_id }}, Size=${{ inputs.artifact_size }} bytes"
8783
8884
# Dynamically generate the Turbo filter for building test applications
89-
# This converts the scenario and type inputs into Turbo filter syntax
85+
# This converts the scenario input into Turbo filter syntax
9086
- name: 🪄 Generate Build Filter for Test Apps
9187
id: gen-build
9288
uses: actions/github-script@v8
9389
with:
9490
result-encoding: string
9591
script: |
96-
const generateBuildFilter = (scenario, type) => {
92+
const generateBuildFilter = (scenario) => {
9793
return scenario
9894
.split(',')
99-
.map((s) => `--filter=electron-${s.trim()}-${type}-e2e-app`)
95+
.map((s) => `--filter=electron-${s.trim()}-e2e-app`)
10096
.join(' ');
10197
};
102-
return generateBuildFilter('${{ inputs.scenario }}', '${{ inputs.type }}');
98+
return generateBuildFilter('${{ inputs.scenario }}');
10399
104100
# Build the test applications using Turbo with the generated filter
105101
# This builds only the necessary test apps for the current test configuration
@@ -108,25 +104,23 @@ jobs:
108104
run: pnpm exec turbo run ${{ inputs.build-command }} ${{ steps.gen-build.outputs.result }} --only --parallel
109105

110106
# Dynamically generate the test commands to run
111-
# This handles both single and multiple scenarios, and ESM/CJS/both
107+
# This handles both single and multiple scenarios
112108
- name: 🪄 Generate Test Execution Plan
113109
id: gen-test
114110
uses: actions/github-script@v8
115111
with:
116112
result-encoding: string
117113
script: |
118-
const generateTestCommand = (scenario, type) => {
114+
const generateTestCommand = (scenario) => {
119115
return scenario
120116
.split(',')
121-
.flatMap((s) => {
117+
.map((s) => {
122118
const scenarioTrimmed = s.trim();
123-
return type === '*'
124-
? [`test:e2e:electron-${scenarioTrimmed}-esm`, `test:e2e:electron-${scenarioTrimmed}-cjs`]
125-
: [`test:e2e:electron-${scenarioTrimmed}-${type}`];
119+
return `test:e2e:electron-${scenarioTrimmed}`;
126120
})
127121
.join(' ');
128122
};
129-
return generateTestCommand('${{ inputs.scenario }}', '${{ inputs.type }}');
123+
return generateTestCommand('${{ inputs.scenario }}');
130124
131125
# Run the E2E tests using Turbo with the generated test commands
132126
# Each test builds its own apps with correct environment context
@@ -146,8 +140,8 @@ jobs:
146140
uses: ./.github/workflows/actions/upload-archive
147141
if: failure()
148142
with:
149-
name: e2e-logs-${{ inputs.os }}${{ contains(inputs.build-command, 'mac-universal') && '-u' || '' }}-${{ inputs.scenario }}${{ inputs.type != '*' && format('-{0}',inputs.type) || '' }}
150-
output: e2e-logs-${{ inputs.os }}${{ contains(inputs.build-command, 'mac-universal') && '-u' || '' }}-${{ inputs.scenario }}${{ inputs.type != '*' && format('-{0}',inputs.type) || '' }}.zip
143+
name: e2e-logs-${{ inputs.os }}${{ contains(inputs.build-command, 'mac-universal') && '-u' || '' }}-${{ inputs.scenario }}
144+
output: e2e-logs-${{ inputs.os }}${{ contains(inputs.build-command, 'mac-universal') && '-u' || '' }}-${{ inputs.scenario }}.zip
151145
paths: e2e/logs/**/*.log
152146

153147
# Provide an interactive debugging session on failure

.github/workflows/_ci-package.reusable.yml

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ on:
1515
type: string
1616
required: false
1717
default: 'both'
18+
module-type:
19+
description: 'Module type for Electron package tests (cjs, esm, or both)'
20+
type: string
21+
required: false
22+
default: 'both'
1823
build_id:
1924
description: 'Build ID from the build job'
2025
type: string
@@ -160,7 +165,8 @@ jobs:
160165
case "${{ inputs.service }}" in
161166
electron)
162167
echo "Running Electron package tests (apps built in isolated environments)"
163-
pnpm run test:package:electron
168+
echo "Module type: ${{ inputs.module-type }}"
169+
pnpm run test:package:electron -- --module-type=${{ inputs.module-type }}
164170
;;
165171
tauri)
166172
if [ "${{ inputs.os }}" == "macos-latest" ]; then
@@ -178,11 +184,13 @@ jobs:
178184
both)
179185
if [ "${{ inputs.os }}" == "macos-latest" ]; then
180186
echo "⚠️ Skipping Tauri package tests on macOS (not supported)"
181-
pnpm run test:package:electron
187+
echo "Module type: ${{ inputs.module-type }}"
188+
pnpm run test:package:electron -- --module-type=${{ inputs.module-type }}
182189
else
183190
echo "Running all package tests (Electron built in isolated environments, Tauri using pre-built binaries)"
191+
echo "Module type: ${{ inputs.module-type }}"
184192
# Electron: build in isolated environments (no --skip-build)
185-
pnpm run test:package:electron
193+
pnpm run test:package:electron -- --module-type=${{ inputs.module-type }}
186194
# Tauri: use --skip-build for pre-built binaries from separate build job
187195
if [ "${{ inputs.os }}" == "ubuntu-latest" ]; then
188196
xvfb-run -a pnpm run test:package:tauri -- --skip-build

.github/workflows/ci.yml

Lines changed: 13 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -87,35 +87,20 @@ jobs:
8787
# Split Electron and Tauri tests across separate jobs for better parallelization and clarity
8888
# Electron apps are built inline on the test runner (faster builds, Turbo caching handles it)
8989
# Tauri apps are built separately due to longer build times and system dependencies
90-
package-electron-linux:
91-
name: Package - Electron [Linux]
92-
needs: [build, lint]
93-
uses: ./.github/workflows/_ci-package.reusable.yml
94-
with:
95-
os: 'ubuntu-latest'
96-
service: 'electron'
97-
build_id: ${{ needs.build.outputs.build_id }}
98-
artifact_size: ${{ needs.build.outputs.artifact_size }}
99-
cache_key: ${{ needs.build.outputs.cache_key }}
100-
101-
package-electron-windows:
102-
name: Package - Electron [Windows]
103-
needs: [build, lint]
104-
uses: ./.github/workflows/_ci-package.reusable.yml
105-
with:
106-
os: 'windows-latest'
107-
service: 'electron'
108-
build_id: ${{ needs.build.outputs.build_id }}
109-
artifact_size: ${{ needs.build.outputs.artifact_size }}
110-
cache_key: ${{ needs.build.outputs.cache_key }}
111-
112-
package-electron-macos:
113-
name: Package - Electron [macOS]
90+
# Electron package tests are split by module type (CJS/ESM) for better error isolation
91+
package-electron-matrix:
92+
name: Package - Electron [${{ matrix.os == 'ubuntu-latest' && 'Linux' || matrix.os == 'windows-latest' && 'Windows' || 'macOS' }}] - ${{ matrix.module-type }}
11493
needs: [build, lint]
94+
strategy:
95+
fail-fast: false
96+
matrix:
97+
os: ['ubuntu-latest', 'windows-latest', 'macos-latest']
98+
module-type: ['cjs', 'esm']
11599
uses: ./.github/workflows/_ci-package.reusable.yml
116100
with:
117-
os: 'macos-latest'
101+
os: ${{ matrix.os }}
118102
service: 'electron'
103+
module-type: ${{ matrix.module-type }}
119104
build_id: ${{ needs.build.outputs.build_id }}
120105
artifact_size: ${{ needs.build.outputs.artifact_size }}
121106
cache_key: ${{ needs.build.outputs.cache_key }}
@@ -159,10 +144,10 @@ jobs:
159144
# E2E test matrix strategy:
160145
# - Run tests across 3 operating systems (Linux, Windows, macOS)
161146
# - Test 3 scenarios (builder, forge, no-binary)
162-
# - Test 2 module types (ESM, CJS)
147+
# - E2E tests use ESM only (CJS/ESM testing is done in package tests)
163148
# - Optimize for GitHub Actions concurrency limits
164149
e2e-matrix:
165-
name: E2E - Electron [${{ matrix.os == 'ubuntu-latest' && 'Linux' || matrix.os == 'windows-latest' && 'Windows' || 'macOS' }}] - ${{ matrix.scenario }}${{ matrix.type != '*' && format(' ({0})', matrix.type) || '' }}
150+
name: E2E - Electron [${{ matrix.os == 'ubuntu-latest' && 'Linux' || matrix.os == 'windows-latest' && 'Windows' || 'macOS' }}] - ${{ matrix.scenario }}
166151
needs: [build]
167152
strategy:
168153
fail-fast: false
@@ -171,23 +156,11 @@ jobs:
171156
os: ['ubuntu-latest', 'windows-latest', 'macos-latest']
172157
# Test all application scenarios
173158
scenario: ['builder', 'forge', 'no-binary']
174-
# Test both module types and wildcard for combined tests
175-
type: ['esm', 'cjs', '*']
176-
exclude:
177-
# Optimization: All platforms run ESM and CJS separately for consistent resource management
178-
# This prevents individual jobs from running too many test variants simultaneously
179-
- os: 'ubuntu-latest'
180-
type: '*'
181-
- os: 'windows-latest'
182-
type: '*'
183-
- os: 'macos-latest'
184-
type: '*'
185159
uses: ./.github/workflows/_ci-e2e.reusable.yml
186160
with:
187161
os: ${{ matrix.os }}
188162
node-version: '20'
189163
scenario: ${{ matrix.scenario }}
190-
type: ${{ matrix.type }}
191164
build_id: ${{ needs.build.outputs.build_id }}
192165
artifact_size: ${{ needs.build.outputs.artifact_size }}
193166
cache_key: ${{ needs.build.outputs.cache_key }}
@@ -258,28 +231,19 @@ jobs:
258231
# Mac Universal builds require special handling
259232
# These are separate from regular macOS tests because they use a different build command
260233
e2e-mac-universal-matrix:
261-
name: E2E [macOS-U] - ${{ matrix.scenario }}${{ matrix.type != '*' && format(' ({0})', matrix.type) || '' }}
234+
name: E2E [macOS-U] - ${{ matrix.scenario }}
262235
needs: [build]
263236
strategy:
264237
fail-fast: false
265238
matrix:
266239
# Test both application scenarios
267240
scenario: ['forge', 'builder']
268-
# Test both module types and wildcard for combined tests
269-
type: ['esm', 'cjs', '*']
270-
exclude:
271-
# Optimization: Both forge and builder tests run ESM and CJS separately for better error isolation
272-
- scenario: 'forge'
273-
type: '*'
274-
- scenario: 'builder'
275-
type: '*'
276241
uses: ./.github/workflows/_ci-e2e.reusable.yml
277242
with:
278243
os: 'macos-latest'
279244
node-version: '20'
280245
build-command: 'build:mac-universal'
281246
scenario: ${{ matrix.scenario }}
282-
type: ${{ matrix.type }}
283247
build_id: ${{ needs.build.outputs.build_id }}
284248
artifact_size: ${{ needs.build.outputs.artifact_size }}
285249
cache_key: ${{ needs.build.outputs.cache_key }}

e2e/README.md

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ The testing framework uses environment variables to control test execution:
5555
- **`APP`**: Application type
5656
- For Electron: `builder` | `forge` | `no-binary`
5757
- For Tauri: `basic` | `advanced`
58-
- **`MODULE_TYPE`**: Module system (`cjs` | `esm`)
5958
- **`TEST_TYPE`**: Test execution mode (`standard` | `window` | `multiremote` | `standalone`)
6059
- **`BINARY`**: Binary mode (`true` | `false`)
6160

@@ -113,14 +112,7 @@ pnpm e2e:multiremote
113112
pnpm e2e:standalone
114113
```
115114

116-
#### Module Type-Specific
117-
```bash
118-
# CommonJS tests
119-
pnpm e2e:cjs
120-
121-
# ES Module tests
122-
pnpm e2e:esm
123-
```
115+
**Note**: E2E tests use ESM only. CJS/ESM module system testing is done in package tests (see `fixtures/package-tests/`).
124116

125117
### Test Matrix Script
126118

@@ -251,15 +243,16 @@ tsx scripts/build-apps.ts --clean
251243
## Test Applications
252244

253245
### Electron Test Apps
254-
Located in `../fixtures/electron-apps/`:
255-
- `builder-cjs` / `builder-esm`: Electron Builder apps
256-
- `forge-cjs` / `forge-esm`: Electron Forge apps
257-
- `no-binary-cjs` / `no-binary-esm`: Development mode apps
246+
Located in `../fixtures/e2e-apps/`:
247+
- `electron-builder`: Electron Builder app (ESM only)
248+
- `electron-forge`: Electron Forge app (ESM only)
249+
- `electron-no-binary`: Development mode app (ESM only)
250+
251+
**Note**: E2E tests use ESM-only apps. CJS/ESM variants are tested in package tests.
258252

259253
### Tauri Test Apps
260-
Located in `../fixtures/tauri-apps/`:
261-
- `basic`: Basic Tauri app with core functionality
262-
- `advanced`: Advanced Tauri app with complex features
254+
Located in `../fixtures/e2e-apps/`:
255+
- `tauri`: Tauri app with core functionality
263256

264257
## CI/CD Integration
265258

@@ -281,7 +274,7 @@ Tests are integrated with Turborepo for efficient execution:
281274
282275
```bash
283276
# Run specific test combinations
284-
turbo run test:e2e:electron-builder-cjs
277+
turbo run test:e2e:electron-builder
285278
turbo run test:e2e:tauri
286279
```
287280

e2e/config/envSchema.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export const EnvSchema = z.object({
1010
// Core test configuration
1111
FRAMEWORK: z.enum(['electron', 'tauri']).default('electron'),
1212
APP: z.enum(['builder', 'forge', 'no-binary', 'basic']).default('builder'),
13-
MODULE_TYPE: z.enum(['cjs', 'esm']).default('esm'),
13+
MODULE_TYPE: z.enum(['cjs', 'esm']).optional().default('esm'),
1414
TEST_TYPE: z.enum(['standard', 'window', 'multiremote', 'standalone']).default('standard'),
1515
BINARY: z.enum(['true', 'false']).default('true'),
1616

@@ -68,7 +68,7 @@ export class EnvironmentContext {
6868
}
6969

7070
get moduleType(): 'cjs' | 'esm' {
71-
return this.env.MODULE_TYPE;
71+
return this.env.MODULE_TYPE ?? 'esm';
7272
}
7373

7474
get testType(): 'standard' | 'window' | 'multiremote' | 'standalone' {
@@ -107,7 +107,7 @@ export class EnvironmentContext {
107107
return this.env.EXAMPLE_DIR;
108108
}
109109

110-
return getE2EAppDirName(this.framework, this.app, this.moduleType, this.isNoBinary);
110+
return getE2EAppDirName(this.framework, this.app, this.isNoBinary);
111111
}
112112

113113
/**
@@ -167,7 +167,6 @@ export class EnvironmentContext {
167167
return {
168168
FRAMEWORK: merged.FRAMEWORK,
169169
APP: merged.APP,
170-
MODULE_TYPE: merged.MODULE_TYPE,
171170
TEST_TYPE: merged.TEST_TYPE,
172171
BINARY: merged.BINARY,
173172
APP_DIR: merged.APP_DIR || '',
@@ -183,7 +182,7 @@ export class EnvironmentContext {
183182
* Get human-readable description of this environment
184183
*/
185184
toString(): string {
186-
const parts = [this.framework, this.app, this.moduleType, this.testType, this.isBinary ? 'binary' : 'no-binary'];
185+
const parts = [this.framework, this.app, this.testType, this.isBinary ? 'binary' : 'no-binary'];
187186

188187
if (this.isMacUniversal) parts.push('mac-universal');
189188
if (this.isSplashEnabled) parts.push('splash');

e2e/lib/utils.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -233,19 +233,17 @@ export function safeJsonParse<T>(json: string, fallback: T): T {
233233
}
234234

235235
/**
236-
* Compute the E2E app directory name based on framework, app type, module type, and binary mode.
236+
* Compute the E2E app directory name based on framework, app type, and binary mode.
237237
* This is used consistently across envSchema, build scripts, and test runners.
238238
*
239239
* @param framework - 'electron' or 'tauri'
240240
* @param app - App type: 'builder', 'forge', 'no-binary', or 'basic' (for Tauri)
241-
* @param moduleType - 'cjs' or 'esm' (only used for Electron)
242241
* @param isNoBinary - Whether this is a no-binary mode (only used for Electron)
243242
* @returns The computed directory name
244243
*/
245244
export function getE2EAppDirName(
246245
framework: 'electron' | 'tauri',
247246
app: 'builder' | 'forge' | 'no-binary' | 'basic',
248-
moduleType: 'cjs' | 'esm',
249247
isNoBinary: boolean,
250248
): string {
251249
if (framework === 'tauri') {
@@ -254,8 +252,8 @@ export function getE2EAppDirName(
254252
}
255253

256254
if (isNoBinary) {
257-
return `electron-no-binary-${moduleType}`;
255+
return 'electron-no-binary';
258256
}
259257

260-
return `electron-${app}-${moduleType}`;
258+
return `electron-${app}`;
261259
}

0 commit comments

Comments
 (0)