I adding unit tests to my Nuxt/Vue project and I'm using Jest for unit testing, I'm fetching data from the server-side using Apollo Client and I have a problem with importing .gql files inside test files.
here is the query file names.gql
{
names {
created_at
id
name
published_at
updated_at
}
}
I'm importing the query inside Vue component like this
import namesQuery from "#/queries/names";
Test file:
import { mount } from '#vue/test-utils';
import Names from '#/components/Names';
describe('Names', () => {
test('is a Vue instance', () => {
const wrapper = mount(Names)
expect(wrapper.vm).toBeTruthy()
})
})
When I run the tests, it says:
SyntaxError: Unexpected token '{'
Please advise.
According to the graphql-tag documentation you need to use jest-transform-graphql to handle imports.
Add this to your jest config file:
"transform": {
"\\.(gql|graphql)$": "jest-transform-graphql",
}
and then let the party begin π
Related
I am currently unable to use third-party plugins in my Nuxt 3 application. Here's what my code/setup looks like:
In my package.json I have the following dependency: "#braze/web-sdk": "^4.6.1"
In my plugins/ directory, I have a braze.client.js file
Within the braze.client.js file, I have the following:
import * as braze from '#braze/web-sdk'
export default defineNuxtPlugin(() => {
braze.initialize(apiKey, {
baseUrl: apiEndpoint
})
return {
provide: {
openSession
}
}
})
Within my nuxt.config.ts, I added the following (since my project has Vite, I followed Braze's documentation here: https://www.braze.com/docs/developer_guide/platform_integration_guides/web/initial_sdk_setup/#vite):
optimizeDeps: {
exclude: ['#braze/web-sdk']
}
Then within my <script> tags within the page/component, I have the following:
const { $openSession } = useNuxtApp()
onMounted(() => {
$openSession()
})
All the steps above continue to create a "500 navigator is not defined" error and I'm stumped with how I can resolve it.
I tried using beforeOnMount, not using as lifecycle hook, as well as placing $openSession() within an if statement:
if (process.client) {
}
Yet no matter what, it still renders the 500 error.
In the Stencil docs section on framework integration with Vue it states the following:
In order to use the custom element library within the Vue app, the
application must be modified to define the custom elements and to
inform the Vue compiler which elements to ignore during compilation.
According to the same page this can be achieved by modifying the config of your Vue instance like this:
Vue.config.ignoredElements = [/test-\w*/];
This relates to Vue 2 however. With Vue 3 (which Ionic Vue uses) you have to use isCustomElement as stated here.
Regretably, I canβt for the life of me get Vue and Stencil to play nice. I have tried setting the config like this:
app.config.compilerOptions.isCustomElement = tag => /gc-\w*/.test(tag)
This causes Vue throw the following warning in the console:
[Vue warn]: The `compilerOptions` config option is only respected when using a build of Vue.js that includes the runtime compiler (aka "full build"). Since you are using the runtime-only build, `compilerOptions` must be passed to `#vue/compiler-dom` in the build setup instead.
- For vue-loader: pass it via vue-loader's `compilerOptions` loader option.
- For vue-cli: see https://cli.vuejs.org/guide/webpack.html#modifying-options-of-a-loader
- For vite: pass it via #vitejs/plugin-vue options. See https://github.com/vitejs/vite/tree/main/p
However, I have no idea how to implement any of the above suggestions using Ionic Vue. I have been messing around with chainWebpack in config.vue.js but without success so far.
Any help would be greatly appreciated.
I'm not an expert in Vue but here's how I did it:
Add the following to your ./vue.config.js (or create it if it doesn't exist):
/**
* #type {import('#vue/cli-service').ProjectOptions}
*/
module.exports = {
// ignore Stencil web components
chainWebpack: config => {
config.module
.rule('vue')
.use('vue-loader')
.tap(options => {
options.compilerOptions = {
...options.compilerOptions,
isCustomElement: tag => tag.startsWith('test-')
}
return options
})
},
}
This will instruct Vue to ignore the test-* components. Source: https://v3.vuejs.org/guide/web-components.html#skipping-component-resolution
Next, load the components in ./src/main.ts.
Import the Stencil project:
import { applyPolyfills, defineCustomElements } from 'test-components/loader';
Then replace createApp(App).use(router).mount('#app') with:
const app = createApp(App).use(router);
// Bind the custom elements to the window object
applyPolyfills().then(() => {
defineCustomElements();
});
app.mount('#app')
Source: https://stenciljs.com/docs/vue
Also, if anyone is using vite2+, just edit the vite.config.js accordingly:
import { fileURLToPath, URL } from 'url'
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue({
template: {
compilerOptions: {
isCustomElement: tag => tag.startsWith('test-') // β
Here
}
}
}) ],
resolve: {
alias: {
'#': fileURLToPath(new URL('./src', import.meta.url))
}
}
})
I'm using storybook in vue.js.
I tried to import my component but it was failed, because Sass which imported in my component made error.
(component which is not importing Sass can imported and displayed.)
so, I check official description and created a .storybook/main.js file to add Sass support.
But i faced a unexpected error, "Require statement not part of import statement" in using storybook" at const path = require('path').
I couldn't find example of this error related storybook, so i'm confusing.
how to solve this error?
I just started using storybook, so i don't know which file info is needed to solve this.
if need other file info, I'll add it.
My main.js
const path = require('path');
// Export a function. Accept the base config as the only param.
module.exports = {
webpackFinal: async ( config ) => {
// Make whatever fine-grained changes you need
config.module.rules.push({
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
include: path.resolve(__dirname, '../'),
});
// Return the altered config
return config;
},
};
official description of using scss in storybook
I have followed the instructions on https://github.com/Justineo/vue-awesome
in my jest.config.js I add the following
transformIgnorePatterns: [
'/node_modules(?![\\\\/]vue-awesome[\\\\/])/'
]
my nuxt.config.js
build: {
transpile: [/^vue-awesome/] // enable font-awesome integration.
},
The icons work just fine when I'm running the dev box, but I get the following when I run yarn test:
[path/to/project]/node_modules/vue-awesome/icons/building.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import Icon from '../components/Icon.vue'
^^^^^^
SyntaxError: Cannot use import statement outside a module
explicitly, the issue seems to be something to do with how babel reads (or overlooks) the imports above the Icon component import. So, for example, given the building.js in the error log above, here is how the import looks in the vuejs file:
<script>
import 'vue-awesome/icons/building'
import Icon from 'vue-awesome/components/Icon'
export default {
componentes: {
'v-icon': Icon
}
...
}
</script>
It looks like I have to explicitly mock the component and its imports at the top of the file (below the imports)
the following works for my test.
import { shallowMount, createLocalVue } from '#vue/test-utils'
import Vuex from 'vuex'
import { AxiosSpy, MockNuxt } from 'jest-nuxt-helper'
import index from '#/pages/courses/index'
// MOCKS:
jest.mock('vue-awesome/icons/building', () => '')
jest.mock('vue-awesome/components/Icon', () => '<div></div>')
...
I'm developing in React Native and trying to set up jest testing by following the directions at https://airbnb.io/enzyme/docs/guides/react-native.html.
I think I've set everything up correctly. Here's my config:
//setup-tests.js
import "react-native";
import "jest-enzyme";
import Adapter from "enzyme-adapter-react-16";
import Enzyme from "enzyme";
// Set up DOM in node.js environment for Enzyme to mount to
const { JSDOM } = require("jsdom");
const jsdom = new JSDOM("<!doctype html><html><body></body></html>");
const { window } = jsdom;
function copyProps(src, target) {
Object.defineProperties(target, {
...Object.getOwnPropertyDescriptors(src),
...Object.getOwnPropertyDescriptors(target)
});
}
global.window = window;
global.document = window.document;
global.navigator = {
userAgent: "node.js"
};
copyProps(window, global);
// Set up Enzyme to mount to DOM, simulate events, and inspect the DOM in tests.
Enzyme.configure({ adapter: new Adapter() });
/* Ignore some expected warnings
* see: https://jestjs.io/docs/en/tutorial-react.html#snapshot-testing-with-mocks-enzyme-and-react-16
* see https://github.com/Root-App/react-native-mock-render/issues/6
*/
const originalConsoleError = console.error;
console.error = message => {
if (message.startsWith("Warning:")) {
return;
}
originalConsoleError(message);
};
// jest.config.js
module.exports = {
setupFilesAfterEnv: "<rootDir>setup-tests.js"
};
// Test.test.js
import React from "react";
import renderer from "react-test-renderer";
import { mount, ReactWrapper } from "enzyme";
import { Provider } from "react-redux";
import { Text } from "react-native";
import LoginView from '../js/LoginView'
You'll see the top of LoginView in a moment.
You'll notice that I haven't even written any tests in the test file, I'm just trying to get jest running to the point where it can evaluate a test.
Without the import LoginView, jest runs and "fails" because my test suite must contain at least one test. Sounds good.
Adding in the import LoginView, I get this error (which shows the import statements at the top of LoginView:
import Button from './buttons/Button';
^^^^^^
SyntaxError: Unexpected identifier
1 | import React, { Component } from "react";
> 2 | import { Input, Button, Image } from "react-native-elements";
| ^
3 | import { Text, View } from "react-native";
4 | import { connect } from "react-redux";
5 | import F8StyleSheet from "./F8StyleSheet";
at ScriptTransformer._transformAndBuildScript (node_modules/#jest/transform/build/ScriptTransformer.js:471:17)
at ScriptTransformer.transform (node_modules/#jest/transform/build/ScriptTransformer.js:513:25)
at Object.<anonymous> (js/LoginView.js:2:1)
So this doesn't make sense to me for a number of reasons.
LoginView renders fine in the actual app, with no "Unexpected identifier" crashes or warnings or anything
The lower arrows in the error on line 2 point to import, which of course shouldn't be unexpected.
Then there's the upper arrows that indicate a line from react-native-elements, so, I don't know about that.
Now, it does occur to me that the jest.config.js file did require me to use module.exports, and fails/crashes when I tried using export default { setupFiles } (or however I tried to do it, allowing VS Code to update it to ES6 syntax). So maybe that's why it's not liking import.
Even if that's the case, I don't know what the heck to do next.
Update
I put in the code suggested in Brian's answer, and I'm now getting all new errors. Even though the errors suggest fixes, it doesn't seem to help β- I've added the following to my package.json under jest. I'm not sure where Dimensions.js is anyway; plus, I would assume that all this setup I'm doing for React Native in particular would know how to identify the convention of having file.ios.js and file.android.js be equivalent to file.
Here's my "fix" following the instructions, which doesn't help at all.
"moduleFileExtensions": [
"js",
"json",
"jsx",
"ts",
"tsx",
"node",
"ios.js",
"android.js"
]
And here's the new errors.
FAIL tests/Test.test.js
β Test suite failed to run
Cannot find module './Platform' from 'Dimensions.js'
However, Jest was able to find:
'./Platform.android.js'
'./Platform.ios.js'
You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'json', 'jsx', 'ts', 'tsx', 'node'].
See https://jestjs.io/docs/en/configuration#modulefileextensions-array-string
However, Jest was able to find:
'../Utilities/Dimensions.js'
You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'json', 'jsx', 'ts', 'tsx', 'node'].
See https://jestjs.io/docs/en/configuration#modulefileextensions-array-string
However, Jest was able to find:
'buttons/Button.js'
You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'json', 'jsx', 'ts', 'tsx', 'node'].
See https://jestjs.io/docs/en/configuration#modulefileextensions-array-string
However, Jest was able to find:
'../js/LoginView.js'
You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'json', 'jsx', 'ts', 'tsx', 'node'].
See https://jestjs.io/docs/en/configuration#modulefileextensions-array-string
at Resolver.resolveModule (node_modules/jest-resolve/build/index.js:229:17)
at Object.require (node_modules/react-native/Libraries/Utilities/Dimensions.js:14:18)
react-native-elements contains ES6 code.
ES6 code needs to be compiled before it can be run by Jest.
By default Jest doesn't compile anything in node_modules, but react-native has a jest-preset that tells Jest to compile react-native and #react-native-community modules.
To include react-native-elements you will need to tell Jest to compile it as well by adding the following to your Jest config:
transformIgnorePatterns: [
'node_modules/(?!(jest-)?react-native|#react-native-community|react-native-elements)',
]