How to register cypress `code-coverage` plugin with cypress v10? - javascript

In cypress migration guide they mention that plugin files are no longer supported. They also mention that you need to use >=v3.10 of code-coverage plugin
I do have correct version installed, and I tried to update cypress.config.ts to:
import { defineConfig } from "cypress";
export default defineConfig({
video: false,
e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
require('#cypress/code-coverage/task')(on, config)
return config
},
},
});
but it doesn't work. What's the correct way? I believe I do have instrumenting working (I'm using #cypress/instrument-cra and see coverage object) but I don't see generated coverage files and I don't see a reset coverege step in tests

From your description the only step missing is the support file import.
// cypress/support/e2e.js
import '#cypress/code-coverage/support'
I also have a .babelrc with the following, but I believe you can do without it if just covering e2e tests.
{
"plugins": ["istanbul"]
}
Let me know if that's not it, I will give you step-by-step.

Related

Next.js (React) - Can't import local typescript file into config file

Situation
I would like to run some Database code (mongoDB(mongoose)) on server startup / during builds. Considering next js doesn't have any lifecycle hooks that you can hook into in an easy manner, I was trying to perform the database actions in my webpack (next.config.mjs) configuration. However I ran into some problems with importing local files.
Current setup
This is the code of my current next.config.mjs file. (PS. I have also tried the CommonJS way of requiring the needed files, but that also fails with error meessage "module not found".)
None of the lines that import a local typescript file appear to succeed and I have checked the paths multiple times. They always end up with the error message "ERR_MODULE_NOT_FOUND". Only if a node_module package is imported, it works as expected (the mongoose npm package).
Code
/** #type {import('next').NextConfig} */
const { EmployeesSchema } = await import("./mongodb_schemas/employee_schema");
import { EmployeesSchema } from "./mongodb_schemas/employee_schema";
import "./util/test"
import mongoose from "mongoose";
const nextConfig = {
experimental: {
externalDir: true,
},
reactStrictMode: true,
swcMinify: true,
images: {
domains: ["*", "**", "www.google.com"],
},
webpack: (
config,
{ buildId, dev, isServer, defaultLoaders, nextRuntime, webpack }
) => {
if (isServer) {
console.log(process.cwd());
}
return config;
},
};
export default nextConfig;
Anyone got a clue to why this might end up happening / have any possible solutions to the problem? I have also tried with a normal JavaScript file instead of a Typescript file, which also didn't work. I have found some similar asked questions on Stack Overflow but which were all left unanswered.
My guess for the reason why this occurs: during the build of the project, so when "npm run dev" is ran, the next.config.mjs is copied to a different location into the file structure, which means that the relative paths aren't correct anymore and thus the files can't be found.
PS. My apologize if the question is unclear / in an unusual format, it is my first post so not used to it.

How to use class when testing with Vue, Cypress and Cucumber?

I am trying to implement something simple: I want my e2e tests run with Cypress and cucumber.
I have an application created with Vue CLI 4.1.1. I added with NPM the package: cypress-cucumber-preprocessor (V1.19.0)
Edit:
After a lot of research and tests, I think I found where the problem comes from, but I don't know how to fix it yet:
The '#vue/cli-plugin-babel/preset' does not seem to be working with
.feature file...
My babel.config.js file is:
module.exports = {
presets: [
'#vue/cli-plugin-babel/preset'
]
}
Any idea how I can make cli-plugin-babel working with cucumber cypress?
Original message :
I have a Test.feature file, executing steps defined in test.step.js files.
Here is the content of my test.spec.js
import { When, Then } from 'cypress-cucumber-preprocessor/steps';
import { HomePage } from './pages/home.page';
When(/^I open the Home page$/, () => {
let homePage = new HomePage();
homePage.goTo();
});
Then(/^I see "([^"]*)" in the main heading$/, msg => {
cy.contains('h1', msg)
});
And the content of my PageObject home.page.js:
export class HomePage {
goTo() {
cy.visit("/");
}
}
When I run:
npm run test:e2e
I get the following error:
Oops...we found an error preparing this test file:
tests/e2e/features/Test.feature
The error was:
SyntaxError: 'import' and 'export' may appear only with 'sourceType: module'
This occurred while Cypress was compiling and bundling your test code. This is usually caused by:
- A missing file or dependency
- A syntax error in the file or one of its dependencies
Fix the error in your code and re-run your tests.
These errors does not occur when I use:
export function goToHomePage() {
cy.visit("/");
}
You can checkout my project on Github: https://github.com/truar/cloudcmr-v2 (branch master for the passing case, branch pageObject_pattern for the failing case).
I am assuming this is something related to ES6 and cypress... but I clearly don't know what is going on here. Besides, everything I find on the Internet talks about cypress cucumber and Typescript, which I don't use...
What am I missing?
I found the answer. See this PR for more details : https://github.com/cypress-io/cypress/issues/2945
Basically, there is an incompatibility between Babel 7 and Cypress 3. I had to change the babel.config.js file :
module.exports = process.env.CYPRESS_ENV
? {}
: {
presets: ["#vue/cli-plugin-babel/preset"]
};
It is just a workaround, not a real fix. We have to disable babel when running cypress.
Hope will help you !

