bahmutov / bahmutov/cypress-split

Empty spec location outside project tree breaks tsconfig path aliases in supportFile

Open
#493 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
285
Forks
28
PR merge metrics
No merged PRs in 30d

Description

### Environment

- cypress-split: 1.24.31
- Cypress: 15.17.0 (batteries-included webpack preprocessor)
- Node: v22.22.3
- TypeScript: 5.9.3
- Monorepo (Nx) with TS path aliases declared in a root tsconfig.base.json, extended by the app's tsconfig.json

### What happens

When a split chunk gets no specs, cypress-split falls back to copying its empty placeholder spec into the OS temp dir:

cypress-split: chunk 2 of 8
cypress-split: no specs to run, running an empty spec file /tmp/empty-2-of-8.cy.js

Cypress then still loads the project's supportFile (src/support/e2e.ts) before that empty spec. The support file uses TS path aliases:
```typescript
import '@app/e2e-support/setup';
import './commands'; // -> import '@app/e2e-support/commands/global';
````
Bundling fails:
```sh
Oops...we found an error preparing this test file:
> src/support/e2e.ts

Error: Webpack Compilation Error
Module not found: Error: Can't resolve '@app/e2e-support/commands/global' ...
Module not found: Error: Can't resolve '@app/e2e-support/setup' ...
```
The exact same run works fine on any chunk that does receive specs.

Root cause

The empty spec is written to a emp diretorcy outside the cypress project folder

// src/index.js
```javascript
const tempFilename = path.join(
os.tmpdir(),
`empty-${splitIndex + 1}-of-${splitN}.cy.js`,
)
const emptyFilename = path.resolve(__dirname, 'empty-spec.cy.js')
fs.copyFileSync(emptyFilename, tempFilename)
config.specPattern = tempFilename
```
Cypress's batteries-included webpack preprocessor resolves the tsconfig.json relative to the spec file's path (via get-tsconfig, walking up from file.filePath). It only registers tsconfig-paths-webpack-plugin when a tsconfig is found:
```javascript
const configFile = getTsconfig.getTsconfig(file.filePath);
// ...
if (configFile?.path) {
webpackOptions.resolve.plugins = [new TsconfigPathsPlugin({ configFile: configFile.path, silent: true })];
}
```
Because the spec lives in /tmp, no tsconfig.json is found in its parent hierarchy, so configFile is null and the paths plugin is never registered. The support file (which is inside the project and relies on those aliases) is bundled in that
same compilation and its @app/* imports fail to resolve

This happens since the update from cypress 15.14.2 to any cypress version >=15.15.0

### Workaround
A workaround is to manually specify where to find the tsconfig file:

// cypress.config.ts
```typescript
import webpackPreprocessor from '@cypress/webpack-preprocessor';
import { defineConfig } from 'cypress';
import cypressSplit from 'cypress-split';
import { TsconfigPathsPlugin } from 'tsconfig-paths-webpack-plugin';

const tsConfigFile = path.resolve(__dirname, 'tsconfig.json');
export default defineConfig({
allowCypressEnv: false,
e2e: {
async setupNodeEvents(on, config) {
on(
'file:preprocessor',
webpackPreprocessor({
webpackOptions: {
resolve: {
extensions: ['.ts', '.tsx', '.js'],
plugins: [new TsconfigPathsPlugin({ configFile: tsConfigFile })],
},
module: {
rules: [
{
test: /\.tsx?$/,
exclude: /node_modules/,
use: [
{
loader: 'ts-loader',
options: {
configFile: tsConfigFile,
transpileOnly: true,
},
},
],
},
],
},
},
}),
);
cypressSplit(on, config);
return config;
},
},
});
```

Contributor guide

No contributing guide indexed for this repository

Research direction

Start in src/index.js at the empty-spec fallback that copies empty-spec.cy.js into the OS temp directory. Reproduce with Cypress 15.15 or newer in a TypeScript project using path aliases, then inspect how an empty chunk is preprocessed alongside src/support/e2e.ts. Done means empty chunks can bundle the support file and resolve its aliases without the manual webpack workaround.

Written by the indexing model from the issue text.

Assessment

Tech stack
cypress, javascript, typescript, webpack
Domain
testing-qa
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
62/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.