blob: 15cfe7b5bd8f102d222b05ec4303863d35b1303d [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import * as Platform from '../../../../core/platform/platform.js';
import * as SDK from '../../../../core/sdk/sdk.js';
import * as Protocol from '../../../../generated/protocol.js';
import {describeWithEnvironment} from '../../../../testing/EnvironmentHelpers.js';
import {createViewFunctionStub, type ViewFunctionStub} from '../../../../testing/ViewFunctionHelpers.js';
import * as PreloadingComponents from './components.js';
const {urlString} = Platform.DevToolsPath;
async function setupWidget(): Promise<{
widget: PreloadingComponents.PreloadingGrid.PreloadingGrid,
view: ViewFunctionStub<typeof PreloadingComponents.PreloadingGrid.PreloadingGrid>,
}> {
const view = createViewFunctionStub(PreloadingComponents.PreloadingGrid.PreloadingGrid);
const widget = new PreloadingComponents.PreloadingGrid.PreloadingGrid(view);
await view.nextInput;
return {widget, view};
}
async function assertRenderResult(rowsInput: {
rows: PreloadingComponents.PreloadingGrid.PreloadingGridRow[],
pageURL: Platform.DevToolsPath.UrlString,
}): Promise<void> {
const {widget, view} = await setupWidget();
widget.rows = rowsInput.rows;
widget.pageURL = rowsInput.pageURL;
await view.nextInput;
assert.strictEqual(rowsInput.rows, view.input.rows);
assert.strictEqual(rowsInput.pageURL, view.input.pageURL);
}
describeWithEnvironment('PreloadingGrid', () => {
it('renders grid', async () => {
await assertRenderResult({
rows: [{
id: 'id',
pipeline: SDK.PreloadingModel.PreloadPipeline.newFromAttemptsForTesting([{
action: Protocol.Preload.SpeculationAction.Prefetch,
key: {
loaderId: 'loaderId:1' as Protocol.Network.LoaderId,
action: Protocol.Preload.SpeculationAction.Prefetch,
url: urlString`https://example.com/prefetched.html`,
},
pipelineId: 'pipelineId:1' as Protocol.Preload.PreloadPipelineId,
status: SDK.PreloadingModel.PreloadingStatus.RUNNING,
prefetchStatus: null,
requestId: 'requestId:1' as Protocol.Network.RequestId,
ruleSetIds: ['ruleSetId:0.1'] as Protocol.Preload.RuleSetId[],
nodeIds: [1] as Protocol.DOM.BackendNodeId[],
}]),
ruleSets: [
{
id: 'ruleSetId:0.1' as Protocol.Preload.RuleSetId,
loaderId: 'loaderId:1' as Protocol.Network.LoaderId,
sourceText: `
{
"prefetch":[
{
"source": "list",
"urls": ["/prefetched.html"]
}
]
}
`,
},
],
}],
pageURL: urlString`https://example.com/`,
});
});
it('renders tag instead of url correctly', async () => {
await assertRenderResult({
rows: [{
id: 'id',
pipeline: SDK.PreloadingModel.PreloadPipeline.newFromAttemptsForTesting([{
action: Protocol.Preload.SpeculationAction.Prefetch,
key: {
loaderId: 'loaderId:1' as Protocol.Network.LoaderId,
action: Protocol.Preload.SpeculationAction.Prefetch,
url: urlString`https://example.com/prefetched.html`,
},
pipelineId: 'pipelineId:1' as Protocol.Preload.PreloadPipelineId,
status: SDK.PreloadingModel.PreloadingStatus.RUNNING,
prefetchStatus: null,
requestId: 'requestId:1' as Protocol.Network.RequestId,
ruleSetIds: ['ruleSetId:0.1'] as Protocol.Preload.RuleSetId[],
nodeIds: [1] as Protocol.DOM.BackendNodeId[],
}]),
ruleSets: [{
id: 'ruleSetId:0.1' as Protocol.Preload.RuleSetId,
loaderId: 'loaderId:1' as Protocol.Network.LoaderId,
tag: 'tag1',
sourceText: `
{
"tag": "tag1",
"prefetch":[
{
"source": "list",
"urls": ["/prefetched.html"]
}
]
}
`,
}],
}],
pageURL: urlString`https://example.com/`,
});
});
it('shows full URL for cross-origin preloading', async () => {
await assertRenderResult({
rows: [{
id: 'id',
pipeline: SDK.PreloadingModel.PreloadPipeline.newFromAttemptsForTesting([{
action: Protocol.Preload.SpeculationAction.Prefetch,
key: {
loaderId: 'loaderId:1' as Protocol.Network.LoaderId,
action: Protocol.Preload.SpeculationAction.Prefetch,
url: urlString`https://cross-origin.example.com/prefetched.html`,
},
pipelineId: 'pipelineId:1' as Protocol.Preload.PreloadPipelineId,
status: SDK.PreloadingModel.PreloadingStatus.RUNNING,
prefetchStatus: null,
requestId: 'requestId:1' as Protocol.Network.RequestId,
ruleSetIds: ['ruleSetId:0.1'] as Protocol.Preload.RuleSetId[],
nodeIds: [1] as Protocol.DOM.BackendNodeId[],
}]),
ruleSets: [
{
id: 'ruleSetId:0.1' as Protocol.Preload.RuleSetId,
loaderId: 'loaderId:1' as Protocol.Network.LoaderId,
sourceText: `
{
"prefetch":[
{
"source": "list",
"urls": ["https://cross-origin.example.com/prefetched.html"]
}
]
}
`,
},
],
}],
pageURL: urlString`https://example.com/`,
});
});
it('shows filename for out-of-document speculation rules', async () => {
await assertRenderResult({
rows: [{
id: 'id',
pipeline: SDK.PreloadingModel.PreloadPipeline.newFromAttemptsForTesting([{
action: Protocol.Preload.SpeculationAction.Prefetch,
key: {
loaderId: 'loaderId:1' as Protocol.Network.LoaderId,
action: Protocol.Preload.SpeculationAction.Prefetch,
url: urlString`https://example.com/prefetched.html`,
},
pipelineId: 'pipelineId:1' as Protocol.Preload.PreloadPipelineId,
status: SDK.PreloadingModel.PreloadingStatus.RUNNING,
prefetchStatus: null,
requestId: 'requestId:1' as Protocol.Network.RequestId,
ruleSetIds: ['ruleSetId:0.1'] as Protocol.Preload.RuleSetId[],
nodeIds: [] as Protocol.DOM.BackendNodeId[],
}]),
ruleSets: [
{
id: 'ruleSetId:0.1' as Protocol.Preload.RuleSetId,
loaderId: 'loaderId:1' as Protocol.Network.LoaderId,
sourceText: `
{
"prefetch":[
{
"source": "list",
"urls": ["/prefetched.html"]
}
]
}
`,
url: 'https://example.com/assets/speculation-rules.json',
},
],
}],
pageURL: urlString`https://example.com/`,
});
});
it('shows the only first speculation rules', async () => {
await assertRenderResult({
rows: [
{
id: 'id',
pipeline: SDK.PreloadingModel.PreloadPipeline.newFromAttemptsForTesting([{
action: Protocol.Preload.SpeculationAction.Prefetch,
key: {
loaderId: 'loaderId:1' as Protocol.Network.LoaderId,
action: Protocol.Preload.SpeculationAction.Prefetch,
url: urlString`https://example.com/rule-set-missing.html`,
},
pipelineId: 'pipelineId:1' as Protocol.Preload.PreloadPipelineId,
status: SDK.PreloadingModel.PreloadingStatus.RUNNING,
prefetchStatus: null,
requestId: 'requestId:1' as Protocol.Network.RequestId,
ruleSetIds: ['ruleSetId:0.1'] as Protocol.Preload.RuleSetId[],
nodeIds: [1] as Protocol.DOM.BackendNodeId[],
}]),
ruleSets: [],
},
{
id: 'id',
pipeline: SDK.PreloadingModel.PreloadPipeline.newFromAttemptsForTesting([{
action: Protocol.Preload.SpeculationAction.Prefetch,
key: {
loaderId: 'loaderId:1' as Protocol.Network.LoaderId,
action: Protocol.Preload.SpeculationAction.Prefetch,
url: urlString`https://example.com/multiple-rule-sets.html`,
},
pipelineId: 'pipelineId:2' as Protocol.Preload.PreloadPipelineId,
status: SDK.PreloadingModel.PreloadingStatus.RUNNING,
prefetchStatus: null,
requestId: 'requestId:2' as Protocol.Network.RequestId,
ruleSetIds: ['ruleSetId:0.2', 'ruleSetId:0.3'] as Protocol.Preload.RuleSetId[],
nodeIds: [1] as Protocol.DOM.BackendNodeId[],
}]),
ruleSets: [
{
id: 'ruleSetId:0.2' as Protocol.Preload.RuleSetId,
loaderId: 'loaderId:1' as Protocol.Network.LoaderId,
sourceText: `
{
"prefetch":[
{
"source": "list",
"urls": ["/multiple-rule-sets.html"]
}
]
}
`,
},
{
id: 'ruleSetId:0.3' as Protocol.Preload.RuleSetId,
loaderId: 'loaderId:1' as Protocol.Network.LoaderId,
sourceText: `
{
"prefetch":[
{
"source": "list",
"urls": ["/multiple-rule-sets.html"]
}
]
}
`,
url: 'https://example.com/assets/speculation-rules.json',
},
],
},
],
pageURL: urlString`https://example.com/`,
});
});
it('shows composed status for failure', async () => {
await assertRenderResult({
rows: [{
id: 'id',
pipeline: SDK.PreloadingModel.PreloadPipeline.newFromAttemptsForTesting([{
action: Protocol.Preload.SpeculationAction.Prerender,
key: {
loaderId: 'loaderId:1' as Protocol.Network.LoaderId,
action: Protocol.Preload.SpeculationAction.Prerender,
url: urlString`https://example.com/prerendered.html`,
},
pipelineId: 'pipelineId:1' as Protocol.Preload.PreloadPipelineId,
status: SDK.PreloadingModel.PreloadingStatus.FAILURE,
prerenderStatus: Protocol.Preload.PrerenderFinalStatus.MojoBinderPolicy,
disallowedMojoInterface: 'device.mojom.GamepadMonitor',
mismatchedHeaders: null,
ruleSetIds: ['ruleSetId:0.1'] as Protocol.Preload.RuleSetId[],
nodeIds: [1] as Protocol.DOM.BackendNodeId[],
}]),
ruleSets: [
{
id: 'ruleSetId:0.1' as Protocol.Preload.RuleSetId,
loaderId: 'loaderId:1' as Protocol.Network.LoaderId,
sourceText: `
{
"prerender":[
{
"source": "list",
"urls": ["/prerendered.html"]
}
]
}
`,
},
],
}],
pageURL: urlString`https://example.com/`,
});
});
it('shows a warning if a prerender fallbacks to prefetch', async () => {
await assertRenderResult({
rows: [{
id: 'id',
pipeline: SDK.PreloadingModel.PreloadPipeline.newFromAttemptsForTesting([
{
action: Protocol.Preload.SpeculationAction.Prefetch,
key: {
loaderId: 'loaderId:1' as Protocol.Network.LoaderId,
action: Protocol.Preload.SpeculationAction.Prefetch,
url: urlString`https://example.com/prerendered.html`,
},
pipelineId: 'pipelineId:1' as Protocol.Preload.PreloadPipelineId,
status: SDK.PreloadingModel.PreloadingStatus.SUCCESS,
prefetchStatus: Protocol.Preload.PrefetchStatus.PrefetchResponseUsed,
requestId: 'requestId:1' as Protocol.Network.RequestId,
ruleSetIds: ['ruleSetId:0.1'] as Protocol.Preload.RuleSetId[],
nodeIds: [1] as Protocol.DOM.BackendNodeId[],
},
{
action: Protocol.Preload.SpeculationAction.Prerender,
key: {
loaderId: 'loaderId:1' as Protocol.Network.LoaderId,
action: Protocol.Preload.SpeculationAction.Prerender,
url: urlString`https://example.com/prerendered.html`,
},
pipelineId: 'pipelineId:1' as Protocol.Preload.PreloadPipelineId,
status: SDK.PreloadingModel.PreloadingStatus.FAILURE,
prerenderStatus: Protocol.Preload.PrerenderFinalStatus.MojoBinderPolicy,
disallowedMojoInterface: 'device.mojom.GamepadMonitor',
mismatchedHeaders: null,
ruleSetIds: ['ruleSetId:0.1'] as Protocol.Preload.RuleSetId[],
nodeIds: [1] as Protocol.DOM.BackendNodeId[],
},
] as SDK.PreloadingModel.PreloadingAttempt[]),
ruleSets: [
{
id: 'ruleSetId:0.1' as Protocol.Preload.RuleSetId,
loaderId: 'loaderId:1' as Protocol.Network.LoaderId,
sourceText: `
{
"prerender":[
{
"source": "list",
"urls": ["/prerendered.html"]
}
]
}
`,
},
],
}],
pageURL: urlString`https://example.com/`,
});
});
it('shows failure if both prefetch and prerender failed', async () => {
await assertRenderResult({
rows: [{
id: 'id',
pipeline: SDK.PreloadingModel.PreloadPipeline.newFromAttemptsForTesting([
{
action: Protocol.Preload.SpeculationAction.Prefetch,
key: {
loaderId: 'loaderId:1' as Protocol.Network.LoaderId,
action: Protocol.Preload.SpeculationAction.Prefetch,
url: urlString`https://example.com/prerendered.html`,
},
pipelineId: 'pipelineId:1' as Protocol.Preload.PreloadPipelineId,
status: SDK.PreloadingModel.PreloadingStatus.FAILURE,
prefetchStatus: Protocol.Preload.PrefetchStatus.PrefetchFailedNon2XX,
requestId: 'requestId:1' as Protocol.Network.RequestId,
ruleSetIds: ['ruleSetId:0.1'] as Protocol.Preload.RuleSetId[],
nodeIds: [1] as Protocol.DOM.BackendNodeId[],
},
{
action: Protocol.Preload.SpeculationAction.Prerender,
key: {
loaderId: 'loaderId:1' as Protocol.Network.LoaderId,
action: Protocol.Preload.SpeculationAction.Prerender,
url: urlString`https://example.com/prerendered.html`,
},
pipelineId: 'pipelineId:1' as Protocol.Preload.PreloadPipelineId,
status: SDK.PreloadingModel.PreloadingStatus.FAILURE,
prerenderStatus: Protocol.Preload.PrerenderFinalStatus.PrerenderFailedDuringPrefetch,
disallowedMojoInterface: null,
mismatchedHeaders: null,
ruleSetIds: ['ruleSetId:0.1'] as Protocol.Preload.RuleSetId[],
nodeIds: [1] as Protocol.DOM.BackendNodeId[],
},
] as SDK.PreloadingModel.PreloadingAttempt[]),
ruleSets: [
{
id: 'ruleSetId:0.1' as Protocol.Preload.RuleSetId,
loaderId: 'loaderId:1' as Protocol.Network.LoaderId,
sourceText: `
{
"prerender":[
{
"source": "list",
"urls": ["/prerendered.html"]
}
]
}
`,
},
],
}],
pageURL: urlString`https://example.com/`,
});
});
});