Why can't react testing library access elements with Selenium? - reactjs

I have a selenium / jest project. I have installed react testing library and a few packages, but when I try to make valid assertions, I get an error. Code:
import { Vocal } from '../../Models/vocalModel';
import {screen} from '#testing-library/dom';
const vocal = new Vocal()
// Test Variables here
let validEmail = 'email#email.com'
let validPassword = 'password'
let invalidEmail = 'ThisEmailIsNotValid'
let invalidPassword = 'ThisPassWordIsNotValid'
describe("Login Test Suite", () => {
beforeAll(async ()=>{
await vocal.navigate();
});
afterAll( async ()=>{
await vocal.quit();
});
test('A user can login and logout', async () =>{
await vocal.userLogin(validEmail, validPassword);
await vocal.userLogout();
let getSignUpButtonText = await vocal.getText(vocal.signUpButtonLogin)
console.log(getSignUpButtonText)
expect(screen.getByText("Sign Up")).toBeVisible();
})
});
When I run this test, the browser runs and the test fails at the final assertion. I get the following error: "TestingLibraryElementError: Unable to find an element with the text: Sign Up. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.".
See photo:
Image of Error here
I've consoled 'getSignUpButtonText' which is defined as the text of that button on the page and it returns "Sign Up" so I know that text is on the page. Why can't screen.getByText('Sign Up') find it?
I have tried a few different packages but I cant seem to get away from this error.

Related

Browser not Defined error in Jest-Image-Snapshot Testing in React

I want to implement https://github.com/americanexpress/jest-image-snapshot#-api in my React application and tried writing one of the test cases but gives me an error saying the browser is not defined when trying to run a test using the command "npm test".I am using a library called Jest-Image-snapshot by americanexpress
import { toMatchImageSnapshot } from 'jest-image-snapshot';
expect.extend({ toMatchImageSnapshot });
jest.setTimeout(10000);
it('renders correctly', async () => {
const page = await browser.newPage();
await page.goto('https://localhost:3000');
const image = await page.screenshot();
expect(image).toMatchImageSnapshot();
});

How should I be using playwright's toHaveScreenshot() within a cucumber test in a React Typescript project?

I'm wanting to implement visual regression testing into a ReactJS app. I already have playwright setup called through cucumber for some other BDD UI tests and wanted to make use of the built in toHaveScreenShot method for visual regression. However, whenever I run the test it throws this error:
Error: toHaveScreenshot() must be called during the test
Here's the test script definition:
package.json excerpt
"test:e2e": "cucumber-js --require cucumber.conf.js --require features/step_definitions/**/*.js --format #cucumber/pretty-formatter",
Here's an example of the code:
cucumber.conf.js
const {
Before,
BeforeAll,
AfterAll,
After,
setDefaultTimeout,
} = require("#cucumber/cucumber");
const { chromium } = require("playwright");
// in milliseconds
setDefaultTimeout(60000);
// launch the browser
BeforeAll(async function () {
global.browser = await chromium.launch({
headless: false,
slowMo: 1000,
});
});
// close the browser
AfterAll(async function () {
await global.browser.close();
});
// Create a new browser context and page per scenario
Before(async function () {
global.context = await global.browser.newContext();
global.page = await global.context.newPage();
});
// Cleanup after each scenario
After(async function () {
await global.page.close();
await global.context.close();
});
homepage.feature
Feature: Homepage
A simple homepage
Scenario: Someone visiting the homepage
Given a new visitor to the site
When they load the homepage
Then they see the page
homepage.js
const { Given, When, Then } = require("#cucumber/cucumber");
const { expect } = require("#playwright/test");
Given("a new visitor to the site", function () {});
When("they load the homepage", async () => {
await page.goto("http://localhost:3000/");
});
Then("they see the page", async () => {
const locator = page.locator('img[alt="An image you expect to see"]');
await expect(locator).toBeVisible();
await expect(locator).toHaveScreenshot();
});
I think the error is complaining that I'm not writing my tests in the usual test() method, but I've not come across anything similar in searches and don't know how to give this context, assuming that is the problem, while using Cucumber.
Can anyone suggest a solution? I'm at a bit of a loss.

How to test signin component with jest and react testing library

