How do I mock this Vue injection? - vue.js

I have a Vue 3 component that, when mounted in tests, cause warnings:
console.warn node_modules/#vue/runtime-core/dist/runtime-core.cjs.js:40
[Vue warn]: injection "Symbol(VueToastification)" not found.
at <ModifyJob ref="VTU_COMPONENT" >
at <VTUROOT>
I assume it's this one complaining https://github.com/Maronato/vue-toastification/blob/master/composition/index.js#L30.
I have nearly 100 of these warnings, so it's kind of hard to read test-run output. I've tried to mock provide for this dependency, but I can't seem to succeed:
let provide = {}
provide[VueToastification] = VueToastification
provide['VueToastification'] = VueToastification
provide[Symbol(VueToastification)] = VueToastification
provide[Symbol('VueToastification')] = VueToastification
provide['Symbol(VueToastification)'] = VueToastification
let options = {
global: {
provide: provide,
}
}
mount(ModifyJob, options)
Is this some Vue2/Vue3 incompatibility or do I just not understand the docs at https://vue-test-utils.vuejs.org/v2/api/#global-provide ? Can someone help me get rid of these warnings, ideally by allowing me to inject a mock so I can test that toasts are made?

That error actually indicates that the plugin isn't installed in the test Vue instance. You could make VueToastification available to the component under test through the global.plugins mounting option:
import { shallowMount } from '#vue/test-utils'
import MyComponent from '#/components/MyComponent.vue'
import VueToastificationPlugin from 'vue-toastification'
it('initializes', () => {
shallowMount(MyComponent, {
global: {
plugins: [VueToastificationPlugin]
}
})
})
Alternatively, if you want to verify that toast() (from VueToastification's useToast()) is called, you could mock vue-toastification:
import { shallowMount } from '#vue/test-utils'
import MyComponent from '#/components/MyComponent.vue'
jest.mock('vue-toastification')
it('should call toast', () => {
const toast = jest.fn()
require('vue-toastification').useToast.mockReturnValueOnce(toast)
shallowMount(MyComponent).vm.showToast()
expect(toast).toHaveBeenCalled()
})

I solved setting a global list of plugins according to https://next.vue-test-utils.vuejs.org/api/#config-global:
// In a jest.setup.js file
import { config } from "#vue/test-utils";
import VueToastificationPlugin from "vue-toastification";
config.global.plugins = [VueToastificationPlugin];
// In your jest.config.js
module.exports = {
...
setupFilesAfterEnv: ["./jest.setup.js"],
};

Related

npm package for vuex module give error after dispatching

I’ve just made an npm package as a module for my vuex. after a long try finally, I could install it and mix it with my vuex. using this link
I console log my store and the action section contain my npm package luckily. but when I want to dispatch it gives me an error :(
use it in my app like :
this.$store.dispatch('orderiomApiPackageAuth/auth')
send me error:
[vuex] unknown action type: orderiomApiPackageAuth/auth
in my module.js:
import axios from "axios";
const state ={
restaurantInfo: {},
imprint: null
};
const mutations = {
setRestaurantInfo(state, restaurantInfo) {
state.restaurantInfo = restaurantInfo
},
setImprint(state, imprint) {
state.imprint = imprint
}
};
const actions = { //some action here }
export default {
namespaced: true,
state,
mutations,
actions
};
in my index.js for package:
import myModule from '/.module.js'
function install(Vue, options ={}) {
if (!options.store) console.log('Please provide a store!!')
options.store.registerModule('desiredName', myModule )
}
export default {
install
}
and use it in my main.js in the project:
import myPackage from 'myPackage'
import store from './store'
Vue.use(myPackage, { store })
I console.log(this.$store) and I realize that the action section contains my modules. but I have a problem with dispatch them.
I took a snapshot from my console share it here :
enter image description here
any help? :(

import and module.exports in Vuex module show Uncaught TypeError: Cannot assign to read only property 'exports' of object

i have a vuex module by Vue CLI
import { Sev } from "../api";
const modules = {
actions: {
getData() {
Sev();
}
}
};
module.exports = modules;
and i got an error in browser console
test.js?5df4:10 Uncaught TypeError: Cannot assign to read only property 'exports' of object '#<Object>'
at Module.eval (test.js?5df4:10)
at eval (test.js:12)
at Module../src/config/store_modules/test.js (app.js:1263)
then i change the code to
import { Sev } from "../api";
// const modules = {
export default {
actions: {
getData() {
Sev();
}
}
};
// module.exports = modules;
then work well. But i don't know what different. is it a bug ?
VueJS is browser code and use ES6 modules
import xxx from './path/to/xxx';
export xxx;
export default xxx;
while CommonJS is used by NodeJS and is completely different
const yyy = require('./path/to/yyy');
module.exports = { yyy };
exports.zzz = yyy;
You're writing Vue code so you must use ES6 modules and the import/export syntax, the module object doesn't behave as you'd expect in ES6

How to unit test Vue.js components that use nuxt-i18n

If I try to run the thing below (with yarn run jest), I get TypeError: _vm.$t is not a function, because SearchField is using a translation ("$t('search')").
import { mount } from "#vue/test-utils";
import SearchField from "#/components/ui/SearchField";
describe("SearchField", () => {
const wrapper = mount(SearchField);
it("renders correctly", () => {
expect(wrapper.element).toMatchSnapshot();
});
});
If I add the following three lines at the beginning, I get TypeError: Cannot read property '_t' of undefined instead.
import Vue from "vue";
import VueI18n from "vue-i18n";
Vue.use(VueI18n);
nuxt-i18n is an external library, not your own code, so the test good practices ask us to just mock the translation library and its needed functions ($t in this case).
The following code should solve your problem:
describe("SearchField", () => {
const wrapper = mount(SearchField);
it("renders correctly", () => {
mocks: {
$t: (msg) => msg
}
expect(wrapper.element).toMatchSnapshot();
});
});
More information on this approach can be found here.

Load aurelia-validation plugin during Jasmine unit tests - with webpack

I am using Aurelia with Webpack. Based on the ESNext Skeleton Webpack.
https://github.com/aurelia/skeleton-navigation/tree/master/skeleton-esnext-webpack
I have some plain JS model classes like:
import {ValidationRules} from 'aurelia-validation';
export class Address {
street = '';
}
ValidationRules
.ensure('street').required()
.on(Address);
As soon as I run my Jasmine tests (via Karma) and also with Wallaby, I get the error:
'Message: Did you forget to add ".plugin('aurelia-validation)" to your main.js?'
OK - I've not got a main.js when running tests, so how to load the plugin?
I've tried doing something like this - using aurelia-testing:
import {StageComponent} from 'aurelia-testing';
import {bootstrap} from 'aurelia-bootstrapper-webpack';
...
let component;
beforeEach(done => {
component = StageComponent
.withResources();
component.bootstrap(aurelia => {
aurelia.use.plugin('aurelia-validation')
});
done();
});
But that does not work with Webpack - open issue with aurelia-bootstrapper-webpack. Or maybe I am doing it wrongly.
Is there some other way to load the validation plugin during the tests? Or get aurelia-testing working with webpack?
At the moment, I am completely blocked from doing any unit tests if I have the validation plugin, or attempt to use aurelia-testing.
I have it working using the aurelia-cli and wallaby. You were very close which I guess makes it even more frustrating. The secret for me is that the validation plugin had to be bootstrapped first with the beforeAll method in the spec file and then the system under test created in the beforeEach method. The following spec file worked for me and resolved the Message: Did you forget to add ".plugin('aurelia-validation') to your main.js" error.
import { SourceSystemEntity } from '../../../src/entities/sourceSystemEntity';
import { StageComponent } from 'aurelia-testing';
import { bootstrap } from 'aurelia-bootstrapper';
describe('SourceSystem class', () => {
let component;
let sut: SourceSystemEntity;
beforeAll(done => {
component = StageComponent.withResources().inView('<div></div>').boundTo({});
component.configure = (aurelia: Aurelia) => {
aurelia.use
.standardConfiguration()
.plugin('aurelia-validation');
};
component.create(bootstrap).then(() => {
done();
});
});
afterAll(() => {
component.dispose();
});
beforeEach(() => {
sut = new SourceSystemEntity();
});
it('has Validation enabled', () => {
expect(sut.hasValidation()).toBeTruthy();
});
});
From what I've found the ValidationRules are run during the import process. Since they haven't been put into the actual class. What worked for me was to put the ValidationRules into the constructor or another method and call them after the bootstrap has run. Still hasn't fixed the functionality of Validation during tests but it does let you run the unit tests
import {ValidationRules} from 'aurelia-validation';
export class Address {
street = '';
constructor() {
ValidationRules
.ensure('street').required()
.on(Address);
}
}

Difference between import and require in jest

I am writing my first test for a react-native project using react-native-router-flux and react-redux
My code is something like
jest.autoMockOff();
jest.setMock('react-native', {
NativeModules: {}
});
jest.setMock('react-native-router-flux', {
Actions: {}
});
const mockStore = require('../../mock/Store');
const actions = require('../myActions');
...
// Some tests that test if the right actions are dispatched.
The above works, However when I use ES6 import instead of require I have a problem.
If I replace
const actions = require('../myActions');
with
import * as actions from "../myActions"
I get the below error.
Runtime Error
- Error: Cannot find module 'ReactNative' from 'react-native.js'
at Resolver.resolveModule (node_modules/jest-cli/node_modules/jest-resolve/src/index.js:117:17)
at Object.<anonymous> (node_modules/react-native/Libraries/react-native/react-native.js:175:25)
at Object.<anonymous> (node_modules/react-native-router-flux/src/Scene.js:10:18)
While I can work with this, I am curious to understand the reason for failure,
Also note that I am just not able to transpile react-native-router-flux with es2015 presets in .bablerc file and I think I will have to live with that limitation (of not being able to transpile react-native-router-flux).
myActions.js looks like
import {Actions} from 'react-native-router-flux';
export function searchRequest() {
return {
type: "search_request"
}
}
export function searchRequestFailure(error) {
return {
type: "search_request_failure",
error: error.toString()
}
}
export function searchRequestSuccess(payload) {
return {
type: "search_request_success",
payload: payload
}
}
export function search(nameOrAddress) {
return dispatch => {
dispatch(searchRequest())
return fetch("http://localhost:8080/search", {
method: "GET"
}).then((response) => {
return response.json()
}).then((responseData) => {
dispatch(searchRequestSuccess(responseData))
Actions.list() //react-native-router-flux dependency
}).catch(error => {
dispatch(searchRequestFailure(error))
})
}
}
Using react-native 0.26 and jest 12.1.1
That is not the correct ES6 conversion.
const actions = require('../myActions'); // requires the defaultMember of the exported module and
//ES6 (ES2015) equivalent is
import actions from '../myActions';
https://developer.mozilla.org/en/docs/web/javascript/reference/statements/import