Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: error with stabilizationInterval argument #42

Merged
merged 1 commit into from
Nov 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 31 additions & 6 deletions src/actions/takeScreenshot.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,46 @@
import {LogEventType} from '../constants/internal';
import {testController} from '../testController';
import {E2edError} from '../utils/error';
import {getDurationWithUnits} from '../utils/getDurationWithUnits';
import {log} from '../utils/log';
import {getPromiseWithResolveAndReject} from '../utils/promise';

import type {Inner} from 'testcafe-without-typecheck';

type TakeScreenshot = ((path?: string) => Promise<void>) &
((options: Inner.TakeScreenshotOptions) => Promise<void>);
((options: Inner.TakeScreenshotOptions & Readonly<{timeout?: number}>) => Promise<void>);

/**
* Takes a screenshot of the tested page.
*/
export const takeScreenshot: TakeScreenshot = (pathOrOptions) => {
const options: Inner.TakeScreenshotOptions | undefined =
typeof pathOrOptions === 'string' ? {path: pathOrOptions} : pathOrOptions;
const {fullPage, path: pathToScreenshot} = options ?? {};
const options = typeof pathOrOptions === 'string' ? {path: pathOrOptions} : pathOrOptions;
const {fullPage, path: pathToScreenshot, timeout = 10_0000} = options ?? {};

log('Take a screenshot of the page', {fullPage, pathToScreenshot}, LogEventType.InternalAction);
const timeoutWithUnits = getDurationWithUnits(timeout);

return testController.takeScreenshot(pathOrOptions as never);
log(
'Take a screenshot of the page',
{fullPage, pathToScreenshot, timeoutWithUnits},
LogEventType.InternalAction,
);

const {promise, reject, setRejectTimeoutFunction} = getPromiseWithResolveAndReject(timeout);

setRejectTimeoutFunction(() => {
const error = new E2edError(
`takeScreenshot promise rejected after ${timeoutWithUnits} timeout`,
{fullPage, pathToScreenshot},
);

reject(error);
});

return Promise.race([
promise,
testController.takeScreenshot({
fullPage,
path: pathToScreenshot,
} as Inner.TakeScreenshotOptions),
]) as Promise<void>;
};
4 changes: 2 additions & 2 deletions src/actions/waitFor/waitForInterfaceStabilization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,9 @@ export const waitForInterfaceStabilization = async (
config;

// eslint-disable-next-line no-param-reassign
stabilizationInterval = stabilizationIntervalFromConfig;
stabilizationInterval ??= stabilizationIntervalFromConfig;
// eslint-disable-next-line no-param-reassign
timeout = timeoutFromConfig;
timeout ??= timeoutFromConfig;
}

