Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Angular Vitest isn't working with Material Harnesses #1440

Closed
1 of 2 tasks
k3nsei opened this issue Nov 13, 2024 · 10 comments · Fixed by #1442
Closed
1 of 2 tasks

Angular Vitest isn't working with Material Harnesses #1440

k3nsei opened this issue Nov 13, 2024 · 10 comments · Fixed by #1442
Labels
bug Something isn't working

Comments

@k3nsei
Copy link

k3nsei commented Nov 13, 2024

Please provide the environment you discovered this bug in.

https://stackblitz.com/edit/angular-material-harnesses-vitest-j2urq?file=src%2Fapp%2Fautocomplete%2Fautocomplete.component.spec.ts

Which area/package is the issue in?

vitest-angular

Description

I want to migrate from Jest to Vitest in one of my angular projects. But the only thing that prevents me from doing so. Is that currently there are some issues with material harness support. Overlays don't show up in the DOM tree.

Please provide the exception or error you saw

npm run test

> test
> ng test


 RUN  v2.1.4 C:/dev/tmp/angular-material-harnesses-vitest-j2urq

stderr | src/app/autocomplete/autocomplete.component.spec.ts > GIVEN AutocompleteComponent > WHEN input value is empty > AND input is focused > THEN autocomplete should have 3 options
DOMException {}

stderr | src/app/autocomplete/autocomplete.component.spec.ts > GIVEN AutocompleteComponent > WHEN input value is not empty > AND input is focused > THEN autocomplete should have 2 options
DOMException {}

 ❯ |app| src/app/autocomplete/autocomplete.component.spec.ts (10) 306ms
   ❯ GIVEN AutocompleteComponent (10) 305ms
     ❯ WHEN input value is empty (5)
       ✓ THEN component should be initialized
       ✓ THEN component should match snapshot
       ❯ AND input is focused (3)
         ✓ THEN component should match snapshot
         ✓ THEN autocomplete should be opened
         × THEN autocomplete should have 3 options
     ❯ WHEN input value is not empty (5)
       ✓ THEN component should be initialized
       ✓ THEN component should match snapshot
       ❯ AND input is focused (3)
         ✓ THEN component should match snapshot
         ✓ THEN autocomplete should be opened
         × THEN autocomplete should have 2 options

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Failed Tests 2 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯

 FAIL  |app| src/app/autocomplete/autocomplete.component.spec.ts > GIVEN AutocompleteComponent > WHEN input value is empty > AND input is focused > THEN autocomplete should have 3 options
 FAIL  |app| src/app/autocomplete/autocomplete.component.spec.ts > GIVEN AutocompleteComponent > WHEN input value is not empty > AND input is focused > THEN autocomplete should have 2 options
SyntaxError: '' is not a valid selector
 ❯ emit node_modules/nwsapi/src/nwsapi.js:575:17
 ❯ Object._querySelectorAll [as select] node_modules/nwsapi/src/nwsapi.js:1512:9
 ❯ HTMLBodyElementImpl.querySelectorAll node_modules/jsdom/lib/jsdom/living/nodes/ParentNode-impl.js:78:26
 ❯ HTMLBodyElement.querySelectorAll node_modules/jsdom/lib/jsdom/living/generated/Element.js:1119:58
 ❯ Object.queryFn ../../src/cdk/testing/testbed/unit-test-element.ts:260:41
 ❯ TestbedHarnessEnvironment.<anonymous> ../../src/cdk/testing/testbed/testbed-harness-environment.ts:83:10
 ❯ fulfilled ../../src/cdk/testing/testbed/task-state-zone-interceptor.ts:46:12
 ❯ _ZoneDelegate.invoke node_modules/zone.js/bundles/zone.umd.js:416:32
 ❯ ZoneImpl.run node_modules/zone.js/bundles/zone.umd.js:147:47

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/2]⎯

 Test Files  1 failed (1)
      Tests  2 failed | 8 passed (10)
   Start at  13:25:22
   Duration  2.09s (transform 515ms, setup 452ms, collect 512ms, tests 306ms, environment 513ms, prepare 87ms)

Other information

Btw. When running tests in browser with npm run test:browser there are other issues that angular-vitest aren't able to inline CSS.

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

  • Yes
  • No
@k3nsei k3nsei added the bug Something isn't working label Nov 13, 2024
@brandonroberts
Copy link
Member

Thanks for the reproduction @k3nsei. The fix is to add @angular/material to the test.server.deps.inline array. Angular packages need to be transformed, and downleveled from async/await if present. The @angular/material package was not picked up

/// <reference types='vitest' />
import path from 'node:path';
import process from 'node:process';
import ngVite from '@analogjs/vite-plugin-angular';
import viteTsConfigPaths from 'vite-tsconfig-paths';
import { defineConfig } from 'vitest/config';