react-testing-library why is toBeInTheDocument() not a function

Here is my code for a tooltip that toggles the CSS property display: block on MouseOver and on Mouse Out display: none.
it('should show and hide the message using onMouseOver and onMouseOut events respectively', () => {
const { queryByTestId, queryByText } = render(
<Tooltip id="test" message="test" />,
)
fireEvent.mouseOver(queryByTestId('tooltip'))
expect(queryByText('test')).toBeInTheDocument()
fireEvent.mouseOut(queryByTestId('tooltip'))
expect(queryByText('test')).not.toBeInTheDocument()
cleanup()
})
I keep getting the error TypeError: expect(...).toBeInTheDocument is not a function
Has anyone got any ideas why this is happening? My other tests to render and snapshot the component all work as expected. As do the queryByText and queryByTestId.
toBeInTheDocument is not part of RTL. You need to install jest-dom to enable it.
And then import it in your test files by:
import '#testing-library/jest-dom'
As mentioned by Giorgio, you need to install jest-dom. Here is what worked for me:
(I was using typescript)
npm i --save-dev #testing-library/jest-dom
Then add an import to your setupTests.ts
import '#testing-library/jest-dom/extend-expect';
Then in your jest.config.js you can load it via:
"setupFilesAfterEnv": [
"<rootDir>/src/setupTests.ts"
]
When you do npm i #testing-library/react make sure there is a setupTests.js file with the following statement in it
import '#testing-library/jest-dom/extend-expect';
Having tried all of the advice in this post and it still not working for me, I'd like to offer an alternative solution:
Install jest-dom:
npm i --save-dev #testing-library/jest-dom
Then create a setupTests.js file in the src directory (this bit is important! I had it in the root dir and this did not work...). In here, put:
import '#testing-library/jest-dom'
(or require(...) if that's your preference).
This worked for me :)
Some of the accepted answers were basically right but some may be slightly outdated:
Some references that are good for now:
https://github.com/testing-library/jest-dom
https://jestjs.io/docs/configuration
Here are the full things you need:
in the project's <rootDir> (aka where package.json and jest.config.js are), make sure you have a file called jest.config.js so that Jest can automatically pick it up for configuration. The file is in JS but is structured similarly to a package.json.
Make sure you input the following:
module.exports = {
testPathIgnorePatterns: ['<rootDir>/node_modules', '<rootDir>/dist'], // might want?
moduleNameMapper: {
'#components(.*)': '<rootDir>/src/components$1' // might want?
},
moduleDirectories: ['<rootDir>/node_modules', '<rootDir>/src'],
setupFilesAfterEnv: ['<rootDir>/src/jest-setup.ts'] // this is the KEY
// note it should be in the top level of the exported object.
};
Also, note that if you're using typescript you will need to make sure your jest-setup.ts file is compiled (so add it to src or to the list of items to compile in your tsconfig.json.
At the top of jest-setup.ts/js (or whatever you want to name this entrypoint) file: add import '#testing-library/jest-dom';.
You may also want to make sure it actually runs so put a console.log('hello, world!');. You also have the opportunity to add any global functions you'd like to have available in jest such as (global.fetch = jest.fn()).
Now you actually have to install #testing-library/jest-dom: npm i -D #testing-library/jest-dom in the console.
With those steps you should be ready to use jest-dom:
Without TS: you still need:
npm i -D #testing-library/jest-dom
Creating a jest.config.js and adding to it a minimum of: module.exports = { setupFilesAfterEnv: ['<rootDir>/[path-to-file]/jest-setup.js'] }.
Creating a [path-to-file]/jest-setup.js and adding to it: import '#testing-library/jest-dom';.
The jest-setup file is also a great place to configure tests like creating a special renderWithProvider( function or setting up global window functions.
None of the answers worked for me because I made the silly mistake of typing toBeInDocument() instead of toBeInTheDocument(). Maybe someone else did the same mistake :)
I had a hard time solving that problem so I believe it's important to note the followings if you're using CREATE REACT APP for your project:
You DO NOT need a jest.config.js file to solve this, so if you have that you can delete it.
You DO NOT need to change anything in package.json.
You HAVE TO name your jest setup file setupTests.js and have it under the src folder. It WILL NOT work if your setup file is called jest.setup.js or jest-setup.js.
install required packages
npm install --save-dev #testing-library/jest-dom eslint-plugin-jest-dom
create jest-setup.js in the root folder of your project and add
import '#testing-library/jest-dom'
in jest.config.js
setupFilesAfterEnv: ['<rootDir>/jest-setup.js']
TypeScript only, add the following to the tsconfig.json file. Also, change .js extension to .ts.
"include": ["./jest-setup.ts"]
toBeInTheDocument() and many similar functions are not part of the React-testing-library. It requires installing an additional package.
For anyone out there that like is trying to run tests in Typescript with jest and is still getting the same error even after installing #testing-library/jest-dom and following all the other answers: you probably need to install the type definitions for jest-dom (here) with:
npm i #types/testing-library__jest-dom
or
yarn add #types/testing-library__jest-dom
You need to install them as real dependencies and not as devDependency.
I was having this issue but for #testing-library/jasmine-dom rather than #testing-library/jest-dom.
The process of setup is just a tiny bit different with jasmine. You need to set up the environment in a before function in order for the matchers to be added. I think jest-dom will go ahead and add the matchers when you first import but Jasmine does not.
import { render, screen } from '#testing-library/react';
import MyComponent from './myComponent';
import JasmineDOM from '#testing-library/jasmine-dom';
describe("My Suite", function () {
beforeAll(() => {
jasmine.getEnv().addMatchers(JasmineDOM);
})
it('render my stuff', () => {
const { getByText } = render(<MyComponent />);
const ele = screen.getByText(/something/i);
expect(ele).toBeInTheDocument();
});
});
If you are using react-script then follow the below steps
Install #testing-library/jest-dom library if not done already using
npm i #testing-library/jest-dom.
Put import "#testing-library/jest-dom/extend-expect" in setUpTest.js
If you are using jest then import the library in jest.setup.js file.
the problem already was solved, but i will comment a little tip here, you don't need to create a single file called setup just for this, you just need to specify the module of the jest-dom on the setupFilesAfterEnv option in your jest configuration file.
Like this:
setupFilesAfterEnv: ['#testing-library/jest-dom/extend-expect'],
If you're using TS
You could also add a test.d.ts file to your test directory and use a triple slash directive:
///<reference types='#testing-library/jest-dom'>
Instead of doing:
expect(queryByText('test')).toBeInTheDocument()
you can find and test that it is in the document with just one line by using
let element = getByText('test');
The test will fail if the element isn't found with the getBy call.

