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

use components discovery with tests #58

Open
bob-lee opened this issue Jun 22, 2020 · 19 comments
Open

use components discovery with tests #58

bob-lee opened this issue Jun 22, 2020 · 19 comments
Labels
documentation Improvements or additions to documentation

Comments

@bob-lee
Copy link

bob-lee commented Jun 22, 2020

Describe the bug
Tried this library first time, dynamic imports are working great!
About auto scan feature, I found it saves many lines of codes but some tests are getting error:

[Vue warn]: Unknown custom element: <MyComponentB> - did you register the component correctly? ...

this is the case where I have MyComponentA and MyComponentB defined under /components folder and MyComponentA is using MyComponentB.

If I resurrect lines of codes that imports MyComponentB in MyComponentA, the test are working back ok but I wonder if I am missing something?

Additional context
[email protected]
@nuxt/[email protected]
@vue/[email protected]

@danielroe
Copy link
Member

I think it would be possible to create something that auto imports components at test level. Otherwise @nuxt/components only is usable at pages/layouts level (typically tested via e2e rather than unit) rather than within components.

@lambda0xff
Copy link

Yes, please implement auto imports at test level.

@Merott
Copy link

Merott commented Jul 3, 2020

As a workaround, I'm registering all components as global Vue components in my jest setup file:

[
  'app/components/MyComponentA.vue',
  'app/components/MyComponentB.vue',
  'ui-kit/components/ComponentA.vue',
  'ui-kit/components/ComponentB.vue',
  'ui-kit/components/ComponentC.vue',
].forEach((path) => {
  const name = path.match(/(\w*)\.vue$/)[1];
  const prefix = path.startsWith('ui-kit/') ? 'Ui' : '';
  Vue.component(`${prefix}${name}`, require(path).default);
});

I could automate this by pulling in the configuration/using globs, but I don't feel the need to make it more complicated than this, especially that I'm working on the project alone.

I've spent the past couple of days messing with my project configuration. Not sure if it's been worth all the trouble, but I hope this helps somebody!

@harrytran998
Copy link

harrytran998 commented Jul 19, 2020

As a workaround, I'm registering all components as global Vue components in my jest setup file:

[
  'app/components/MyComponentA.vue',
  'app/components/MyComponentB.vue',
  'ui-kit/components/ComponentA.vue',
  'ui-kit/components/ComponentB.vue',
  'ui-kit/components/ComponentC.vue',
].forEach((path) => {
  const name = path.match(/(\w*)\.vue$/)[1];
  const prefix = path.startsWith('ui-kit/') ? 'Ui' : '';
  Vue.component(`${prefix}${name}`, require(path).default);
});

I could automate this by pulling in the configuration/using globs, but I don't feel the need to make it more complicated than this, especially that I'm working on the project alone.

I've spent the past couple of days messing with my project configuration. Not sure if it's been worth all the trouble, but I hope this helps somebody!

@Merott Can you show your jest config file, please?

@Merott
Copy link

Merott commented Jul 19, 2020

@harrytran998 are you running into a particular issue? I don't have anything special for auto-scanning components in my jest config file:

// jest.config.js

const path = require('path');

module.exports = {
  moduleNameMapper: {
    '^@@?/(.*)$': '<rootDir>/$1',
    '^~~?/(.*)$': '<rootDir>/$1',
    '^vue$': 'vue/dist/vue.common.js',
  },
  moduleFileExtensions: ['ts', 'js', 'vue', 'json'],
  transform: {
    '^.+\\.ts$': 'ts-jest',
    '^.+\\.js$': 'babel-jest',
    '.*\\.(vue)$': 'vue-jest',
  },
  testPathIgnorePatterns: ['<rootDir>/(.vscode|node_modules|cypress)/'],
  setupFilesAfterEnv: [path.resolve(__dirname, 'jest.setup.ts')],
  snapshotSerializers: ['jest-serializer-vue'],
};

@bob-lee
Copy link
Author

bob-lee commented Jul 20, 2020