I try to create an integrated test for a sign in component but I am facing some issues. Basically I need to check that after entered email and password credentials and clicked the submit button, it redirect me to a given page. I am using waitForComponentToBeRemoved to check the none presence of email or password field of the sign in component but I got an error:
Timed out in waitForElementToBeRemoved.
Please tell me if i dont have the right approach or if you need further informations.
Here is the test:
it( 'Login with real username and password', async () => {
beforeEach(() => {
fetch.dontMock()
})
act(() => {
ReactDOM.render(<App />, container);
})
// log /
console.log('history', window.location.pathname)
const email = process.env.TEST_EMAIL
const password = process.env.TEST_PASSWORD
const signInButton = screen.getByTestId('landing-signin')
fireEvent.click(signInButton)
await waitFor(async () => {
expect(signInButton).not.toBeInTheDocument()
// log /signin
console.log('history', window.location.pathname)
})
const emailField = screen.getByPlaceholderText('Email address')
const passwordField = screen.getByPlaceholderText('Your password')
const button = screen.getByTestId('submit-button')
expect(button).toBeInTheDocument()
expect(passwordField).toBeInTheDocument()
expect(emailField).toBeInTheDocument()
userEvent.type(emailField, email)
userEvent.type(passwordField, password)
await act(async () => {
fireEvent.click(button)
})
// Timed out in waitForElementToBeRemoved.
await waitForElementToBeRemoved(button).then(() => {
console.log('element has been removed')
})
// i need something to wait the response and the redirection to be done
})
ps: I dont want to mock data, it need to do real api call
How to you do the redirect in your source code? Are you using react-router? (In this case you could simply mock the redirect function and check if it has been called!?)
Please check out this related question: Testing redirect after submit with React Testing Library
Kent C Dodds is building and testing a simple sign-in component in this video (starting at timestamp 14:30):
https://www.youtube.com/watch?v=eg_TFYF_cKM&t=869s&ab_channel=Applitools%3AVisualAIPoweredTestAutomation

How to check if alert has been called in Jest testing React using Typescript?

I have a HTML select with some options which when I press a button get submitted to a server. Depending on the response an alert is shown.
The method looks like this:
const sendOrder = async (json : string) => {
const request = await fetchUrl("<irrelevant url>", "POST", json);
if(request.status === 200){
const order = await request.json();
alert(`Created Order #${order.data.id}`)
}else{
alert("Order failed")
}
}
Now I have mocked the server using msw and my test looks something like this:
it('should create an order', async () => {
render(<ArticleList />);
render(<ShoppingCart afterSubmit={()=> {}}/>)
const articlesList = getNullSafeElement('articles');
await waitFor(() => {
expect(articlesList.children.length).toBe(2);
})
const orderButton = getNullSafeElement('submitBtn');
const shoppingCart = document.querySelector('#cart') as HTMLSelectElement;
const addressInput = document.querySelector('#address') as HTMLInputElement;
addressInput.value = "testAddress"
expect(shoppingCart.options.length).toBe(0);
fireEvent.click(articlesList.children[0]);
expect(shoppingCart.children.length).toBe(1);
fireEvent.click(orderButton);
});
I know for sure that this test runs as expected and that the request is definetly beeing sent to the mocked server by fireEvent.click(orderButton).
However, if I now want to do something like this expect(global.alert).toHaveBeenCalledTimes(1), it does not work.
Now I know that I have to mock the call and I saw some posts on SO about this issue
Mock or asser whether window.alert has fired
Test alert in React Native
But neither global.alert = jest.fn(), nor jest.spyOn(global, 'alert') have worked out. Both result in 0 calls.
So my question is: How can I test if alert() has been called in my test?
(I am creating a frontend using create-react-app with the typescript template and testing with Jest)

enzyme testing react with context api

I'm trying to test a form. When the form is submitted it should set a state on error: true and then a div with an error information should appear. My test looks like this:
outer = shallow(<Search />);
it("should not submit a form and display an error if title or author is empty", () => {
const Children = outer.props().children({});
const wrapper = mount(Children);
const button = wrapper.find("form button");
button.simulate("submit", {
preventDefault() {
outer.setState({ error: true });
}
});
expect(wrapper.find("div.error")).toHaveLength(1);
});
Unfortunately it doesn't work. I am new to unit testing and I have no idea if I'm doing it correctly and how should I fix that.
I think I also should get somehow inputs values but don't know how.
This is the sample to set value to input elements:
it('Should capture firstname correctly onChange', function(){
const component = mount(<Form />);
const input = component.find('input').at(0);
input.instance().value = 'hello';
input.simulate('change');
expect(component.state().firstname).toEqual('hello');
})
But it may not work because of different other reasons, make sure you have initialized enzyme components in beforeAll(). Try to read enzyme's examples about this topic.

Resources