core(user-flow): add base flags option (#14459)
This commit is contained in:
Родитель
872d816e17
Коммит
88cc46b1bc
|
@ -99,6 +99,29 @@ describe('UserFlow', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
it('should merge flow flags with step flags', async () => {
|
||||
const flowFlags = {maxWaitForLoad: 500, maxWaitForFcp: 500};
|
||||
const flow = new UserFlow(mockPage.asPage(), {flags: flowFlags});
|
||||
await flow.navigate('https://example.com/1');
|
||||
|
||||
const flags = {maxWaitForLoad: 1000};
|
||||
await flow.navigate('https://example.com/2', flags);
|
||||
|
||||
expect(navigationModule.navigationGather).toHaveBeenCalledTimes(2);
|
||||
/** @type {any[][]} */
|
||||
const [[,, call1], [,, call2]] =
|
||||
navigationModule.navigationGather.mock.calls;
|
||||
|
||||
expect(call1.flags.maxWaitForLoad).toBe(500);
|
||||
expect(call1.flags.maxWaitForFcp).toBe(500);
|
||||
expect(call2.flags.maxWaitForLoad).toBe(1000);
|
||||
expect(call2.flags.maxWaitForFcp).toBe(500);
|
||||
|
||||
// Check that we didn't mutate the original objects.
|
||||
expect(flowFlags).toEqual({maxWaitForLoad: 500, maxWaitForFcp: 500});
|
||||
expect(flags).toEqual({maxWaitForLoad: 1000});
|
||||
});
|
||||
|
||||
it('should disable storage reset on subsequent navigations', async () => {
|
||||
const flow = new UserFlow(mockPage.asPage());
|
||||
await flow.navigate('https://example.com/1');
|
||||
|
@ -114,22 +137,30 @@ describe('UserFlow', () => {
|
|||
const flagsExplicit = {disableStorageReset: false};
|
||||
await flow.navigate('https://example.com/4', flagsExplicit);
|
||||
|
||||
// Try once when we explicitly set it on the flow.
|
||||
const flowFlagsExplicit = {disableStorageReset: false};
|
||||
const flow2 = new UserFlow(mockPage.asPage(), {flags: flowFlagsExplicit});
|
||||
await flow2.navigate('https://example.com/5');
|
||||
|
||||
// Check that we have the property set.
|
||||
expect(navigationModule.navigationGather).toHaveBeenCalledTimes(4);
|
||||
expect(navigationModule.navigationGather).toHaveBeenCalledTimes(5);
|
||||
/** @type {any[][]} */
|
||||
const [[,, call1], [,, call2], [,, call3], [,, call4]] =
|
||||
const [[,, call1], [,, call2], [,, call3], [,, call4], [,, call5]] =
|
||||
navigationModule.navigationGather.mock.calls;
|
||||
expect(call1).not.toHaveProperty('flags.disableStorageReset');
|
||||
expect(call2).toHaveProperty('flags.disableStorageReset');
|
||||
expect(call3).toHaveProperty('flags.disableStorageReset');
|
||||
expect(call4).toHaveProperty('flags.disableStorageReset');
|
||||
expect(call5).toHaveProperty('flags.disableStorageReset');
|
||||
expect(call2.flags.disableStorageReset).toBe(true);
|
||||
expect(call3.flags.disableStorageReset).toBe(true);
|
||||
expect(call4.flags.disableStorageReset).toBe(false);
|
||||
expect(call5.flags.disableStorageReset).toBe(false);
|
||||
|
||||
// Check that we didn't mutate the original objects.
|
||||
expect(flags).toEqual({maxWaitForLoad: 1000});
|
||||
expect(flagsExplicit).toEqual({disableStorageReset: false});
|
||||
expect(flowFlagsExplicit).toEqual({disableStorageReset: false});
|
||||
});
|
||||
|
||||
it('should disable about:blank jumps by default', async () => {
|
||||
|
@ -144,20 +175,29 @@ describe('UserFlow', () => {
|
|||
const flagsExplicit = {skipAboutBlank: false};
|
||||
await flow.navigate('https://example.com/3', flagsExplicit);
|
||||
|
||||
// Try once when we explicitly set it on the flow.
|
||||
const flowFlagsExplicit = {skipAboutBlank: false};
|
||||
const flow2 = new UserFlow(mockPage.asPage(), {flags: flowFlagsExplicit});
|
||||
await flow2.navigate('https://example.com/5');
|
||||
|
||||
// Check that we have the property set.
|
||||
expect(navigationModule.navigationGather).toHaveBeenCalledTimes(3);
|
||||
expect(navigationModule.navigationGather).toHaveBeenCalledTimes(4);
|
||||
/** @type {any[][]} */
|
||||
const [[,, call1], [,, call2], [,, call3]] = navigationModule.navigationGather.mock.calls;
|
||||
const [[,, call1], [,, call2], [,, call3], [,, call4]] =
|
||||
navigationModule.navigationGather.mock.calls;
|
||||
expect(call1).toHaveProperty('flags.skipAboutBlank');
|
||||
expect(call2).toHaveProperty('flags.skipAboutBlank');
|
||||
expect(call3).toHaveProperty('flags.skipAboutBlank');
|
||||
expect(call4).toHaveProperty('flags.skipAboutBlank');
|
||||
expect(call1.flags.skipAboutBlank).toBe(true);
|
||||
expect(call2.flags.skipAboutBlank).toBe(true);
|
||||
expect(call3.flags.skipAboutBlank).toBe(false);
|
||||
expect(call4.flags.skipAboutBlank).toBe(false);
|
||||
|
||||
// Check that we didn't mutate the original objects.
|
||||
expect(flags).toEqual({maxWaitForLoad: 1000});
|
||||
expect(flagsExplicit).toEqual({skipAboutBlank: false});
|
||||
expect(flowFlagsExplicit).toEqual({skipAboutBlank: false});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -235,6 +275,31 @@ describe('UserFlow', () => {
|
|||
{flags: undefined},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should merge flow flags with step flags', async () => {
|
||||
const flowFlags = {maxWaitForLoad: 500, maxWaitForFcp: 500};
|
||||
const flow = new UserFlow(mockPage.asPage(), {flags: flowFlags});
|
||||
await flow.startTimespan();
|
||||
await flow.endTimespan();
|
||||
|
||||
const flags = {maxWaitForLoad: 1000};
|
||||
await flow.startTimespan(flags);
|
||||
await flow.endTimespan();
|
||||
|
||||
expect(timespanModule.startTimespanGather).toHaveBeenCalledTimes(2);
|
||||
/** @type {any[][]} */
|
||||
const [[, call1], [, call2]] =
|
||||
timespanModule.startTimespanGather.mock.calls;
|
||||
|
||||
expect(call1.flags.maxWaitForLoad).toBe(500);
|
||||
expect(call1.flags.maxWaitForFcp).toBe(500);
|
||||
expect(call2.flags.maxWaitForLoad).toBe(1000);
|
||||
expect(call2.flags.maxWaitForFcp).toBe(500);
|
||||
|
||||
// Check that we didn't mutate the original objects.
|
||||
expect(flowFlags).toEqual({maxWaitForLoad: 500, maxWaitForFcp: 500});
|
||||
expect(flags).toEqual({maxWaitForLoad: 1000});
|
||||
});
|
||||
});
|
||||
|
||||
describe('.endTimespan()', () => {
|
||||
|
@ -263,6 +328,29 @@ describe('UserFlow', () => {
|
|||
{flags: undefined},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should merge flow flags with step flags', async () => {
|
||||
const flowFlags = {maxWaitForLoad: 500, maxWaitForFcp: 500};
|
||||
const flow = new UserFlow(mockPage.asPage(), {flags: flowFlags});
|
||||
await flow.snapshot();
|
||||
|
||||
const flags = {maxWaitForLoad: 1000};
|
||||
await flow.snapshot(flags);
|
||||
|
||||
expect(snapshotModule.snapshotGather).toHaveBeenCalledTimes(2);
|
||||
/** @type {any[][]} */
|
||||
const [[, call1], [, call2]] =
|
||||
snapshotModule.snapshotGather.mock.calls;
|
||||
|
||||
expect(call1.flags.maxWaitForLoad).toBe(500);
|
||||
expect(call1.flags.maxWaitForFcp).toBe(500);
|
||||
expect(call2.flags.maxWaitForLoad).toBe(1000);
|
||||
expect(call2.flags.maxWaitForFcp).toBe(500);
|
||||
|
||||
// Check that we didn't mutate the original objects.
|
||||
expect(flowFlags).toEqual({maxWaitForLoad: 500, maxWaitForFcp: 500});
|
||||
expect(flags).toEqual({maxWaitForLoad: 1000});
|
||||
});
|
||||
});
|
||||
|
||||
describe('.getFlowResult', () => {
|
||||
|
|
|
@ -11,6 +11,7 @@ import {navigationGather} from './gather/navigation-runner.js';
|
|||
import {Runner} from './runner.js';
|
||||
import {initializeConfig} from './config/config.js';
|
||||
import {getFormatted} from '../shared/localization/format.js';
|
||||
import {mergeConfigFragment, deepClone} from './config/config-helpers.js';
|
||||
import * as i18n from './lib/i18n/i18n.js';
|
||||
|
||||
/** @typedef {WeakMap<LH.UserFlow.GatherStep, LH.Gatherer.FRGatherResult['runnerOptions']>} GatherStepRunnerOptions */
|
||||
|
@ -67,30 +68,39 @@ class UserFlow {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {LH.UserFlow.StepFlags} [flags]
|
||||
* @param {LH.UserFlow.StepFlags|undefined} flags
|
||||
* @return {LH.UserFlow.StepFlags|undefined}
|
||||
*/
|
||||
_getNextFlags(flags) {
|
||||
const clonedFlowFlags = this._options?.flags && deepClone(this._options?.flags);
|
||||
if (!flags) return clonedFlowFlags;
|
||||
return mergeConfigFragment(clonedFlowFlags || {}, flags, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {LH.UserFlow.StepFlags|undefined} flags
|
||||
* @return {LH.UserFlow.StepFlags}
|
||||
*/
|
||||
_getNextNavigationFlags(flags) {
|
||||
const newStepFlags = {...flags};
|
||||
const nextFlags = this._getNextFlags(flags) || {};
|
||||
|
||||
if (newStepFlags.skipAboutBlank === undefined) {
|
||||
newStepFlags.skipAboutBlank = true;
|
||||
if (nextFlags.skipAboutBlank === undefined) {
|
||||
nextFlags.skipAboutBlank = true;
|
||||
}
|
||||
|
||||
// On repeat navigations, we want to disable storage reset by default (i.e. it's not a cold load).
|
||||
const isSubsequentNavigation = this._gatherSteps
|
||||
.some(step => step.artifacts.GatherContext.gatherMode === 'navigation');
|
||||
if (isSubsequentNavigation) {
|
||||
if (newStepFlags.disableStorageReset === undefined) {
|
||||
newStepFlags.disableStorageReset = true;
|
||||
if (nextFlags.disableStorageReset === undefined) {
|
||||
nextFlags.disableStorageReset = true;
|
||||
}
|
||||
}
|
||||
|
||||
return newStepFlags;
|
||||
return nextFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {LH.Gatherer.FRGatherResult} gatherResult
|
||||
* @param {LH.UserFlow.StepFlags} [flags]
|
||||
*/
|
||||
|
@ -111,13 +121,13 @@ class UserFlow {
|
|||
if (this.currentTimespan) throw new Error('Timespan already in progress');
|
||||
if (this.currentNavigation) throw new Error('Navigation already in progress');
|
||||
|
||||
const newStepFlags = this._getNextNavigationFlags(flags);
|
||||
const nextFlags = this._getNextNavigationFlags(flags);
|
||||
const gatherResult = await navigationGather(this._page, requestor, {
|
||||
config: this._options?.config,
|
||||
flags: newStepFlags,
|
||||
flags: nextFlags,
|
||||
});
|
||||
|
||||
this._addGatherStep(gatherResult, newStepFlags);
|
||||
this._addGatherStep(gatherResult, nextFlags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -179,11 +189,13 @@ class UserFlow {
|
|||
if (this.currentTimespan) throw new Error('Timespan already in progress');
|
||||
if (this.currentNavigation) throw new Error('Navigation already in progress');
|
||||
|
||||
const nextFlags = this._getNextFlags(flags);
|
||||
|
||||
const timespan = await startTimespanGather(this._page, {
|
||||
config: this._options?.config,
|
||||
flags: flags,
|
||||
flags: nextFlags,
|
||||
});
|
||||
this.currentTimespan = {timespan, flags};
|
||||
this.currentTimespan = {timespan, flags: nextFlags};
|
||||
}
|
||||
|
||||
async endTimespan() {
|
||||
|
@ -204,12 +216,14 @@ class UserFlow {
|
|||
if (this.currentTimespan) throw new Error('Timespan already in progress');
|
||||
if (this.currentNavigation) throw new Error('Navigation already in progress');
|
||||
|
||||
const nextFlags = this._getNextFlags(flags);
|
||||
|
||||
const gatherResult = await snapshotGather(this._page, {
|
||||
config: this._options?.config,
|
||||
flags: flags,
|
||||
flags: nextFlags,
|
||||
});
|
||||
|
||||
this._addGatherStep(gatherResult, flags);
|
||||
this._addGatherStep(gatherResult, nextFlags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,6 +9,8 @@ declare module UserFlow {
|
|||
export interface Options {
|
||||
/** Config to use for each flow step. */
|
||||
config?: LH.Config.Json;
|
||||
/** Base flags to use for each flow step. Step specific flags will override these flags. */
|
||||
flags?: LH.Flags;
|
||||
/** Display name for this user flow. */
|
||||
name?: string;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче