cypress icon indicating copy to clipboard operation
cypress copied to clipboard

Angular Component Testing cannot find type definition files

Open cg-roling opened this issue 1 year ago • 2 comments

Current behavior

When running Cypress component files, type definition files added to compilerOptions.types in tsconfig.app.json are not found.

If I add the "node" type definitions, I get the following output from npx cypress run --component:

asset cypress_support_component_ts.js 2.38 MiB {cypress_support_component_ts} [cached] (name: Volumes-Files-git-cy-comp-cypress-support-component-ts) 1 related asset
asset default-node_modules_angular_core_fesm2020_core_mjs.js 1.2 MiB {default-node_modules_angular_core_fesm2020_core_mjs} [cached] (name: Volumes-Files-git-cy-comp-cypress-support-component-ts) (i
d hint: default) 1 related asset
asset polyfills.js 318 KiB {polyfills} [cached] (name: polyfills) 1 related asset
asset cypress-entry.js 213 KiB {cypress-entry} [cached] (name: cypress-entry) 1 related asset
asset styles.js 209 KiB {styles} [cached] (name: styles) 1 related asset
asset runtime.js 12.6 KiB {runtime} [cached] (name: runtime) 1 related asset
asset spec-0.js 2.11 KiB {spec-0} [cached] (name: spec-0) 1 related asset
asset favicon.ico 948 bytes [cached] [from: src/favicon.ico] [copied]
asset styles.css 736 bytes {styles} [cached] (name: styles) 1 related asset
asset index.html 605 bytes [cached]
Entrypoint polyfills = runtime.js polyfills.js 2 auxiliary assets
Entrypoint styles = runtime.js styles.css styles.js 3 auxiliary assets
Entrypoint cypress-entry = runtime.js cypress-entry.js 2 auxiliary assets
chunk {cypress-entry} (runtime: runtime) cypress-entry.js (cypress-entry) 196 KiB [initial] [rendered]
chunk {cypress_support_component_ts} (runtime: runtime) cypress_support_component_ts.js (Volumes-Files-git-cy-comp-cypress-support-component-ts) 2.32 MiB [rendered]
chunk {default-node_modules_angular_core_fesm2020_core_mjs} (runtime: runtime) default-node_modules_angular_core_fesm2020_core_mjs.js (Volumes-Files-git-cy-comp-cypress-support-component-ts) (id hi
nt: default) 1.14 MiB [rendered] split chunk (cache group: default)
chunk {polyfills} (runtime: runtime) polyfills.js (polyfills) 303 KiB [initial] [rendered]
chunk {runtime} (runtime: runtime) runtime.js (runtime) 7.59 KiB [entry] [rendered]
chunk {spec-0} (runtime: runtime) spec-0.js (spec-0) 871 bytes [rendered]
chunk {styles} (runtime: runtime) styles.css, styles.js (styles) 195 KiB (javascript) 80 bytes (css/mini-extract) [initial] [rendered]

ERROR in error TS2688: Cannot find type definition file for 'node'.
  The file is in the program because:
    Entry point of type library 'node' specified in compilerOptions

Desired behavior

tsconfig "types" should be found for component tests

Test code to reproduce

Reproduction is available here: https://github.com/cg-roling/cypress-component-types-repro

I followed the Getting Started Guide and created a new Angular project, along with a component and spec.

npx cypress run --component works perfectly at this point.

Then I edited tsconfig.app.json and added "node" to the types config option. I used "node" because it's already installed, any type definition causes the same error.

npx cypress run --component now shows:

ERROR in error TS2688: Cannot find type definition file for 'node'.
  The file is in the program because:
    Entry point of type library 'node' specified in compilerOptions

This is my edited tsconfig.app.json:

/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "./out-tsc/app",
    "types": ["node"]
  },
  "files": ["src/main.ts", "src/polyfills.ts"],
  "include": ["src/**/*.d.ts"]
}

Cypress Version

10.8.0

Node version

v16.14.2

Operating System

macOS 13 Beta

Debug Logs

Logs are too long to include here, I can include relevant parts if necessary.

Other

Type definitions in local .d.ts files appear to be missing as well.

cg-roling avatar Sep 15 '22 23:09 cg-roling

@cg-roling thanks for opening the issue, I was able to reproduce the problem with your provided repo, we are going to have to change how we generate/manage our handling of the tsconfigs in order to get a fix for this problem.

In the meantime, you should be able to workaround this issue by using the /// <reference types="x" /> in your cypress/support/component.ts file. For example, if you wanted to include the types for "node" you would add:

/// <reference types="node" />

and that will add the types to the compilation. I'm going to follow up with my ideas on how to get a proper fix for this problem.

Edit:

Following up on this, this issue points out two issues that we have with our current Angular implementation for handling types/tsconfig.

  1. The first problem is that types: [...] in the user's tsconfig.app.json (or the tsconfig specified in devServer.options.projectConfig) aren't being included. From my investigation, this is due to where we generate the tsconfig for the project which is an os-specific temporary directory. By default, the typeRoots property is configured to recursively search for node_modules/@types relative to the location of the tsconfig. Since this "temporary" tsconfig is not generated inside the project, it won't find the project's node_modules/@types. Changing the temporary tsconfig to be generated inside the project would alleviate this problem and we could utilize a commonly gitignored folder ("dist", "out-tsc", "tmp", even "node_modules"). We could also set typeRoots to point to the project, but would have to verify if the recursive search works to handle monorepos.
  2. The second problem is that the tsconfig we generate overrides the include property that the extended tsconfig might have. For example if the user's tsconfig.app.json has "include": ["src/**/*.d.ts"], their declaration files wouldn't be included. An option here would be to concat the existing include into the array that we generate in our tsconfig to preserve this.

For context, when building the Angular application we don't use the given tsconfig property found in the build options but rather extend from it by generating another tsconfig. These issues are a result of this decision where the location of this generated tsconfig affects the type resolution and the merging/overriding of the properties changes the properties that the user might expect to not be changed.

Another option to remove a lot of this complexity would be to scaffold a tsconfig.cypress.json (source-controlled) that would be used rather than generating one on demand. That way, the user could modify this file to add types and change the compilation options themselves if need be. This would make it very transparent as to what files and options are being used to compile their application rather than obfuscate it from the user.

ZachJW34 avatar Sep 19 '22 15:09 ZachJW34

Awesome, thanks for the workaround, that should get us going for sure!

In terms of a fix, from my perspective anyway, a "real" tsconfig.cypress.json rather than a generated one certainly seems easier to debug.

cg-roling avatar Sep 19 '22 18:09 cg-roling