const config = defineConfig({
  root: import.meta.dirname,
  cacheDir: path.resolve(import.meta.dirname, 'node_modules/.vite'),
  plugins: [
    ngVite(),
    viteTsConfigPaths({
      projects: [path.resolve(import.meta.dirname, 'tsconfig.spec.json')],
    }),
  ],
  define: {
    'import.meta.vitest': true,
  },
  test: {
    name: 'app',
    globals: true,
    watch: false,
    pool: 'threads',
    environment: 'jsdom',
    include: ['src/**/*.{test,spec}.?(c|m)[jt]s'],
    setupFiles: ['src/test-setup.ts'],
    reporters: [
      'default',
      [
        'junit',
        {
          addFileAttribute: false,
          includeConsoleOutput: false,
          outputFile: path.resolve(import.meta.dirname, 'coverage/junit.xml'),
        },
      ],
    ],
    coverage: {
      provider: 'v8',
      reporter: ['clover', 'json', 'text'],
      reportsDirectory: path.resolve(import.meta.dirname, 'coverage'),
    },
    server: {
      deps: {
        inline: ['@angular/material'] // <-- transform additional Angular dependencies
      }
    }
  },
});

if (process.env['USE_BROWSER'] === 'true') {
  const testConfig = config.test!;

  delete testConfig.environment;

  Object.assign(testConfig, {
    watch: true,
    browser: {
      provider: 'playwright',
      name: 'chromium',
      enabled: true,
      headless: false,
    }
  });
}

export default config;

This fixes the running the tests in Node. We can add this to our internal list when running tests.

Still looking into the browser tests

@k3nsei
Copy link
Author

k3nsei commented Nov 14, 2024

@brandonroberts could you detect if CDK or Material is in package.json and add it dynamically?

@brandonroberts
Copy link
Member

@brandonroberts could you detect if CDK or Material is in package.json and add it dynamically?

We could, but it doesn't have to be dynamic. It has no impact if you don't use material even if we include it

@brandonroberts
Copy link
Member

@k3nsei adding this to the vite.config.ts fixes the browser tests

  optimizeDeps: {
    include: ['tslib', '@angular/cdk/testing/testbed'],
    exclude: ['@angular/cdk/testing']
  },

@k3nsei
Copy link
Author

k3nsei commented Nov 14, 2024

@brandonroberts could you detect if CDK or Material is in package.json and add it dynamically?

We could, but it doesn't have to be dynamic. It has no impact if you don't use material even if we include it

From my point of view it would be nice if things just worked like with jest-preset-angular. But if not add it as default it could at least be added to the docs. Many projects use angular material so it could be common problem.

Anyway thanks for your help and all your work.

@brandonroberts
Copy link
Member

I agree, the goal is to have most common use cases covered out of the box. I didn't think anything special was needed for angular material. We'll ensure Angular Material/CDK is supported without manual configuration

@k3nsei
Copy link
Author

k3nsei commented Nov 15, 2024

@brandonroberts now tests in monorepo stopped working as paths are incorrect. They are not points to node_modules. In this case node_modules/@ngx-formly/core and node_modules/@ngx-formly/material should be used. Also it reporting paths from source maps.

PS. I do not think this error saying what is really happening. My intuition telling me that basically Formly cannot access it dependency which is @angular/material.

TypeError: Cannot read properties of undefined (reading '_observers')
    at observe (file:///C:/dev/admin-tool/src/AdminTool.Admin/ClientApp/src/core/src/lib/utils.ts:265:10)
    at FormFieldSelectComponent2.set select [as select] (file:///C:/dev/admin-tool/src/AdminTool.Admin/ClientApp/src/ui/material/select/src/select.type.ts:71:5)
    at FormlyFieldSelect_Query (ng:///FormlyFieldSelect/ɵcmp.js:119:76)
    at definition.viewQuery (file:///C:/dev/admin-tool/src/packages/core/src/render3/features/inherit_definition_feature.ts:201:7)
    at executeViewQueryFn (file:///C:/dev/admin-tool/src/packages/core/src/render3/instructions/shared.ts:1923:5)
    at renderView (file:///C:/dev/admin-tool/src/packages/core/src/render3/instructions/render.ts:125:7)
    at renderComponent (file:///C:/dev/admin-tool/src/packages/core/src/render3/instructions/render.ts:41:3)

@brandonroberts
Copy link
Member

@k3nsei this issue here with the older @ngx-formly packages. Add this to the vitest config

  ssr: {
    noExternal: [/fesm2015/]
  },

@k3nsei
Copy link
Author

k3nsei commented Nov 15, 2024

@brandonroberts Is this related to latest changes? As with previous version it was working.

Anyway it helped. Thanks again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
2 participants