Thanks @Merott, I ended up doing:

// test/setupTest.js (jest setup)

const components = [
  '../components/MyComponentA.vue',
  '../components/MyComponentB.vue',
]
components.forEach((path) => {
  const name = path.match(/(\w*)\.vue$/)[1];
  Vue.component(`${name}`, require(path).default);
});

then could use auto scan feature freely. Happy for now.

@JBustin
Copy link

JBustin commented Jul 24, 2020

Thanks, I have tried this solution which works.
But the duration of my tests went from 20ms to 40ms. Normal, because we load all components before each test suites.
I have failed to improve it.
Code lines VS unit tests duration, I vote to keep unit test duration low. I hope for a good solution at the end.

@ryoju-ohata
Copy link

This solution is great, but it fails when some component is contained within auto-scanning components.

@ryoju-ohata
Copy link

The following code can automatically register components.

// jest.setup.js
import path from 'path'
import glob from 'glob'
import Vue from 'vue'

glob.sync(path.join(__dirname, './src/components/**/*.vue')).forEach(file => {
  const name = file.match(/(\w*)\.vue$/)[1]
  Vue.component(name, require(file).default)
})

global.Vue = Vue

@DragonWhisperer
Copy link

DragonWhisperer commented Nov 11, 2020

I hope someone will give it a clean solution.
Just register all the components in the folder is not enough because I use font-awasom-icon component inside the tested component, and I get error:

[Vue warn]: Unknown custom element: <font-awesome-icon>

I can use stubs:

const wrapper = mount(MyComponent, { stubs: ['font-awesome-icon'] })

But it's not clean.

@fbtwitter
Copy link

fbtwitter commented Jan 18, 2021

I don't know if it's truly not affecting to any configuration that running on test system..

But i found this configuration working to me, and these setting helps me prevents warning @bob-lee mentions.
https://dev.to/bawa_geek/how-to-setup-jest-testing-in-nuxt-js-project-5c84

By adding code in ./test/jest.setup.js

import Vue from 'vue'
import { config } from '@vue/test-utils'

Vue.config.silent = true

// Vue.config.ignoredElements = ['nuxt-link']
// Mock Nuxt components
config.stubs.nuxt = { template: '<div />' }
config.stubs['nuxt-link'] = { template: '<a><slot /></a>' }
config.stubs['no-ssr'] = { template: '<span><slot /></span>' }

and add these lines in config file ./jest.config.js
setupFilesAfterEnv: ['./test/jest.setup.js']

@brendan1212
Copy link

// test/setupTest.js (jest setup)

const components = [
  '../components/MyComponentA.vue',
  '../components/MyComponentB.vue',
]
components.forEach((path) => {
  const name = path.match(/(\w*)\.vue$/)[1];
  Vue.component(`${name}`, require(path).default);
});

@danielroe Is there something that could be implemented to include auto-scanning? This solution here works, but I can't get @ryoju-ohata 's solution working.

@pi0
Copy link
Member

pi0 commented Apr 6, 2021

There are actually two solutions to polyfill components in test environment:

  • Importing .nuxt/components/plugin.js (auto registers to global Vue)
  • Importing .nuxt/components/index.js and register manually

For both, we need a nuxt build step. (an upcoming nuxt dryrun would make it faster to only generate templates)

@pi0 pi0 changed the title Question: auto scan feature causes some tests failure use components discovery with tests Apr 6, 2021
@pi0 pi0 added the question Further information is requested label Apr 6, 2021
@pi0 pi0 closed this as completed Apr 6, 2021
@nmackey
Copy link

nmackey commented May 12, 2021

@pi0 So what is the official way to setup our tests to take advantage of auto import feature? Could there be some documentation added to Nuxt to demonstrate this?

Very difficult to take advantage of the auto import feature with our code if our tests don't work.

@pi0 pi0 added documentation Improvements or additions to documentation and removed question Further information is requested labels May 12, 2021
@pi0 pi0 reopened this May 12, 2021
@pi0
Copy link
Member

