analog icon indicating copy to clipboard operation
analog copied to clipboard

Error: EISDIR: illegal operation on a directory, read (npm test)

Open aelbore opened this issue 1 year ago • 14 comments

Please provide the environment you discovered this bug in.

stackblitz https://stackblitz.com/edit/stackblitz-starters-yjhfgh

Just download and run it locally

Which area/package is the issue in?

vite-plugin-angular

Description

when running the test it has "Error: EISDIR: illegal operation on a directory" error. when using "happy-dom" and "jsdom" with "[email protected]"

it works fine if

  • when it using playwright it works fine with
  • using "happy-dom" and "jsdom" with "[email protected]"

Note: not too sure if this is analogjs issue or with vite/vitest

Please provide the exception or error you saw

"Error: EISDIR: illegal operation on a directory"

Other information

No response

I would be willing to submit a PR to fix this issue

  • [ ] Yes
  • [ ] No

aelbore avatar Apr 05 '24 10:04 aelbore

I've run into a similar issue also in another repo. Did some digging here and it has something to do with the bundling of rxjs. If you disable the angular plugin, you get.

 FAIL  src/app.component.spec.ts [ src/app.component.spec.ts ]
Error: Directory import '/Users/dev/projects/stackblitz-starters-yjhfgh/node_modules/rxjs/operators' is not supported resolving ES modules imported from /Users/dev/projects/stackblitz-starters-yjhfgh/node_modules/@angular/core/fesm2022/testing.mjs
Did you mean to import rxjs/operators/index.js?
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
Serialized Error: { url: 'file:///Users/dev/projects/stackblitz-starters-yjhfgh/node_modules/rxjs/operators', code: 'ERR_UNSUPPORTED_DIR_IMPORT' }

If you go into the .mjs files and replace rxjs/operators with rxjs/operators/index.js, it works fine.

brandonroberts avatar Apr 05 '24 13:04 brandonroberts

@brandonroberts thanks will try this, by the way thanks for the plugin great job ^_^

aelbore avatar Apr 05 '24 13:04 aelbore

Found a workaround.

/// <reference types="vitest" />
import { defineConfig } from 'vite';

import angular from '@analogjs/vite-plugin-angular';

export default defineConfig(({ mode }) => ({
  plugins: [angular()],
  test: {
    globals: true,
    setupFiles: ['src/test-setup.ts'],
    environment: 'happy-dom',
    include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
    reporters: ['default'],
    server: {
      deps: {
        inline: [/fesm2022/]
      }
    }
  },
  define: {
    'import.meta.vitest': mode !== 'production',
  },
}));

We're already doing this internally but only for cdk/fesm libraries because it slows down running the tests.

brandonroberts avatar Apr 05 '24 16:04 brandonroberts

Found a workaround.

/// <reference types="vitest" />
import { defineConfig } from 'vite';

import angular from '@analogjs/vite-plugin-angular';

export default defineConfig(({ mode }) => ({
  plugins: [angular()],
  test: {
    globals: true,
    setupFiles: ['src/test-setup.ts'],
    environment: 'happy-dom',
    include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
    reporters: ['default'],
    server: {
      deps: {
        inline: [/fesm2022/]
      }
    }
  },
  define: {
    'import.meta.vitest': mode !== 'production',
  },
}));

We're already doing this internally but only for cdk/fesm libraries because it slows down running the tests.

@brandonroberts wow this works for me, is this just a work around if using [email protected]? thank you so much on this, i didnt know theres server options in test

aelbore avatar Apr 05 '24 17:04 aelbore

@aelbore not sure if its only needed for rxjs 6.x because our tests are running fine without it on RxJS 7.x. Maybe it surfaced as a result of switching to ESM.

I may add it as a config option because of the performance cost, but I'd prefer to not include it by default.

brandonroberts avatar Apr 05 '24 18:04 brandonroberts

I ran into this error as well with RxJs 7.x. The workaround works for me.

ahnpnl avatar May 29 '24 06:05 ahnpnl

I ran into this error as well with RxJs 7.x. The workaround works for me.

What version of RxJS was it?

brandonroberts avatar May 30 '24 03:05 brandonroberts

It is 7.8.1, this is the repo https://github.com/ahnpnl/monorepo-multi-apps

To reproduce:

  • uncomment the workaround in https://github.com/ahnpnl/monorepo-multi-apps/blob/main/apps/ng-app/vitest.config.mts
  • At root of the project, run pnpm run test

ahnpnl avatar May 30 '24 04:05 ahnpnl

It is 7.8.1, this is the repo https://github.com/ahnpnl/monorepo-multi-apps

To reproduce:

  • uncomment the workaround in https://github.com/ahnpnl/monorepo-multi-apps/blob/main/apps/ng-app/vitest.config.mts
  • At root of the project, run pnpm run test

Thanks. If you downlevel the target in the tsconfig, the workaround isn't needed.

// apps/ng-app/tsconfig.spec.json

/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "./out-tsc/spec",
    "target": "es2016",
    "types": ["node", "vitest/globals"]
  },
  "files": ["test/Framework/testSetup.ts"],
  "include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
}
// apps/ng-app/vitest.config.mts
import angular from '@analogjs/vite-plugin-angular';
import { defineConfig } from 'vite';

export default defineConfig(() => ({
    plugins: [
        angular(),
    ],
    test: {
        globals: true,
        environment: 'jsdom',
        setupFiles: ['test/Framework/testSetup.ts'],
        include: ['test/**/*.spec.ts'],
        passWithNoTests: true,
    },
}));

brandonroberts avatar May 30 '24 13:05 brandonroberts

It also works by just adding "files": ["test/Framework/testSetup.ts"], to the apps/ng-app/tsconfig.json

brandonroberts avatar May 30 '24 13:05 brandonroberts

Among these workarounds, do they have the same root cause about switching to ESM like being mentioned above?

ahnpnl avatar May 30 '24 14:05 ahnpnl

Among these workarounds, do they have the same root cause about switching to ESM like being mentioned above?

Yes, using ESM requires the file extensions and unless the angular libraries are transformed/inlined, it won't convert the import paths to include the extension.

brandonroberts avatar May 30 '24 15:05 brandonroberts

Reading about downside of specifying inline dep above impacts the performance, we have 2 other workarounds: downleveling target vs including setup file in tsconfig, which one would be easier to understand for devs in your opinion?

For me:

  • Downleveling target reminds me of this issue https://github.com/angular/components/issues/21632#issuecomment-764975917, possibly it has been resolved. This one is actually not too obvious to devs about what’s going on.

  • Including setup files in tsconfig seems to be more obvious, though I’m not sure how to explain about this workaround, not really obvious about being related to ESM.

Is there something analogjs can do to warn users about this?

ahnpnl avatar Jun 02 '24 12:06 ahnpnl

I think including the setup file in the tsconfig is the most straightforward path. We include a downleveled tsconfig with the application templates by default.

Past that, I think the performance hit should be an opt-in that could be a flag or explained in the docs.

brandonroberts avatar Jun 03 '24 17:06 brandonroberts