chrome-devtools-frontend
Version:
Chrome DevTools UI
161 lines (136 loc) • 6.72 kB
text/typescript
// Copyright 2024 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 * as Host from '../../core/host/host.js';
import * as Platform from '../../core/platform/platform.js';
import {
describeWithEnvironment,
} from '../../testing/EnvironmentHelpers.js';
import type * as Buttons from '../../ui/components/buttons/buttons.js';
import type * as UI from '../../ui/legacy/legacy.js';
import * as WhatsNew from './whats_new.js';
const {urlString} = Platform.DevToolsPath;
const CONTENT1 = 'Something something topic-1.\n';
const CONTENT2 = 'Something something topic-2.\n';
describeWithEnvironment('Release Note View', () => {
before(() => {
WhatsNew.ReleaseNoteText.setReleaseNoteForTest(
{
version: 99,
header: 'What\'s new in DevTools 100',
markdownLinks: [
{
key: 'topic-1',
link: 'https://google.com.com/#topic-1',
},
],
videoLinks: [
{
description: 'Highlight from the Chrome 132 update',
link: urlString`https://developer.chrome.com/blog/new-in-devtools-132/`,
type: WhatsNew.ReleaseNoteText.VideoType.WHATS_NEW,
},
{
description: 'DevTools tips',
link: urlString`https://developer.chrome.com/blog/devtools-tips-39`,
type: WhatsNew.ReleaseNoteText.VideoType.DEVTOOLS_TIPS,
},
{
description: 'Other',
link: urlString`https://developer.chrome.com/`,
type: WhatsNew.ReleaseNoteText.VideoType.OTHER,
},
],
link: 'https://google.com',
},
);
});
it('splits up markdown file content into separate sections', async () => {
const h1 = '### [Topic 1](topic-1)\n';
const h2 = '### [Topic 2](topic-2)\n';
const content = [h1, CONTENT1, h2, CONTENT2];
const notes = content.join('');
sinon.stub(WhatsNew.ReleaseNoteView.ReleaseNoteView, 'getFileContent').returns(Promise.resolve(notes));
const splitContent = await WhatsNew.ReleaseNoteView.getMarkdownContent();
assert.lengthOf(splitContent, 2);
for (let i = 0; i < 2; ++i) {
assert.lengthOf(splitContent[i], 2);
assert.deepEqual(splitContent[i][0].type, 'heading');
assert.deepEqual(splitContent[i][1].type, 'paragraph');
assert.deepEqual(splitContent[i][0].raw, content[i * 2]);
assert.deepEqual(splitContent[i][1].raw, content[i * 2 + 1]);
}
});
it('groups nested markdown headers into one', async () => {
const h1 = '### [Topic 1](topic-1)\n';
const h2 = '#### [Topic 2](topic-2)\n';
const content = [h1, CONTENT1, h2, CONTENT2];
const notes = content.join('');
sinon.stub(WhatsNew.ReleaseNoteView.ReleaseNoteView, 'getFileContent').returns(Promise.resolve(notes));
const splitContent = await WhatsNew.ReleaseNoteView.getMarkdownContent();
assert.lengthOf(splitContent, 1);
assert.lengthOf(splitContent[0], 4);
assert.deepEqual(splitContent[0][0].raw, h1);
assert.deepEqual(splitContent[0][1].raw, CONTENT1);
assert.deepEqual(splitContent[0][2].raw, h2);
assert.deepEqual(splitContent[0][3].raw, CONTENT2);
});
it('splits headerless paragraphs into its own section', async () => {
const h1 = '### [Topic 1](topic-1)\n';
const content = [CONTENT1, h1];
const notes = content.join('');
sinon.stub(WhatsNew.ReleaseNoteView.ReleaseNoteView, 'getFileContent').returns(Promise.resolve(notes));
const splitContent = await WhatsNew.ReleaseNoteView.getMarkdownContent();
assert.lengthOf(splitContent, 2);
assert.lengthOf(splitContent[0], 1);
assert.lengthOf(splitContent[1], 1);
assert.deepEqual(splitContent[0][0].raw, CONTENT1);
assert.deepEqual(splitContent[1][0].raw, h1);
});
it('renders markdown content', async () => {
sinon.stub(WhatsNew.ReleaseNoteView.ReleaseNoteView, 'getFileContent').returns(Promise.resolve(CONTENT1));
const releaseNoteView = new WhatsNew.ReleaseNoteView.ReleaseNoteView();
await releaseNoteView.updateComplete;
const markdown = releaseNoteView.contentElement.querySelector('devtools-markdown-view');
assert.isNotNull(markdown);
});
it('renders button that links to blogpost', async () => {
sinon.stub(WhatsNew.ReleaseNoteView.ReleaseNoteView, 'getFileContent').returns(Promise.resolve(''));
const releaseNoteView = new WhatsNew.ReleaseNoteView.ReleaseNoteView();
await releaseNoteView.updateComplete;
const button = releaseNoteView.contentElement.querySelector<Buttons.Button.Button>('devtools-button');
assert.isNotNull(button);
const openInNewTabStub = sinon.stub(Host.InspectorFrontendHost.InspectorFrontendHostInstance, 'openInNewTab');
button.click();
sinon.assert.callCount(openInNewTabStub, 1);
assert.isTrue(
openInNewTabStub.firstCall.calledWith(urlString`https://google.com/`),
'openInNewTab was not called with the expected URL.');
});
it('renders video links with description text', async () => {
sinon.stub(WhatsNew.ReleaseNoteView.ReleaseNoteView, 'getFileContent').returns(Promise.resolve(''));
const releaseNoteView = new WhatsNew.ReleaseNoteView.ReleaseNoteView();
await releaseNoteView.updateComplete;
const videos = releaseNoteView.contentElement.querySelectorAll<UI.XLink.XLink>('.video-container > x-link');
assert.lengthOf(videos, 3);
const releaseNotes = WhatsNew.ReleaseNoteText.getReleaseNote();
const descriptions = Array.from(videos).map(n => n.innerText.trim());
const expectedDescriptions = releaseNotes.videoLinks.map(video => video.description);
assert.deepEqual(descriptions, expectedDescriptions);
});
it('renders expected thumbnails', async () => {
sinon.stub(WhatsNew.ReleaseNoteView.ReleaseNoteView, 'getFileContent').returns(Promise.resolve(''));
const releaseNoteView = new WhatsNew.ReleaseNoteView.ReleaseNoteView();
await releaseNoteView.updateComplete;
const thumbnails = releaseNoteView.contentElement.querySelectorAll<HTMLImageElement>('.thumbnail');
assert.lengthOf(thumbnails, 3);
const thumbnailFilepaths = Array.from(thumbnails).map(n => n.src);
const expectedThumbnails = [
WhatsNew.ReleaseNoteView.WHATS_NEW_THUMBNAIL,
WhatsNew.ReleaseNoteView.DEVTOOLS_TIPS_THUMBNAIL,
WhatsNew.ReleaseNoteView.GENERAL_THUMBNAIL,
];
const expectedFilepaths = expectedThumbnails.map(src => new URL(src, import.meta.url).toString());
assert.deepEqual(thumbnailFilepaths, expectedFilepaths);
});
});