UNPKG

chrome-devtools-frontend

Version:
209 lines (165 loc) 8.33 kB
// Copyright 2022 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import type * as SDK from '../../../core/sdk/sdk.js'; import * as Protocol from '../../../generated/protocol.js'; import { getCleanTextContentFromElements, getElementWithinComponent, renderElementIntoDOM, } from '../../../testing/DOMHelpers.js'; import {describeWithLocale} from '../../../testing/EnvironmentHelpers.js'; import * as RenderCoordinator from '../../../ui/components/render_coordinator/render_coordinator.js'; import * as ReportView from '../../../ui/components/report_view/report_view.js'; import * as UI from '../../../ui/legacy/legacy.js'; import * as ApplicationComponents from './components.js'; async function makeView( storageKeyOrBucketInfo: string|Protocol.Storage.StorageBucketInfo, storageBucketsModel?: SDK.StorageBucketsModel.StorageBucketsModel) { const component = new ApplicationComponents.StorageMetadataView.StorageMetadataView(); renderElementIntoDOM(component); if (storageBucketsModel) { component.enableStorageBucketControls(storageBucketsModel); } if (typeof storageKeyOrBucketInfo === 'string') { component.setStorageKey(storageKeyOrBucketInfo); } else { component.setStorageBucket(storageKeyOrBucketInfo); } await RenderCoordinator.done(); return component; } describeWithLocale('SharedStorageMetadataView', () => { it('renders with an origin only', async () => { const component = await makeView('https://example.com/'); const report = getElementWithinComponent(component, 'devtools-report', ReportView.ReportView.Report); const {textContent} = report.shadowRoot!.querySelector('.report-title')!; assert.strictEqual(textContent, 'https://example.com'); assert.isNotNull(component.shadowRoot); const keys = getCleanTextContentFromElements(component.shadowRoot, 'devtools-report-key'); assert.deepEqual(keys, [ 'Origin', ]); const values = getCleanTextContentFromElements(component.shadowRoot, 'devtools-report-value'); assert.deepEqual(values, [ 'https://example.com', ]); }); it('renders with an top-level site', async () => { const component = await makeView('https://example.com/^0https://test.example'); const report = getElementWithinComponent(component, 'devtools-report', ReportView.ReportView.Report); const {textContent} = report.shadowRoot!.querySelector('.report-title')!; assert.strictEqual(textContent, 'https://example.com'); assert.isNotNull(component.shadowRoot); const keys = getCleanTextContentFromElements(component.shadowRoot, 'devtools-report-key'); assert.deepEqual(keys, ['Origin', 'Top-level site', 'Is third-party']); const values = getCleanTextContentFromElements(component.shadowRoot, 'devtools-report-value'); assert.deepEqual( values, ['https://example.com', 'https://test.example', 'Yes, because the origin is outside of the top-level site']); }); it('renders with an opaque top-level site', async () => { const component = await makeView('https://example.com/^43735928559^5110521^6'); const report = getElementWithinComponent(component, 'devtools-report', ReportView.ReportView.Report); const {textContent} = report.shadowRoot!.querySelector('.report-title')!; assert.strictEqual(textContent, 'https://example.com'); assert.isNotNull(component.shadowRoot); const keys = getCleanTextContentFromElements(component.shadowRoot, 'devtools-report-key'); assert.deepEqual(keys, ['Origin', 'Top-level site', 'Is third-party', 'Is opaque']); const values = getCleanTextContentFromElements(component.shadowRoot, 'devtools-report-value'); assert.deepEqual(values, [ 'https://example.com', '(opaque)', 'Yes, because the top-level site is opaque', 'Yes, because the top-level site is opaque', ]); }); it('renders with an opaque key', async () => { const component = await makeView('https://example.com/^13735928559^2110521'); const report = getElementWithinComponent(component, 'devtools-report', ReportView.ReportView.Report); const {textContent} = report.shadowRoot!.querySelector('.report-title')!; assert.strictEqual(textContent, 'https://example.com'); assert.isNotNull(component.shadowRoot); const keys = getCleanTextContentFromElements(component.shadowRoot, 'devtools-report-key'); assert.deepEqual(keys, ['Origin', 'Is third-party', 'Is opaque']); const values = getCleanTextContentFromElements(component.shadowRoot, 'devtools-report-value'); assert.deepEqual(values, ['https://example.com', 'Yes, because the storage key is opaque', 'Yes']); }); it('renders with a cross-site ancestor chain', async () => { const component = await makeView('https://example.com/^31'); const report = getElementWithinComponent(component, 'devtools-report', ReportView.ReportView.Report); const {textContent} = report.shadowRoot!.querySelector('.report-title')!; assert.strictEqual(textContent, 'https://example.com'); assert.isNotNull(component.shadowRoot); const keys = getCleanTextContentFromElements(component.shadowRoot, 'devtools-report-key'); assert.deepEqual(keys, ['Origin', 'Is third-party']); const values = getCleanTextContentFromElements(component.shadowRoot, 'devtools-report-value'); assert.deepEqual(values, ['https://example.com', 'Yes, because the ancestry chain contains a third-party origin']); }); it('renders with a bucket', async () => { const component = await makeView({ bucket: {storageKey: 'https://example.com/^31', name: 'My Bucket'}, id: 'BUCKET_ID', persistent: true, durability: Protocol.Storage.StorageBucketsDurability.Relaxed, quota: 4096, expiration: 42, }); const report = getElementWithinComponent(component, 'devtools-report', ReportView.ReportView.Report); const {textContent} = report.shadowRoot!.querySelector('.report-title')!; assert.strictEqual(textContent, 'https://example.com'); assert.isNotNull(component.shadowRoot); const keys = getCleanTextContentFromElements(component.shadowRoot, 'devtools-report-key'); assert.deepEqual( keys, ['Origin', 'Is third-party', 'Bucket name', 'Is persistent', 'Durability', 'Quota', 'Expiration']); const values = getCleanTextContentFromElements(component.shadowRoot, 'devtools-report-value'); assert.deepEqual(values, [ 'https://example.com', 'Yes, because the ancestry chain contains a third-party origin', 'My Bucket', 'Yes', 'relaxed', '4.1 kB', (new Date(42000)).toLocaleString(), ]); }); it('renders with an emtpy string title', async () => { const component = await makeView(''); const report = getElementWithinComponent(component, 'devtools-report', ReportView.ReportView.Report); assert.isNull(report.shadowRoot!.querySelector('.report-title')); }); it('renders bucket controls', async () => { const storageBucketsModel = { deleteBucket: sinon.spy(), target: () => ({ model: () => ({ getBucketByName: () => null, }), }), }; const storageBucket = { storageKey: 'https://example.com/^31', name: 'My Bucket', }; const component = await makeView( { bucket: storageBucket, id: 'BUCKET_ID', persistent: true, durability: Protocol.Storage.StorageBucketsDurability.Relaxed, quota: 4096, expiration: 42, }, storageBucketsModel as unknown as SDK.StorageBucketsModel.StorageBucketsModel); const buttons = component.shadowRoot!.querySelectorAll('devtools-button'); assert.lengthOf(buttons, 1); const [deleteButton] = buttons; assert.instanceOf(deleteButton, HTMLElement); assert.strictEqual(deleteButton.textContent!.trim(), 'Delete bucket'); const showDialog = sinon.stub(UI.UIUtils.ConfirmDialog, 'show').resolves(true); deleteButton.click(); sinon.assert.calledOnce(showDialog); await new Promise(resolve => setTimeout(resolve, 0)); sinon.assert.calledOnceWithExactly(storageBucketsModel.deleteBucket, storageBucket); }); });