Skip to content

Commit

Permalink
FI-1011 fix: error in interface stabilization mechanism
Browse files Browse the repository at this point in the history
feat: add `getBrowserJsErrors` action
tests: add tests on `getBrowserJsErrors` action
feat: add `setPageElementsIgnoredOnInterfaceStabilization` action
tests: add tests on `setPageElementsIgnoredOnInterfaceStabilization` action
  • Loading branch information
uid11 committed Nov 11, 2023
1 parent 5a0a474 commit 52584c7
Show file tree
Hide file tree
Showing 28 changed files with 273 additions and 93 deletions.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -323,8 +323,6 @@ If `null`, the report will not be saved.
`skipTests: SkipTests`: this setting allows you to describe a set of skipped tests in a custom form.
You can define the `SkipTests` type and `skipTests` processing rules in the hook `autotests/hooks/isTestSkipped.ts`.

`stabilizationInterval: number`: default stabilization interval for `waitForInterfaceStabilization` action.

`takeFullPageScreenshotOnError: boolean`: if `true`, then takes a screenshot of the full page
(not just the viewport) at the time of the test error, for display in the HTML report.

Expand Down Expand Up @@ -352,6 +350,12 @@ returned by the `waitForAllRequestsComplete` function will be successfully resol
If the wait is longer than this timeout, then the promise
returned by the `waitForAllRequestsComplete` function will be rejected.

`waitForInterfaceStabilization.stabilizationInterval: number`: default stabilization interval for `waitForInterfaceStabilization` function.

`waitForInterfaceStabilization.timeout: number`: default timeout (in milliseconds) for `waitForInterfaceStabilization` function.
If the wait is longer than this timeout, then the promise
returned by the `waitForInterfaceStabilization` function will be rejected.

`waitForRequestTimeout: number`: default timeout (in milliseconds) for `waitForRequest` function.
If the wait is longer than this timeout, then the promise returned by the `waitForRequest` function will be rejected.

