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

  1. 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

Most upvoted comments

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.