IndexedDB testing with Jest & enzyme - ReferenceError: indexedDB is not defined

I'm looking for help with unit tests for my app, where I'm using indexedDB. Before I implemented indexedDB functionality, tests were correct. But now, for all of them I see one error:
ReferenceError: indexedDB is not defined
Can someone give me an advice how to get rid of that error? I was searching information, and trying different ways to mock window, or indexedDB, but with no result.
This issue is due to Dexie expecting window.indexedDB to be defined, this is not the case when running in a headless mode (using Jest) that does not have a true DOM or window scope.
Found a solution deep in the Dexie git issues which suggests:
const Dexie = require('dexie')
Dexie.dependencies.indexedDB = require('fake-indexeddb')
Dexie.dependencies.IDBKeyRange = require('fake-indexeddb/lib/FDBKeyRange')
We have also had success with:
import Dexie from 'dexie';
import indexedDB from 'fake-indexeddb';
Dexie.dependencies.indexedDB = indexedDB;
Link to the original issue:
https://github.com/dfahlander/Dexie.js/issues/495
Or according to the documentation, you can provide the indexedDB option like:
import Dexie from 'dexie';
import indexedDB from 'fake-indexeddb';
var db = new Dexie("MyDatabase", { indexedDB: indexedDB });
Link to documentation: http://dexie.org/docs/Dexie/Dexie
If You are using jest and enzyme for testing indexdb or you are using dexie which is a indexDB wrapper which is also used for implementing indexDB api you have to just add these three lines in you global-test.js file .
const Dexie = require('dexie');
Dexie.dependencies.indexedDB = require('fake-indexeddb');
Dexie.dependencies.IDBKeyRange = require('fake-indexeddb/lib/FDBKeyRange');
Now you have to provide this file to jest, show that it can use fake-indexddb instead of original indexDB.
setupFiles: ['<rootDir>/src/test/globals-test.ts']
when using jest, according to the fakeindexeddb docs,
install,
npm install --save-dev fake-indexeddb
or
yarn add --dev fake-indexeddb
then add below code to the jestconfig file
"jest": {
...
"setupFiles": [
"fake-indexeddb/auto"
]
}
I'm not using Dexie (but instead got here when Firebase was throwing an exception on import), the fix was simply adding require('fake-indexeddb/auto') into setupTests.ts for Jest to pick up.
For Angular 7.3+ with jest add this to your global-test.ts file:
const Dexie = require('dexie');
Dexie.dependencies.indexedDB = require('fake-indexeddb');
Dexie.dependencies.IDBKeyRange = require('fake-indexeddb/lib/FDBKeyRange');
then load the file in jest.config.js:
module.exports = {
preset: 'jest-preset-angular',
transformIgnorePatterns: ['node_modules'],
setupTestFrameworkScriptFile: '<rootDir>/src/setupJest.ts',
moduleNameMapper: {
'\\.(jpg|jpeg|png)$': '<rootDir>/__mocks__/image.js',
'#lib/(.*)': '<rootDir>/src/lib/$1'
},
globals: {
'ts-jest': {
tsConfigFile: 'src/tsconfig.spec.json'
},
__TRANSFORM_HTML__: true
},
setupFiles: ['<rootDir>/src/test/globals-test.ts']
};

Can I get the dependency tree before webpack starts to build?

Does webpack expose the dependency tree before the build is sealed? I have searched all through the compiler instance, but have found nothing about a dependency tree. It seems that there should be one hidden in that object somewhere, because webpack has to know what this tree is in order to later output the stats.json.
I've tried using the dependency-tree npm package, but it doesn't support some things I have in my webpack config, so the tree is incomplete.
TL;DR: Yes, you can access the dependency tree just before it's being sealed.
To do this, add the following code to your webpack.config.js:
class AccessDependenciesPlugin {
apply (compiler) {
compiler.hooks.compilation.tap('AccessDependenciesPlugin', compilation => {
compilation.hooks.finishModules.tap('AccessDependenciesPlugin', modules => {
/*
|---------------------------------------------------
| Here we go, `modules` is what we're looking for!
|---------------------------------------------------
*/
})
})
}
}
module.exports = {
// ...
plugins: [
new AccessDependenciesPlugin()
]
}
For more details, see the explanation below.
The hook we're looking for
We can access the pre-sealed dependency tree with the finishModules compilation hook.
How do we know?
Since the webpack hook docs are very minimal (to say the least), we had to read webpack source code to be sure it's what we're looking for:
The last thing the compiler does before sealing the dependency tree is "finishing" it.
This happens in Compiler.js, line 492
Finishing the dependency tree offers a hook on the compilation.
finishModules hook in the webpack docs
The hook is being called in Compilation.js, line 828
Code example
We create a plugin called AccessDependenciesPlugin:
// Basic webpack plugin structure
class AccessDependenciesPlugin {
apply (compiler) {
}
}
To use a compilation hook, we need to get access to the compilation object first. We do that with the compilation hook:
class AccessDependenciesPlugin {
apply (compiler) {
compiler.hooks.compilation.tap('AccessDependenciesPlugin', compilation => {
// We have access to the compilation now!
})
}
}
Now we tap the finishModules hook of the compilation:
class AccessDependenciesPlugin {
apply (compiler) {
compiler.hooks.compilation.tap('AccessDependenciesPlugin', compilation => {
compilation.hooks.finishModules.tap('AccessDependenciesPlugin', modules => {
// Here we go, `modules` is what we're looking for!
})
})
}
}
The modules parameter of that hook is an array of webpack modules with their dependencies and basically all other data available about them.
Last but not least, we need to add the plugin to our webpack configuration:
module.exports = {
plugins: [
new AccessDependenciesPlugin()
]
}
And we're done. 🎉
Hope this helps.
Bonus Content: webpack 3
Per request in the comments: Here's the version of the AccessDependenciesPlugin for the legacy plugin system of webpack 3.
class AccessDependenciesPlugin {
apply (compiler) {
compiler.plugin('compilation', compilation => {
compilation.plugin('finish-modules', modules => {
/*
|---------------------------------------------------
| Here we go, `modules` is what we're looking for!
|---------------------------------------------------
*/
})
})
}
}
Perhaps the line of code from this GitHub thread will help you out:
"Compile with webpack --profile --json > stats.json
(node.js API: { profile: true } and stats.toJson())
Go to http://webpack.github.io/analyse/#modules
Load your stats file (It's not uploaded, the analyse tools is a client only tool).
Wait a bit until the graph has been stabilized."
If that's not what you need, then I'd look into #Loilo 's answer - more complicated, but probably more what you need too.

Categories