MOBILE-4616 behat: Fix flaky tests using relative dates

Allow a difference of one minute for the base time used to calculate
the timestamps of relative dates. This change prevents test errors caused
by delays between setting the data with relative dates and the rules that
match those dates.
main
Albert Gasset 2024-08-30 14:13:27 +02:00
parent 1815059e28
commit a837c9c551
3 changed files with 33 additions and 7 deletions

View File

@ -738,25 +738,36 @@ EOF;
* This function is similar to the arg_time_to_string transformation, but it allows the time to be a sub-text of the string. * This function is similar to the arg_time_to_string transformation, but it allows the time to be a sub-text of the string.
* *
* @param string $text * @param string $text
* @return string Transformed text. * @return string|string[] Transformed text.
*/ */
protected function transform_time_to_string(string $text): string { protected function transform_time_to_string(string $text): string|array {
if (!preg_match('/##(.*)##/', $text, $matches)) { if (!preg_match('/##(.*)##/', $text, $matches)) {
// No time found, return the original text. // No time found, return the original text.
return $text; return $text;
} }
$timepassed = explode('##', $matches[1]); $timepassed = explode('##', $matches[1]);
$basetime = time();
// If not a valid time string, then just return what was passed. // If not a valid time string, then just return what was passed.
if ((($timestamp = strtotime($timepassed[0])) === false)) { if ((($timestamp = strtotime($timepassed[0], $basetime)) === false)) {
return $text; return $text;
} }
$count = count($timepassed); $count = count($timepassed);
if ($count === 2) { if ($count === 2) {
// If timestamp with specified strftime format, then return formatted date string. // If timestamp with specified strftime format, then return formatted date string.
return str_replace($matches[0], userdate($timestamp, $timepassed[1]), $text); $result = [str_replace($matches[0], userdate($timestamp, $timepassed[1]), $text)];
// If it's a relative date, allow a difference of 1 minute for the base time used to calculate the timestampt.
if ($timestamp !== strtotime($timepassed[0], 0)) {
$timestamp = strtotime($timepassed[0], $basetime - 60);
$result[] = str_replace($matches[0], userdate($timestamp, $timepassed[1]), $text);
}
$result = array_unique($result);
return count($result) == 1 ? $result[0] : $result;
} else if ($count === 1) { } else if ($count === 1) {
return str_replace($matches[0], $timestamp, $text); return str_replace($matches[0], $timestamp, $text);
} else { } else {

View File

@ -124,9 +124,13 @@ export class TestingBehatDomUtilsService {
*/ */
protected findElementsBasedOnTextWithinWithExact( protected findElementsBasedOnTextWithinWithExact(
container: HTMLElement, container: HTMLElement,
text: string, text: string | string[],
options: TestingBehatFindOptions, options: TestingBehatFindOptions,
): ElementsWithExact[] { ): ElementsWithExact[] {
if (Array.isArray(text)) {
return text.map((text) => this.findElementsBasedOnTextWithinWithExact(container, text, options)).flat();
}
// Escape double quotes to prevent breaking the query selector. // Escape double quotes to prevent breaking the query selector.
const escapedText = text.replace(/"/g, '\\"'); const escapedText = text.replace(/"/g, '\\"');
const attributesSelector = `[aria-label*="${escapedText}"], a[title*="${escapedText}"], ` + const attributesSelector = `[aria-label*="${escapedText}"], a[title*="${escapedText}"], ` +
@ -266,7 +270,7 @@ export class TestingBehatDomUtilsService {
*/ */
protected findElementsBasedOnTextWithin( protected findElementsBasedOnTextWithin(
container: HTMLElement, container: HTMLElement,
text: string, text: string | string[],
options: TestingBehatFindOptions, options: TestingBehatFindOptions,
): HTMLElement[] { ): HTMLElement[] {
const elements = this.findElementsBasedOnTextWithinWithExact(container, text, options); const elements = this.findElementsBasedOnTextWithinWithExact(container, text, options);
@ -495,6 +499,17 @@ export class TestingBehatDomUtilsService {
locator: TestingBehatElementLocator, locator: TestingBehatElementLocator,
options: TestingBehatFindOptions = {}, options: TestingBehatFindOptions = {},
): HTMLElement | undefined { ): HTMLElement | undefined {
if (Array.isArray(locator.text)) {
for (const text of locator.text) {
const element = this.findElementBasedOnText({ ...locator, text });
if (element) {
return element;
}
}
return undefined;
}
// Remove extra spaces. // Remove extra spaces.
const treatedText = locator.text.trim().replace(/\s\s+/g, ' '); const treatedText = locator.text.trim().replace(/\s\s+/g, ' ');
if (treatedText !== locator.text) { if (treatedText !== locator.text) {

View File

@ -809,7 +809,7 @@ export type TestingBehatFindOptions = {
}; };
export type TestingBehatElementLocator = { export type TestingBehatElementLocator = {
text: string; text: string | string[];
within?: TestingBehatElementLocator; within?: TestingBehatElementLocator;
near?: TestingBehatElementLocator; near?: TestingBehatElementLocator;
selector?: string; selector?: string;