testcafe: execution stucks in chrome headless
What is your Scenario?
Trying to execute tests with concurrency 3 in chrome headless mode
What is the Current behavior?
first 3 tests marked as failed and tight after the execution stucks
What is the Expected behavior?
next tests have to be executed
What is your public website URL? (or attach your complete example)
https://staging.guidetoiceland.is
What is your TestCafe test code?
import { randomInt } from 'fp-ts/lib/Random';
import { ClientFunction, RequestHook, RequestMock, Selector } from 'testcafe';
import moment from 'moment';
fixture`A set of examples that illustrate how to use TestCafe API`
export async function removeTargetAttributes() {
return ClientFunction(() => {
const selector = document.querySelectorAll("div[data-testid='availability-cta'] a");
selector.forEach(el => el.removeAttribute("target"));
})();
}
async function waitForVisible(t, selector, timeout = 10000) {
await t
.expect(selector.with({ timeout: 10000 }).visible)
.ok(`element '${selector[Object.getOwnPropertySymbols(selector)[0]].fn}' is not visible`, {
timeout,
});
}
async function waitForExist(t, selector, timeout = 10000) {
await t
.expect(selector.exists)
.ok(`element '${selector[Object.getOwnPropertySymbols(selector)[0]].fn}' is not exist`, {
timeout,
});
}
async function waitForNotExist(t, selector, timeout = 10000) {
await t
.expect(selector.exists)
.notOk(`element '${selector[Object.getOwnPropertySymbols(selector)[0]].fn}' is exist`, {
timeout,
});
}
async function waitForEnabled(t, selector, timeout = 10000) {
await t
.expect(selector.hasAttribute("disabled"))
.notOk(`element '${selector[Object.getOwnPropertySymbols(selector)[0]].fn}' is not enabled`, {
timeout,
});
}
async function isVisible(selector, timeout = 10000) {
const result = await selector.with({ timeout }).visible;
return result;
}
async function beforeHook(t) {
await t.navigateTo("https://staging.guidetoiceland.is")
if (t.browser.alias.includes("headless")) {
await t.resizeWindow(1900, 1000);
} else {
await t.maximizeWindow();
}
await waitForVisible(t, Selector("[data-id='components_ui_Tabs_RoundedTabs_TabsWrapper']"));
await waitForExist(t, Selector(":is(#coverCarouselfrontCover,[data-id='components_ui_ImageCarousel_ImageGalleryCarousel_Wrapper'])"));
await waitForVisible(t, Selector("#contactUsButtonWrapper button"));
await waitForNotExist(t, Selector("#navBarCurrencyPicker").withText("• • •"));
}
export const productTypes = {
Trips: "Trips",
};
export function randomInteger(min, max) {
const rnd = randomInt(min, max)();
return rnd;
}
async function activateSearch(t, searchType) {
switch (searchType) {
case productTypes.Trips:
await t.click(Selector("[data-testid='trips-tab-label']"));
break;
default:
throw Error("Undefined type of Search");
}
}
async function search(t, searchType) {
if (!(await isVisible(Selector("#nextMonth"), 3000))) {
await t.click(Selector(`:is([data-testid='datePicker'],[data-testid='datePickerstarting-location-id']) svg:first-of-type`));
}
await t.click(Selector(".DayPicker-Month .DayPicker-Week div[class*='DayPicker-Day'][aria-disabled='false']").nth(20));
await t.click(Selector(".DayPicker-Month .DayPicker-Week div[class*='DayPicker-Day'][aria-disabled='false']").nth(25));
switch (searchType) {
case productTypes.Trips:
await t.typeText(Selector(":is([data-testid='trips-location-idAutocomplete'],[data-testid='starting-location-idAutocomplete']"), "Reykjavik")
await t.click(Selector("div[data-testid$='AutocompleteWrapper'] a").withText(/Reykjavik/));
await t.click(Selector('[data-testid="searchButton"]'));
await waitForVisible(t, Selector("[data-id='components_features_SearchPage_TourSearchAndCategoryContainer_Row']"));
await waitForVisible(t, Selector("[data-testid='imageWrapper']"));
await waitForNotExist(t, Selector("[data-id='components_ui_Search_LoadingBar_Wrapper']"));
await t.eval(() => {
const selector = document.querySelectorAll("a[target]");
selector.forEach(el => el.removeAttribute("target"));
});
await t.takeScreenshot();
const rnd = randomInteger(1, (await Selector("[data-testid='imageWrapper']").count) - 1);
await removeTargetAttributes();
await t.click(Selector("[data-testid='imageWrapper']").nth(rnd));
await waitForVisible(t, Selector("#pageContentContainer"));
await waitForVisible(t, Selector("[data-testid='continueBookButton'],#stickyFooter button")
.withText(/(Continue to book|Continue|Book Now|Add to Cart)/)
.filterVisible(),
30000);
await t.click(Selector("[data-testid='continueBookButton'],#stickyFooter button")
.withText(/(Continue to book|Continue|Book Now|Add to Cart)/)
.filterVisible());
await waitForEnabled(t, Selector("#paymentFormButton"), 30000);
break;
default:
throw Error("Undefined type of Search");
}
}
async function searchForProduct(t, product) {
await activateSearch(t, product);
await search(t, product);
}
test('GTI trip', async t => {
console.log(`${moment().format("HH:MM:ss")} GTI trip is stated`);
await beforeHook(t);
await searchForProduct(t, productTypes.Trips);
console.log(`${moment().format("HH:MM:ss")} GTI trip is finished`);
});
test('GTI trip2', async t => {
console.log(`${moment().format("HH:MM:ss")} GTI trip2 is stated`);
await beforeHook(t);
await searchForProduct(t, productTypes.Trips);
console.log(`${moment().format("HH:MM:ss")} GTI trip2 is finished`);
});
test('GTI trip3', async t => {
console.log(`${moment().format("HH:MM:ss")} GTI trip3 is stated`);
await beforeHook(t);
await searchForProduct(t, productTypes.Trips);
console.log(`${moment().format("HH:MM:ss")} GTI trip3 is finished`);
});
test('GTI trip4', async t => {
console.log(`${moment().format("HH:MM:ss")} GTI trip4 is stated`);
await beforeHook(t);
await searchForProduct(t, productTypes.Trips);
console.log(`${moment().format("HH:MM:ss")} GTI trip4 is finished`);
});
test('GTI trip5', async t => {
console.log(`${moment().format("HH:MM:ss")} GTI trip5 is stated`);
await beforeHook(t);
await searchForProduct(t, productTypes.Trips);
console.log(`${moment().format("HH:MM:ss")} GTI trip5 is finished`);
});
test('GTI trip6', async t => {
console.log(`${moment().format("HH:MM:ss")} GTI trip6 is stated`);
await beforeHook(t);
await searchForProduct(t, productTypes.Trips);
console.log(`${moment().format("HH:MM:ss")} GTI trip6 is finished`);
});
Your complete configuration file
const requestLogger = require("./tests/requestLogger");
module.exports = {
screenshots: {
path: "./artifacts/screenshots",
takeOnFails: true,
pathPattern: "${DATE}_${TIME}/${TEST}/${FILE_INDEX}_${QUARANTINE_ATTEMPT}.png",
thumbnails: false
},
disableMultipleWindows: true,
browsers: "chrome:headless",
concurrency: 3,
skipJsErrors: true,
pageLoadTimeout: 40000,
pageRequestTimeout: 45000,
selectorTimeout: 15000,
disableNativeAutomation: false,
hooks: {
request: requestLogger,
},
}
Your complete test report
No response
Screenshots
No response
Steps to Reproduce
- Run tests
TestCafe version
3.1.0-rc.1
Node.js version
v16.19.0
Command-line arguments
npx testcafe
Browser name(s) and version(s)
No response
Platform(s) and version(s)
MacOS 13.4.1
Other
No response
About this issue
- Original URL
- State: closed
- Created a year ago
- Reactions: 3
- Comments: 29 (6 by maintainers)
Commits related to this issue
- Native Automation: fix test execution stuck in headless (closes #7898) (#7939) — committed to rachaelparris/testcafe by AlexKamaev 10 months ago
We appreciate you taking the time to share the information about this issue. We replicated it, and it is currently in our internal queue. Please note that the research may take time. We’ll update this thread once we have news.
Hi, we also started seeing issues with Chrome just recently. changing to Firefox (firefox --headless) passess them just fine but we’d like to test different browsers specially Chrome.
@vasilyevi We are working on this. We are planning to release the 3.3.0 version next week if everything is ok.
Release v3.3.0-rc.1 addresses this.
I confirm that the issue is not related to the
disableMultipleWindows
options. I’m researching the issue. However, I do not have any results yet.Hi @Aleksey28,
I have the similar case with identical testcafe behavior. And it’s a huge blocker for me.