if (!(stabilizationInterval > 0) || !(timeout > 0)) {
Expand Down
2 changes: 1 addition & 1 deletion src/utils/report/client/addDomContentLoadedHandler.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Adds DOMContentloaded handler for report page.
* Adds `DOMContentLoaded` handler for report page.
* If the page is already loaded, then call the handler immediately.
* This client function should not use scope variables (except global functions).
* @internal
Expand Down
2 changes: 1 addition & 1 deletion src/utils/report/client/chooseTestRun.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ declare const e2edTestRunDetailsContainer: HTMLElement;
declare const reportClientState: ReportClientState;

/**
* Choose TestRun (render chosen TestRun in right panel).
* Chooses TestRun (render chosen TestRun in right panel).
* This base client function should not use scope variables (except other base functions).
* @internal
*/
Expand Down
6 changes: 5 additions & 1 deletion src/utils/report/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,18 @@ export {clickOnStep} from './clickOnStep';
/** @internal */
export {clickOnTestRun} from './clickOnTestRun';
/** @internal */
export {domContentLoadedHandler} from './domContentLoadedHandler';
export {onDomContentLoad} from './onDomContentLoad';
/** @internal */
export {onFirstJsonReportDataLoad} from './onFirstJsonReportDataLoad';
/** @internal */
export {initialScript} from './initialScript';
/** @internal */
export {parseMarkdownLinks} from './parseMarkdownLinks';
/** @internal */
export {readJsonReportData} from './readJsonReportData';
/** @internal */
export {readPartOfJsonReportData} from './readPartOfJsonReportData';
/** @internal */
export {
renderDatesInterval,
renderDuration,
Expand Down
6 changes: 3 additions & 3 deletions src/utils/report/client/initialScript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import {addOnClickOnClass as clientAddOnClickOnClass} from './addOnClickOnClass'
import {clickOnRetry as clientClickOnRetry} from './clickOnRetry';
import {clickOnStep as clientClickOnStep} from './clickOnStep';
import {clickOnTestRun as clientClickOnTestRun} from './clickOnTestRun';
import {domContentLoadedHandler as clientDomContentLoadedHandler} from './domContentLoadedHandler';
import {onDomContentLoad as clientOnDomContentLoad} from './onDomContentLoad';
import {setReadJsonReportDataObservers as clientSetReadJsonReportDataObservers} from './setReadJsonReportDataObservers';

const addDomContentLoadedHandler = clientAddDomContentLoadedHandler;
const addOnClickOnClass = clientAddOnClickOnClass;
const clickOnRetry = clientClickOnRetry;
const clickOnStep = clientClickOnStep;
const clickOnTestRun = clientClickOnTestRun;
const domContentLoadedHandler = clientDomContentLoadedHandler;
const onDomContentLoad = clientOnDomContentLoad;
const setReadJsonReportDataObservers = clientSetReadJsonReportDataObservers;

/**
Expand All @@ -26,5 +26,5 @@ export const initialScript = (): void => {

setReadJsonReportDataObservers();

addDomContentLoadedHandler(domContentLoadedHandler);
addDomContentLoadedHandler(onDomContentLoad);
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ declare const reportClientState: ReportClientState;
const readJsonReportData = clientReadJsonReportData;

/**
* DOMContentloaded handler for report page.
* `DOMContentLoaded` handler for report page.
* This client function should not use scope variables (except global functions).
* @internal
*/
export function domContentLoadedHandler(): void {
export function onDomContentLoad(): void {
readJsonReportData(true);

for (const observer of reportClientState.readJsonReportDataObservers) {
Expand Down
36 changes: 36 additions & 0 deletions src/utils/report/client/onFirstJsonReportDataLoad.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import {clickOnTestRun as clientClickOnTestRun} from './clickOnTestRun';

const clickOnTestRun = clientClickOnTestRun;

declare const e2edTestRunDetailsContainer: HTMLElement;

/**
* Handler of loading first part of JSON report data for report page.
* This client function should not use scope variables (except global functions).
* @internal
*/
export function onFirstJsonReportDataLoad(): void {
if (window.location.hash !== '') {
return;
}

const buttonForFailedTestRun = document.querySelector(
'.retry:not([hidden]) .test-button_status_failed',
);

if (!buttonForFailedTestRun) {
return;
}

clickOnTestRun(buttonForFailedTestRun as HTMLElement);

const buttonOfOpenStep = document.querySelector('.step-expanded[aria-expanded="true"]');

if (buttonOfOpenStep) {
const {top} = buttonOfOpenStep.getBoundingClientRect();

setTimeout(() => {
e2edTestRunDetailsContainer.scrollTop = top;
}, 8);
}
}
36 changes: 18 additions & 18 deletions src/utils/report/client/readJsonReportData.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import type {FullTestRun, ReportClientState} from '../../../types/internal';
import {onFirstJsonReportDataLoad as clientOnFirstJsonReportDataLoad} from './onFirstJsonReportDataLoad';
import {readPartOfJsonReportData as clientReadPartOfJsonReportData} from './readPartOfJsonReportData';

import type {ReportClientState} from '../../../types/internal';

const onFirstJsonReportDataLoad = clientOnFirstJsonReportDataLoad;
const readPartOfJsonReportData = clientReadPartOfJsonReportData;

declare const reportClientState: ReportClientState;

Expand All @@ -9,7 +15,7 @@ declare const reportClientState: ReportClientState;
* This client function should not use scope variables (except global functions).
* @internal
*/
export function readJsonReportData(areAllScriptsLoaded?: boolean): void {
export function readJsonReportData(areAllScriptsLoaded = false): void {
const {lengthOfReadedJsonReportDataParts} = reportClientState;
const scripts = document.querySelectorAll('body > script.e2edJsonReportData');
const {length} = scripts;
Expand All @@ -18,26 +24,20 @@ export function readJsonReportData(areAllScriptsLoaded?: boolean): void {
return;
}

let hasParseErrorForLastScript = false;
let isLastReadSuccessful = true;

for (let i = lengthOfReadedJsonReportDataParts; i < length; i += 1) {
try {
const fullTestRuns = JSON.parse(scripts[i]?.textContent ?? '') as readonly FullTestRun[];
for (let index = lengthOfReadedJsonReportDataParts; index < length; index += 1) {
isLastReadSuccessful = readPartOfJsonReportData({
scriptToRead: scripts[index],
shouldLogError: index < length - 1 || areAllScriptsLoaded,
});
}

(reportClientState.fullTestRuns as FullTestRun[]).push(...fullTestRuns);
} catch (error) {
if (i < length - 1 || areAllScriptsLoaded) {
// eslint-disable-next-line no-console
console.error(`Cannot parse JSON report data from script number ${i}`);
}
const newLength = areAllScriptsLoaded || isLastReadSuccessful ? length : length - 1;

if (i === length - 1) {
hasParseErrorForLastScript = true;
}
}
if (reportClientState.lengthOfReadedJsonReportDataParts === 0 && newLength > 0) {
onFirstJsonReportDataLoad();
}

const newLength = !areAllScriptsLoaded && hasParseErrorForLastScript ? length - 1 : length;

reportClientState.lengthOfReadedJsonReportDataParts = newLength;
}
31 changes: 31 additions & 0 deletions src/utils/report/client/readPartOfJsonReportData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type {FullTestRun, ReportClientState} from '../../../types/internal';

declare const reportClientState: ReportClientState;

type Options = Readonly<{
scriptToRead: Element | undefined;
shouldLogError: boolean;
}>;

/**
* Reads part of JSON report data from script tag.
* Returns `true` if read successfully, and `false` if it has parse errors.
* This client function should not use scope variables (except global functions).
* @internal
*/
export function readPartOfJsonReportData({scriptToRead, shouldLogError}: Options): boolean {
try {
const fullTestRuns = JSON.parse(scriptToRead?.textContent ?? '') as readonly FullTestRun[];

(reportClientState.fullTestRuns as FullTestRun[]).push(...fullTestRuns);
} catch (error) {
if (shouldLogError) {
// eslint-disable-next-line no-console
console.error('Cannot parse JSON report data from script', error);
}

return false;
}

return true;
}
8 changes: 6 additions & 2 deletions src/utils/report/render/renderScriptFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ import {
clickOnStep,
clickOnTestRun,
createSafeHtmlWithoutSanitize,
domContentLoadedHandler,
onDomContentLoad,
onFirstJsonReportDataLoad,
parseMarkdownLinks,
readJsonReportData,
readPartOfJsonReportData,
renderDatesInterval,
renderDuration,
renderStep,
Expand Down Expand Up @@ -39,10 +41,12 @@ ${createSafeHtmlWithoutSanitize.toString()}
${clickOnRetry.toString()}
${clickOnStep.toString()}
${clickOnTestRun.toString()}
${domContentLoadedHandler.toString()}
${onDomContentLoad.toString()}
${onFirstJsonReportDataLoad.toString()}
${getDurationWithUnits.toString()}
${parseMarkdownLinks.toString()}
${readJsonReportData.toString()}
${readPartOfJsonReportData.toString()}
${renderDatesInterval.toString()}
${renderDuration.toString()}
${renderStep.toString()}
Expand Down
Loading