pi0 commented May 12, 2021

That's a nice idea @nmackey. I'm currently a little bit overwhelmed by tasks but PR definitely welcome for adding examples or docs. /cc @danielroe @ricardogobbosouza if you are interested to help on this.

@Strift
Copy link

Strift commented Aug 14, 2021

Hello, I wouldn't mind writing the documentation, but I'm unsure what are the steps to actually make it work. 🤔

@ambirdsall-gogo
Copy link

ambirdsall-gogo commented Aug 24, 2021

I got one definitely working solution, based on this comment:

There are actually two solutions to polyfill components in test environment:

Importing .nuxt/components/plugin.js (auto registers to global Vue)
Importing .nuxt/components/index.js and register manually
For both, we need a nuxt build step. (an upcoming nuxt dryrun would make it faster to only generate templates)

The steps I actually took:

  1. I added setupFiles: ["./.nuxt/components/plugin.js"], to my jest.config.js
  2. I changed my package.json["scripts"]["test"] from just jest to nuxt build && jest

This worked, but it's a significant slowdown for running tests. If I know I have an up-to-date-build, I can delete the nuxt build && (or create a new script without it, e.g. retest, in package.json), but I'm not aware of any automated solution to that.

This specific implementation is to my mind too slow and hacky to enshrine in the official documentation, honestly, even though the programatically-generated .nuxt/components/plugin.js is exactly what the test env needs 😞. I'd love any suggestions on how to improve it.

@vencho-mdp
Copy link

vencho-mdp commented Feb 15, 2022

Hi! So what would be the official way to solve this issue?
BTW, the setup I'm using right now that's completely automated (but not efficient) is to have this in my jest.config.js

module.exports = {
  preset: '@nuxt/test-utils',
  moduleFileExtensions: [
    'js',
    'json',
    'vue'
  ],
  transform: {
    '.*\\.(vue)$': '@vue/vue2-jest',
    '.*\\.(js)$': 'babel-jest'
  },
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/$1',
    '^~/(.*)$': '<rootDir>/$1',
    '^vue$': 'vue/dist/vue.common.js',
    '~/([a-zA-Z0-9/.\\-_]*)': '<rootDir>/$1',
    '/^~/(.*)$/': './$1',
    '^.+\\.(css)$': '<rootDir>/test/__mocks__/css.js'
  },
  testEnvironment: 'jsdom',
  setupFilesAfterEnv: ['./jest.setup.js']
}

And in jest.setup.js

const path = require('path')
const glob = require('glob')
const Vue = require('vue')

glob.sync(path.join(__dirname, './components/**/*.vue')).forEach((file) => {
  const name = file.match(/(\w*)\.vue$/)[1]
  Vue.component(name, require(file).default)
})

global.Vue = Vue

PS: And do you know if this will still be an issue with Nuxt 3 and Vitest?

@arishojaei
Copy link

I got one definitely working solution, based on this comment:

There are actually two solutions to polyfill components in test environment:
Importing .nuxt/components/plugin.js (auto registers to global Vue)
Importing .nuxt/components/index.js and register manually
For both, we need a nuxt build step. (an upcoming nuxt dryrun would make it faster to only generate templates)

The steps I actually took:

  1. I added setupFiles: ["./.nuxt/components/plugin.js"], to my jest.config.js
  2. I changed my package.json["scripts"]["test"] from just jest to nuxt build && jest

This worked, but it's a significant slowdown for running tests. If I know I have an up-to-date-build, I can delete the nuxt build && (or create a new script without it, e.g. retest, in package.json), but I'm not aware of any automated solution to that.

This specific implementation is to my mind too slow and hacky to enshrine in the official documentation, honestly, even though the programatically-generated .nuxt/components/plugin.js is exactly what the test env needs 😞. I'd love any suggestions on how to improve it.

@ambirdsall-gogo Just having setupFiles: ["./.nuxt/components/plugin.js"] in jest.config.js and run npm run jest is working. Is there any possible issue that I don't see?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests