Playwright & Vite - test block cannot find an element, although exists - reactjs

I'm running some e2e tests with playwright with vite frontend application.
This is my code:
import { test, expect } from '#playwright/test';
test.describe('Auth page #auth-page', () => {
test('auth page should have brand logo', async ({ page }) => {
await page.goto('http://localhost:8080/');
const isBrandLogoElementVisible = await page.locator("[data-test-id='auth-brand-logo']").isVisible();
expect(isBrandLogoElementVisible).toBe(true);
});
});
I run this script: playwright test -c ./playwright.config.ts
When I run the test the output is
basic/auth.spec.ts:4:6 › Auth page #auth-page › auth page should have brand logo ==============
Error: expect(received).toBe(expected) // Object.is equality
Expected: true
Received: false
7 | const isBrandLogoElementVisible = await page.locator("[data-test-id='auth-brand-logo']").isVisible();
8 |
> 9 | expect(isBrandLogoElementVisible).toBe(true);
| ^
10 | });
11 |
12 | test('auth page should have main header', async ({ page }) => {
But, when I run playwright test -c ./playwright.config.ts --debug it succeeds. I guesss it's because the test waits for my inputs on debug mode and then the element start rendering.
How can I change it to work?
I Expect Playwright to find the element as it exists

According to the docs, page.locator(...).isVisible() does not wait for the element to become visible. The recommended way to do this is to use expect(page.locator(...)).toBeVisible() which does wait for a specific, configurable amount of time.
await expect(page.locator("[data-test-id='auth-brand-logo']")).toBeVisible()

Related

Jest: await mssql.connect not working (timeout)

I want to test some functionality that should not rely on mocked sql query results but that should actually write to the database in a nextjs Typescript project.
Here's a minimal example of what is going wrong:
/* #/lib/db.ts */
import sql, { ConnectionPool } from "mssql";
const sqlConfig: sql.config = {
user: process.env.DB_USER,
password: process.env.DB_PWD,
database: process.env.DB_NAME,
server: process.env.DB_HOST!,
pool: {
max: parseInt(process.env.MAX_DB_CONNECTIONS || "10"),
min: 0,
idleTimeoutMillis: 30000
},
options: {
encrypt: true, // for azure
trustServerCertificate: true // change to true for local dev / self-signed certs
}
};
if (!global.db) {
global.db = { pool: null };
}
export async function connectToDatabase(): Promise<ConnectionPool> {
if (!global.db.pool) {
console.log("No pool available, creating new pool."); // this output shows up in the console
const pool = await sql.connect(sqlConfig);
global.db.pool = pool;
console.log("Created new pool."); // this is never reached
}
return global.db.pool!;
}
/* db.test.ts */
import { connectToDatabase } from "#/lib/db";
// as you can see I already tried a high timeout. The db connection never takes this long in development
jest.setTimeout(30000);
describe("Database", ()=>{
it("can connect", async()=>{
const pool = await connectToDatabase();
expect(1).toBe(1);
});
});
export {};
The test above fails because the connectToDatabase() Promise never fulfills (it doesn't reject either, which it should do when the credentials are wrong)
I have copied the .env.local file, which contains the DB credentials, and named it .env.test. I have also verified that the env data are in fact getting read correctly by outputting sqlConfig
The db.ts functions work perfectly in development.
Is there anything I overlooked why this shouldn't work in jest out of the box?
Ok I found it:
After taking a deeper look at the error log, I saw that I only read the lower half (ignore the different file name from the question):
ControllingTableLock
✕ works (30016 ms)
● ControllingTableLock › works
ReferenceError: setImmediate is not defined
at node_modules/mssql/lib/base/connection-pool.js:402:9
at Array.forEach (<anonymous>)
at node_modules/mssql/lib/base/connection-pool.js:401:26
● ControllingTableLock › works
thrown: "Exceeded timeout of 30000 ms for a test.
Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."
5 |
6 | describe("ControllingTableLock", ()=>{
> 7 | it("works", async()=>{
| ^
8 | const pool = await connectToDatabase();
9 | expect(1).toBe(1);
10 | return;
After some research I found out that
setImmediate is not defined
is an error that stems from jest using the jsdom environment instead of node.
The fix was very simple: I added
/*
* #jest-environment node
*/
above the imports in the test file.

Can't import #testing-library/jest-dom, expect.extend is not a function

I'm trying to add #testing-library/jest-dom to my project with no luck. It is installed by yarn into my dev dependencies and imported in setupTests.js with:
import '#testing-library/jest-dom';
The test fails with:
Invalid Chai property: toBeDisabled
40 | it('should be disabled', async () => {
41 | const button = screen.getByRole('button', { name: 'Create button' });
> 42 | expect(button).toBeDisabled();
| ^
43 | });
44 | });
Where am I going wrong?
Looks like you're using both Chai and Jest in the same test suite, both of which have an expect function. In this test you're expecting to use Jest but it's Chai that's getting called. Chai's expect does not have a toBeDisabled function property, thus the error.
Are you also importing Chai in that file? If so, remove that import. If you need both testing frameworks I'd recommend separating your tests into different files so that in one file you're only running tests with one framework.

Unit Tests Failing After Updating React Scripts from v.3.4.4 to v.4.0.3

I'm working on a new project for a client and have been asked to update create-react-app (react-scripts) from v.2.0.5 to v.4.0.3. I did that, and a bunch of unit tests failed. I went back through the project and isolated the breaking change to be the update from react-scripts 3.4.4 to 4.0.0.
Basically, the main error I'm seeing seems to apply to any tests running against async/await methods. Jest reports that the test times out but these tests are only timing out because they are failing. They all pass without issue on an earlier version of react-scripts (and by extension an earlier version of Jest I'd guess).
thrown: "Exceeded timeout of 5000 ms for a test.
Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."
The timeout seems to be relating to an issue with promises as it's preceeded by this error:
TypeError: Cannot read property 'then' of undefined
Along with a fairly indecipherable stack trace that lists a load of node modules.
Here's an example of the test that's failing:
test('dispatching fetchPublishedArticlesAuthors action causes an API GET and updates the store', async (done) => {
const options = { page: 0, size: 20, sort: 'createdBy.firstName,asc' };
store.dispatch(fetchPublishedArticlesAuthors(options));
const state = await stateChange(store);
expect(fetch).toHaveBeenCalledWith(
`https://content.onehub.test/articles/authors?page=0&size=20&sort=createdBy.firstName%2Casc`,
expect.objectContaining({ method: 'GET' }),
);
expect(getPublishedArticlesAuthors(state)).toMatchSnapshot();
done();
});
The await stateChange(store) references this method:
export function stateChange(store) {
return new Promise((resolve) => {
let currentState = store.getState();
store.subscribe(() => {
const newState = store.getState();
if (newState !== currentState) {
resolve(newState);
}
currentState = newState;
});
});
}
This method works without issue on another project running react-scripts 4.0.3 so I don't think that it's the issue per se but it is failing to return anything if I'm not mistaken.
Store is mocked as follows:
beforeEach(() => {
store = mockStore({ initialState, reducers, rootSaga: sagas });
fetch.mockClear();
});
Any tips on where to start? Confused as to why it fails on a more recent version but passes on an earlier one.
The solution was to set resetMocks to false. I tried doing this in Jest config but couldn't get it working so just added it directly to package.json:
"jest": {
"resetMocks": false
}
It wasn't obvious from the failing tests but having read the release notes you can see that the version of Jest used by Create React App changed from v24 to v26. In the process, resetMocks is set to true which was breaking the implementation in the test above, causing them all to time out.

Cypress: unit testing the pure React component is throwing error

I am writing unit tests using Cypress for my React JS web application. I can write functional tests using Cypress. But I also need to write the unit tests for my presentation components in my app. So I am using this Cypress wrapper for React, https://github.com/cypress-io/cypress/tree/master/npm/react. But, when I write the unit test for my component, it is throwing an error. Following is how I installed and wrote the unit test for my pure component.
First I installed the required libraries running the following command.
npm install --save-dev cypress #cypress/react #cypress/webpack-dev-server
Then I added the following line into the cypress/plugins/index.js
module.exports = (on, config) => {
require('#cypress/react/plugins/react-scripts')(on, config)
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
}
Then I created a test file called, no_result.spec.js with the following code.
import React from 'react';
import { mount } from '#cypress/react';
import NoResult from "../../../src/components/NoResult";
describe("NoResult Component", () => {
it ('should display message', () => {
mount(<NoResult message={"No data available."} />);
cy.contains('No data available').should('be.visible');
})
})
Then I opened the cypress and run that no_result.js test and I got the following error.
AssertionError
Timed out retrying after 4000ms: Expected to find element: #__cy_root, but never found it.
Because this error occurred during a before each hook we are skipping all of the remaining tests.
node_modules/#cypress/react/dist/cypress-react.esm-bundler.js:317:1
315 | return cy.then(function () {
316 | var selector = "#" + ROOT_ID;
> 317 | return cy.get(selector, { log: false }).then(function ($el) {
| ^
318 | var wasUnmounted = unmountComponentAtNode($el[0]);
319 | if (wasUnmounted && options.log) {
320 | cy.log('Unmounted component at', $el);
What is missing in my configuration and how can I fix it?

Cypress ReactJs tests Fail to find elements on Gitlab CI

I am testing some Reactjs UI with Cypress. When I run the tests locally using localhost:3000, the tests pass but when I push to Gitlab CI, the tests fail and the error is as shown below.
CypressError: Timed out retrying: Expected to find element: '.css-iyxtew', but never found it.
This is not due to server delay, I have tried adding wait time in vain. My guess is that the localhost server on Gitlab is not okay. Please help me with any solutions.
beforeEach(() => {
cy.visit('localhost:3000')
eslint-disable-next-line no-return-assign
cy.window().then(win => win.onbeforeunload = undefined)
})
it('Does not do much!', () => {
expect(true).to.equal(true)
})
it('.should() - make an assertion about the current page', () => {
cy.get('[data-cy=loader]').find('h6').should('be.visible')
cy.get('body').should('be.visible')
cy.get('.css-iyxtew').should('be.visible')
cy.get('[data-cy=index-page]').find('[data-cy=heading]').should('be.visible')
cy.get('.css-iyxtew').find('li').should('have.length', 2)
.find('.login').find('.css-17nm302-Button')
.should('have.css', 'background-color', 'rgba(0, 0, 0, 0)')
cy.get('.main-section').should('exist').find('.left-nav ').should('exist')
.find('.left-margin-pane').should('exist')
cy.get('.heading').find('.sub-heading')
.contains('Choose a phase below to browse our growing collection of adaptive implementation resources')
})
The solution I found out after some time is that I needed to add env variables to the CI environment too for the server to run.
this is gitlab-ci.yml
variables:
GET_PHASE_KITS: $GET_PHASE_KITS
GET_KIT: $GET_KIT
GET_PHASE_ASSETS: $GET_PHASE_ASSETS
GET_USER: $GET_USER
CREATE_USER: $CREATE_USER
ADD_USER_KIT: $ADD_USER_KIT
GET_USER_BY_ID: $GET_USER_BY_ID
GET_PHASES: $GET_PHASES
ADD_USER_ASSET: $ADD_USER_ASSET
GET_ASSET: $GET_ASSET
GET_PHASE: $GET_PHASE
EDIT_USER: $EDIT_USER

Resources