Skip to content

Commit

Permalink
FI-1476 feat: add actions for switching tabs
Browse files Browse the repository at this point in the history
  • Loading branch information
uid11 committed Nov 8, 2024
1 parent 90e2d77 commit 6f7587a
Show file tree
Hide file tree
Showing 14 changed files with 134 additions and 15 deletions.
3 changes: 3 additions & 0 deletions src/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,16 @@ export {setCookies} from './setCookies';
export {setFilesToUpload} from './setFilesToUpload';
export {setHeadersAndNavigateToUrl} from './setHeadersAndNavigateToUrl';
export {switchToIframe} from './switchToIframe';
export {switchToMainTab} from './switchToMainTab';
export {switchToMainWindow} from './switchToMainWindow';
export {switchToTab} from './switchToTab';
export {takeElementScreenshot} from './takeElementScreenshot';
export {takeScreenshot} from './takeScreenshot';
export {typeText} from './typeText';
export {
waitForAllRequestsComplete,
waitForInterfaceStabilization,
waitForNewTab,
waitForRequest,
waitForRequestToRoute,
waitForResponse,
Expand Down
12 changes: 12 additions & 0 deletions src/actions/switchToMainTab.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import {LogEventType} from '../constants/internal';
import {clearTab} from '../context/tab';
import {log} from '../utils/log';

/**
* Switches page context to the specified tab.
*/
export const switchToMainTab = (): void => {
log('Switch page context to the main tab', LogEventType.InternalAction);

clearTab();
};
14 changes: 14 additions & 0 deletions src/actions/switchToTab.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {LogEventType} from '../constants/internal';
import {setTab} from '../context/tab';
import {log} from '../utils/log';

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

/**
* Switches page context to the specified tab.
*/
export const switchToTab = (tab: Tab): void => {
log('Switch page context to the specified tab', LogEventType.InternalAction);

setTab(tab);
};
1 change: 1 addition & 0 deletions src/actions/waitFor/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export {waitForAllRequestsComplete} from './waitForAllRequestsComplete';
export {waitForInterfaceStabilization} from './waitForInterfaceStabilization';
export {waitForNewTab} from './waitForNewTab';
export {waitForRequest} from './waitForRequest';
export {waitForRequestToRoute} from './waitForRequestToRoute';
export {waitForResponse} from './waitForResponse';
Expand Down
22 changes: 22 additions & 0 deletions src/actions/waitFor/waitForNewTab.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {getPlaywrightPage} from '../../useContext';
import {getFullPackConfig} from '../../utils/config';

import type {InternalTab, Tab} from '../../types/internal';

type Options = Readonly<{
timeout?: number;
}>;

/**
* Waits for opening of new tab and returns this tab.
*/
export const waitForNewTab = async (options?: Options): Promise<Tab> => {
const context = getPlaywrightPage().context();
const timeout = options?.timeout ?? getFullPackConfig().pageRequestTimeout;

const page = await context.waitForEvent('page', {timeout});

const newTab: InternalTab = {page};

return newTab as Tab;
};
3 changes: 3 additions & 0 deletions src/context/frameContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@ const [get, set, clear] = useContext<FrameLocator>();

/**
* Get frame context.
* @internal
*/
export const getFrameContext: GetContext<FrameLocator> = get;

/**
* Set frame context.
* @internal
*/
export const setFrameContext: SetContext<FrameLocator> = set;

/**
* Clear frame context.
* @internal
*/
export const clearFrameContext: ClearContext = clear;
24 changes: 24 additions & 0 deletions src/context/tab.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// eslint-disable-next-line import/no-internal-modules
import {useContext} from '../useContext/useContext';

import type {ClearContext, GetContext, SetContext, Tab} from '../types/internal';

const [get, set, clear] = useContext<Tab>();

/**
* Get tab.
* @internal
*/
export const getTab: GetContext<Tab> = get;

/**
* Set tab.
* @internal
*/
export const setTab: SetContext<Tab> = set;

/**
* Clear tab.
* @internal
*/
export const clearTab: ClearContext = clear;
1 change: 1 addition & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export type {
export type {StackFrame} from './stackTrace';
export type {PackageInfo, StartInfo} from './startInfo';
export type {StringForLogs} from './string';
export type {Tab} from './tab';
export type {MergeTuples, TupleRest} from './tuples';
export type {
CloneWithoutUndefinedProperties,
Expand Down
4 changes: 4 additions & 0 deletions src/types/internal.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable max-lines */

export type {ClearContext, GetContext, GetWithDefaultValueContext, SetContext} from '../useContext';
export type {WithStabilizationInterval} from './actions';
export type {Brand, IsBrand} from './brand';
export type {Expect, IsEqual, IsReadonlyKey} from './checks';
Expand Down Expand Up @@ -120,6 +121,9 @@ export type {IsTestSkippedResult} from './skipTest';
export type {StackFrame} from './stackTrace';
export type {PackageInfo, StartInfo} from './startInfo';
export type {StringForLogs} from './string';
export type {Tab} from './tab';
/** @internal */
export type {InternalTab} from './tab';
export type {
LiteTestRun,
RejectTestRun,
Expand Down
14 changes: 14 additions & 0 deletions src/types/tab.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type {Page} from '@playwright/test';

import type {Brand} from './brand';

/**
* Internal presentation of `Tab`.
* @internal
*/
export type InternalTab = Partial<Tab> & Readonly<{page: Page}>;

/**
* Tab with page (in test).
*/
export type Tab = Brand<object, 'Tab'>;
2 changes: 1 addition & 1 deletion src/useContext/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export {getPlaywrightPage} from './page';
/** @internal */
export {pageStorage} from './page';
export {pageStorage} from './internalPage';
export type {
Clear as ClearContext,
Get as GetContext,
Expand Down
23 changes: 23 additions & 0 deletions src/useContext/internalPage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {AsyncLocalStorage} from 'node:async_hooks';

import {assertValueIsDefined} from '../utils/asserts';

import type {Page} from '@playwright/test';

/**
* Async local storage for `page` of current test.
* @internal
*/
export const pageStorage = new AsyncLocalStorage<Page>();

/**
* Internal get `page` object from context of current test.
* @internal
*/
export const getInternalPlaywrightPage = (): Page => {
const maybePage = pageStorage.getStore();

assertValueIsDefined(maybePage, 'maybePage is defined');

return maybePage;
};
18 changes: 8 additions & 10 deletions src/useContext/page.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
import {AsyncLocalStorage} from 'node:async_hooks';
import {getTab} from '../context/tab';

import {assertValueIsDefined} from '../utils/asserts';
import {getInternalPlaywrightPage} from './internalPage';

import type {Page} from '@playwright/test';

/**
* Async local storage for `page` of current test.
* @internal
*/
export const pageStorage = new AsyncLocalStorage<Page>();
import type {InternalTab} from '../types/internal';

/**
* Get `page` object from context of current test.
*/
export const getPlaywrightPage = (): Page => {
const maybePage = pageStorage.getStore();
const tab = getTab();

assertValueIsDefined(maybePage, 'maybePage is defined');
if (tab !== undefined) {
return (tab as InternalTab).page;
}

return maybePage;
return getInternalPlaywrightPage();
};
8 changes: 4 additions & 4 deletions src/useContext/useContext.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {getPlaywrightPage} from './page';
import {getInternalPlaywrightPage} from './internalPage';

import type {Page} from '@playwright/test';

Expand All @@ -25,7 +25,7 @@ export const useContext = (<Type>(defaultValue?: Type) => {
* Set value to test context.
*/
const set = (value: Type): void => {
const page: PageWithCtx = getPlaywrightPage();
const page: PageWithCtx = getInternalPlaywrightPage();

if (page.ctx === undefined) {
page.ctx = Object.create(null) as {};
Expand All @@ -50,7 +50,7 @@ export const useContext = (<Type>(defaultValue?: Type) => {
* Get value from test context.
*/
const get = (): Type | undefined => {
const page: PageWithCtx = getPlaywrightPage();
const page: PageWithCtx = getInternalPlaywrightPage();

if (page.ctx === undefined) {
page.ctx = Object.create(null) as {};
Expand All @@ -68,7 +68,7 @@ export const useContext = (<Type>(defaultValue?: Type) => {
* Get value from test context (or default value, if it is `undefined`).
*/
const getWithDefaultValue = (): Type => {
const page: PageWithCtx = getPlaywrightPage();
const page: PageWithCtx = getInternalPlaywrightPage();

if (page.ctx === undefined) {
page.ctx = Object.create(null) as {};
Expand Down

0 comments on commit 6f7587a

Please sign in to comment.