Expand Down
2 changes: 1 addition & 1 deletion autotests/configurator/skipTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type {SkipTests} from 'autotests/types/skipTests';
*/
export const skipTests: SkipTests = [
{
reason: 'Skip for testing skipping mechanism (with link [Google](https://google.com))',
reason: 'Skip for testing skipping mechanism (with link to [Google](https://google.com))',
testIds: ['4'],
unskipTaskUrl: 'https://tasktracker.com/3',
},
Expand Down
5 changes: 4 additions & 1 deletion autotests/packs/allTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ export const pack: Pack = {
reportFileName: 'report.html',
selectorTimeout: 10_000,
skipTests,
stabilizationInterval: 500,
takeFullPageScreenshotOnError: false,
takeViewportScreenshotOnError: true,
testFileGlobs: ['./autotests/tests/**/*.ts', '!**/*.skip.ts'],
Expand All @@ -58,6 +57,10 @@ export const pack: Pack = {
maxIntervalBetweenRequestsInMs: 500,
timeout: 30_000,
},
waitForInterfaceStabilization: {
stabilizationInterval: 500,
timeout: 30_000,
},
waitForRequestTimeout: 30_000,
waitForResponseTimeout: 30_000,
};
1 change: 1 addition & 0 deletions autotests/packs/local.example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ import type {Pack} from 'autotests/types/pack';
export const pack: Pack = {
...allTestsPack,
browserInitTimeout: 40_000,
dockerImage: 'e2edhub/e2ed',
};
2 changes: 1 addition & 1 deletion autotests/pageObjects/pages/Main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export class Main extends Page<CustomPageParams> {
/**
* Header selector.
*/
readonly headerSelector = mainPageLocator.header();
readonly header = mainPageLocator.header();

/**
* Search input.
Expand Down
57 changes: 57 additions & 0 deletions autotests/tests/e2edReportExample/browserData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/* eslint-disable no-console */

import {it} from 'autotests';
import {E2edReportExample} from 'autotests/pageObjects/pages';
import {createClientFunction, expect} from 'e2ed';
import {
getBrowserConsoleMessages,
getBrowserJsErrors,
navigateToPage,
setPageElementsIgnoredOnInterfaceStabilization,
waitForInterfaceStabilization,
} from 'e2ed/actions';

it('correctly read data from browser', {meta: {testId: '14'}}, async () => {
await navigateToPage(E2edReportExample);

await setPageElementsIgnoredOnInterfaceStabilization(['.retry']);

await waitForInterfaceStabilization(100);

await createClientFunction(() => {
console.error('error');
console.info('info');
console.log('log');
console.warn('warn');

const key = Symbol.for('e2ed:PageElementsIgnoredOnInterfaceStabilization');
const global = globalThis as {[key]?: readonly string[] | undefined};

console.log(global[key]);

setTimeout(() => {
throw new Error('foo');
}, 8);
setTimeout(() => {
throw new Error('bar');
}, 32);
})();

const {error, info, log, warn} = await getBrowserConsoleMessages();

await expect(
error[0] === 'error' && info[0] === 'info' && log[0] === 'log' && warn[0] === 'warn',
'`getBrowserConsoleMessages` read all of messages',
).eql(true);

await expect(log[1], '`setPageElementsIgnoredOnInterfaceStabilization` works correct').eql(
'.retry',
);

const jsErrors = await getBrowserJsErrors();

await expect(
jsErrors.length === 2 && jsErrors[0]?.message === 'foo' && jsErrors[1]?.message === 'bar',
'`getBrowserJsErrors` read JS errors',
).eql(true);
});
8 changes: 6 additions & 2 deletions autotests/tests/main/exists.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ it('exists', {meta: {testId: '1'}, testIdleTimeout: 35_000, testTimeout: 90_000}

const mainPage = await navigateToPage(Main, {language});

await expect(mainPage.pageParams, 'pageParams is correct after navigateToPage').eql({language});
await expect(mainPage.pageParams, '`pageParams` is correct after `navigateToPage`').eql({
language,
});

await expect(mainPage.searchString, 'search string is empty').eql('');

Expand Down Expand Up @@ -67,7 +69,9 @@ it('exists', {meta: {testId: '1'}, testIdleTimeout: 35_000, testTimeout: 90_000}
* Do not use the following pageParams and url (by getParamsFromUrl) checks in your code.
* These are e2ed internal checks. Use `assertPage` instead.
*/
await expect(searchPage.pageParams, 'pageParams is correct after assertPage').eql({searchQuery});
await expect(searchPage.pageParams, '`pageParams` is correct after `assertPage`').eql({
searchQuery,
});

const url = await getDocumentUrl();

Expand Down
8 changes: 3 additions & 5 deletions src/actions/getBrowserConsoleMessages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ import {LogEventType} from '../constants/internal';
import {testController} from '../testController';
import {log} from '../utils/log';

type ConsoleMessages = ReturnType<typeof testController.getBrowserConsoleMessages> extends Promise<
infer Type
>
? Type
: never;
import type {UnwrapPromise} from '../types/internal';

type ConsoleMessages = UnwrapPromise<ReturnType<typeof testController.getBrowserConsoleMessages>>;

/**
* Returns an object that contains messages output to the browser console.
Expand Down
29 changes: 29 additions & 0 deletions src/actions/getBrowserJsErrors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {LogEventType} from '../constants/internal';
import {createClientFunction} from '../createClientFunction';
import {log} from '../utils/log';

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

const clientGetBrowserJsErrors = createClientFunction(
(): readonly BrowserJsError[] => {
const key = Symbol.for('e2ed:JsErrors');
const global = window as {[key]?: BrowserJsError[]};
// eslint-disable-next-line no-multi-assign
const errors = (global[key] ??= []);
const copyOfErrors = [...errors];

errors.length = 0;

return copyOfErrors;
},
{name: 'getBrowserJsErrors'},
);

/**
* Get browser JS errors.
*/
export const getBrowserJsErrors = (): Promise<readonly BrowserJsError[]> => {
log('Get browser JS errors', LogEventType.InternalAction);

return clientGetBrowserJsErrors();
};
2 changes: 2 additions & 0 deletions src/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export {doubleClick} from './doubleClick';
export {drag} from './drag';
export {dragToElement} from './dragToElement';
export {getBrowserConsoleMessages} from './getBrowserConsoleMessages';
export {getBrowserJsErrors} from './getBrowserJsErrors';
export {getCookies} from './getCookies';
export {hover} from './hover';
export {mockApiRoute, unmockApiRoute} from './mock';
Expand All @@ -38,6 +39,7 @@ export {setCookies} from './setCookies';
export {setFilesToUpload} from './setFilesToUpload';
export {setHeadersAndNavigateToUrl} from './setHeadersAndNavigateToUrl';
export {setNativeDialogHandler} from './setNativeDialogHandler';
export {setPageElementsIgnoredOnInterfaceStabilization} from './setPageElementsIgnoredOnInterfaceStabilization';
export {switchToIframe} from './switchToIframe';
export {takeElementScreenshot} from './takeElementScreenshot';
export {takeScreenshot} from './takeScreenshot';
Expand Down
29 changes: 29 additions & 0 deletions src/actions/setPageElementsIgnoredOnInterfaceStabilization.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {LogEventType} from '../constants/internal';
import {createClientFunction} from '../createClientFunction';
import {log} from '../utils/log';

const clientSetPageElementsIgnoredOnInterfaceStabilization = createClientFunction(
(elementsCssSelectors: readonly string[]) => {
const key = Symbol.for('e2ed:PageElementsIgnoredOnInterfaceStabilization');
const global = globalThis as {[key]?: readonly string[] | undefined};

global[key] = elementsCssSelectors;
},
{name: 'setPageElementsIgnoredOnInterfaceStabilization'},
);

/**
* Set an array of elements (by their string CSS selectors) that will be ignored
* when determining the end of interface stabilization (these are usually animated elements).
*/
export const setPageElementsIgnoredOnInterfaceStabilization = (
elementsCssSelectors: readonly string[],
): Promise<void> => {
log(
'Set page element that will be ignored when determining the end of interface stabilization',
{elementsCssSelectors},
LogEventType.InternalAction,
);

return clientSetPageElementsIgnoredOnInterfaceStabilization(elementsCssSelectors);
};
Loading

0 comments on commit 52584c7

Please sign in to comment.