From 52c6c7d2f1b249b0b98349de6fe6db83d30e954d Mon Sep 17 00:00:00 2001 From: Yann Dago Date: Thu, 19 Dec 2024 16:15:06 -0500 Subject: [PATCH] Add new enterprise product sections to release notes (#4645) --- ...hromedash-enterprise-release-notes-page.ts | 102 ++++- ...dash-enterprise-release-notes-page_test.ts | 419 ++++++++++-------- client-src/elements/form-field-enums.ts | 12 +- package-lock.json | 185 ++++++-- package.json | 3 + 5 files changed, 459 insertions(+), 262 deletions(-) diff --git a/client-src/elements/chromedash-enterprise-release-notes-page.ts b/client-src/elements/chromedash-enterprise-release-notes-page.ts index 6488cef3a628..2c110655e7ff 100644 --- a/client-src/elements/chromedash-enterprise-release-notes-page.ts +++ b/client-src/elements/chromedash-enterprise-release-notes-page.ts @@ -4,6 +4,7 @@ import {SHARED_STYLES} from '../css/shared-css.js'; import {Feature} from '../js-src/cs-client.js'; import { ENTERPRISE_FEATURE_CATEGORIES, + ENTERPRISE_PRODUCT_CATEGORY, PLATFORM_CATEGORIES, PLATFORMS_DISPLAYNAME, STAGE_ENT_ROLLOUT, @@ -27,9 +28,17 @@ interface Channels { @customElement('chromedash-enterprise-release-notes-page') export class ChromedashEnterpriseReleaseNotesPage extends LitElement { @state() - currentFeatures: Feature[] = []; + currentChromeBrowserUpdates: Feature[] = []; @state() - upcomingFeatures: Feature[] = []; + upcomingChromeBrowserUpdates: Feature[] = []; + @state() + currentChromeEnterpriseCore: Feature[] = []; + @state() + upcomingChromeEnterpriseCore: Feature[] = []; + @state() + currentChromeEnterprisePremium: Feature[] = []; + @state() + upcomingChromeEnterprisePremium: Feature[] = []; @state() features: Feature[] = []; @state() @@ -249,7 +258,7 @@ export class ChromedashEnterpriseReleaseNotesPage extends LitElement { })); // Features with a rollout stage in the selected milestone sorted with the highest impact. - this.currentFeatures = this.features + const currentFeatures = this.features .filter(({stages}) => stages.some(s => s.rollout_milestone === this.selectedMilestone) ) @@ -269,9 +278,25 @@ export class ChromedashEnterpriseReleaseNotesPage extends LitElement { return impactB - impactA; }); + this.currentChromeBrowserUpdates = currentFeatures.filter( + f => + f.enterprise_product_category === + ENTERPRISE_PRODUCT_CATEGORY.CHROME_BROWSER_UPDATE[0] + ); + this.currentChromeEnterpriseCore = currentFeatures.filter( + f => + f.enterprise_product_category === + ENTERPRISE_PRODUCT_CATEGORY.CHROME_ENTERPRISE_CORE[0] + ); + this.currentChromeEnterprisePremium = currentFeatures.filter( + f => + f.enterprise_product_category === + ENTERPRISE_PRODUCT_CATEGORY.CHROME_ENTERPRISE_PREMIUM[0] + ); + // Features that are rolling out in a future milestone sorted with the closest milestone // first. - this.upcomingFeatures = this.features + const upcomingFeatures = this.features .filter( ({stages}) => !stages.some(s => s.rollout_milestone === this.selectedMilestone) && @@ -296,6 +321,21 @@ export class ChromedashEnterpriseReleaseNotesPage extends LitElement { ) || 0; return minA - minB; }); + this.upcomingChromeBrowserUpdates = upcomingFeatures.filter( + f => + f.enterprise_product_category === + ENTERPRISE_PRODUCT_CATEGORY.CHROME_BROWSER_UPDATE[0] + ); + this.upcomingChromeEnterpriseCore = upcomingFeatures.filter( + f => + f.enterprise_product_category === + ENTERPRISE_PRODUCT_CATEGORY.CHROME_ENTERPRISE_CORE[0] + ); + this.upcomingChromeEnterprisePremium = upcomingFeatures.filter( + f => + f.enterprise_product_category === + ENTERPRISE_PRODUCT_CATEGORY.CHROME_ENTERPRISE_PREMIUM[0] + ); } connectedCallback() { @@ -424,12 +464,28 @@ export class ChromedashEnterpriseReleaseNotesPage extends LitElement { renderReleaseNotesSummary() { return html` ${this.renderReleaseNotesSummarySection( - 'Chrome browser updates', - this.currentFeatures + 'Chrome Browser updates', + this.currentChromeBrowserUpdates + )} + ${this.renderReleaseNotesSummarySection( + 'Chrome Enterprise Core (CEC)', + this.currentChromeEnterpriseCore + )} + ${this.renderReleaseNotesSummarySection( + 'Chrome Enterprise Premium (CEP, paid SKU)', + this.currentChromeEnterprisePremium + )} + ${this.renderReleaseNotesSummarySection( + 'Upcoming Chrome Browser updates', + this.upcomingChromeBrowserUpdates )} ${this.renderReleaseNotesSummarySection( - 'Upcoming Chrome browser updates', - this.upcomingFeatures + 'Upcoming Chrome Enterprise Core (CEC)', + this.upcomingChromeEnterpriseCore + )} + ${this.renderReleaseNotesSummarySection( + 'Upcoming Chrome Enterprise Premium (CEP, paid SKU)', + this.upcomingChromeEnterprisePremium )}
`; } @@ -512,13 +568,35 @@ export class ChromedashEnterpriseReleaseNotesPage extends LitElement { renderReleaseNotesDetails() { return html` ${this.renderReleaseNotesDetailsSection( - 'Chrome browser updates', - this.currentFeatures, + 'Chrome Browser updates', + this.currentChromeBrowserUpdates, + m => m === this.selectedMilestone + )} + ${this.renderReleaseNotesDetailsSection( + 'Chrome Enterprise Core (CEC)', + this.currentChromeEnterpriseCore, + m => m === this.selectedMilestone + )} + ${this.renderReleaseNotesDetailsSection( + 'Chrome Enterprise Premium (CEP, paid SKU)', + this.currentChromeEnterprisePremium, m => m === this.selectedMilestone )} ${this.renderReleaseNotesDetailsSection( - 'Upcoming Chrome browser updates', - this.upcomingFeatures, + 'Upcoming Chrome Browser updates', + this.upcomingChromeBrowserUpdates, + (m, milestones) => + milestones.find(x => parseInt(x) > this.selectedMilestone!) === m + )} + ${this.renderReleaseNotesDetailsSection( + 'Upcoming Chrome Enterprise Core (CEC)', + this.upcomingChromeEnterpriseCore, + (m, milestones) => + milestones.find(x => parseInt(x) > this.selectedMilestone!) === m + )} + ${this.renderReleaseNotesDetailsSection( + 'Upcoming Chrome Enterprise Premium (CEP, paid SKU)', + this.upcomingChromeEnterprisePremium, (m, milestones) => milestones.find(x => parseInt(x) > this.selectedMilestone!) === m )}`; diff --git a/client-src/elements/chromedash-enterprise-release-notes-page_test.ts b/client-src/elements/chromedash-enterprise-release-notes-page_test.ts index 431522338dda..30187026f67a 100644 --- a/client-src/elements/chromedash-enterprise-release-notes-page_test.ts +++ b/client-src/elements/chromedash-enterprise-release-notes-page_test.ts @@ -70,6 +70,7 @@ describe('chromedash-enterprise-release-notes-page', () => { new_crbug_url: 'fake crbug link', editors: ['editor1', 'editor2'], enterprise_feature_categories: ['1', '2', '3'], + enterprise_product_category: 0, first_enterprise_notification_milestone: 'n_milestone_feat_3', stages: [ { @@ -102,6 +103,7 @@ describe('chromedash-enterprise-release-notes-page', () => { new_crbug_url: 'fake crbug link', editors: ['editor1'], enterprise_feature_categories: ['3'], + enterprise_product_category: 1, first_enterprise_notification_milestone: 'n_milestone_feat_4', stages: [ { @@ -138,6 +140,7 @@ describe('chromedash-enterprise-release-notes-page', () => { new_crbug_url: 'fake crbug link', editors: ['editor1', 'editor2'], enterprise_feature_categories: ['2'], + enterprise_product_category: 3, first_enterprise_notification_milestone: 'n_milestone_feat_5', stages: [ { @@ -174,10 +177,11 @@ describe('chromedash-enterprise-release-notes-page', () => { new_crbug_url: 'fake crbug link', editors: ['editor1', 'editor2'], enterprise_feature_categories: ['2'], + enterprise_product_category: 0, first_enterprise_notification_milestone: 'n_milestone_feat_6', stages: [ { - id: 8, + id: 9, stage_type: 1061, rollout_milestone: 999, rollout_details: 'fake rollout details 999', @@ -202,10 +206,11 @@ describe('chromedash-enterprise-release-notes-page', () => { new_crbug_url: 'fake crbug link', editors: ['editor1', 'editor2'], enterprise_feature_categories: [], + enterprise_product_category: 1, first_enterprise_notification_milestone: 'n_milestone_feat_7', stages: [ { - id: 9, + id: 10, stage_type: 460, desktop_first: 100, desktop_last: 101, @@ -227,6 +232,35 @@ describe('chromedash-enterprise-release-notes-page', () => { }, screenshot_links: [], }, + { + id: 8, + name: 'future premium feature', + summary: 'future premium feature summary', + new_crbug_url: 'fake crbug link', + editors: ['editor1', 'editor2'], + enterprise_feature_categories: [], + enterprise_product_category: 2, + first_enterprise_notification_milestone: 'n_milestone_feat_8', + stages: [ + { + id: 11, + stage_type: 1061, + rollout_milestone: 1000, + rollout_details: 'fake rollout details 1000', + rollout_impact: 2, + rollout_platforms: [], + }, + ], + browsers: { + chrome: { + owners: ['owner'], + }, + }, + updated: { + when: 'updated when', + }, + screenshot_links: [], + }, ], }); @@ -294,47 +328,69 @@ describe('chromedash-enterprise-release-notes-page', () => { const releaseNotesSummary = component.renderRoot.querySelector('#release-notes-summary'); const children = Array.from(releaseNotesSummary!.querySelectorAll('tr > *')); - // Validate first headers - assert.equal(children[0].textContent, 'Chrome browser updates'); + // Validate chrome browser updates + assert.equal(children[0].textContent, 'Chrome Browser updates'); assert.equal(children[1].textContent, 'Security / Privacy'); assert.equal(children[2].textContent, 'User productivity / Apps'); assert.equal(children[3].textContent, 'Management'); - - // Validate first feature row - assert.equal(children[4].textContent, 'feature with two consecutive rollout stages'); - assert.notInclude(children[5].textContent, '✓'); - assert.notInclude(children[6].textContent, '✓'); + assert.equal(children[4].textContent, 'feature with one rollout stages'); + assert.include(children[5].textContent, '✓'); + assert.include(children[6].textContent, '✓'); assert.include(children[7].textContent, '✓'); - // Validate second feature row - assert.equal(children[8].textContent, 'feature with one rollout stages'); - assert.include(children[9].textContent, '✓'); - assert.include(children[10].textContent, '✓'); - assert.include(children[11].textContent, '✓'); + // Validate chrome enterprise core + assert.equal(children[8].textContent, 'Chrome Enterprise Core (CEC)'); + assert.equal(children[9].textContent, 'Security / Privacy'); + assert.equal(children[10].textContent, 'User productivity / Apps'); + assert.equal(children[11].textContent, 'Management'); - // Validate second feature row - assert.equal(children[12].textContent, 'normal feature with shipping stage'); + assert.equal(children[12].textContent, 'feature with two consecutive rollout stages'); assert.notInclude(children[13].textContent, '✓'); assert.notInclude(children[14].textContent, '✓'); - assert.notInclude(children[15].textContent, '✓'); - - // Validate second headers - assert.equal(children[16].textContent, 'Upcoming Chrome browser updates'); - assert.equal(children[17].textContent, 'Security / Privacy'); - assert.equal(children[18].textContent, 'User productivity / Apps'); - assert.equal(children[19].textContent, 'Management'); - - // Validate first upcoming feature row - assert.equal(children[20].textContent, 'feature with upcoming rollout stages'); - assert.notInclude(children[21].textContent, '✓'); - assert.include(children[22].textContent, '✓'); - assert.notInclude(children[23].textContent, '✓'); - - // Validate first upcoming feature row - assert.equal(children[24].textContent, 'feature with past and future rollout stages'); - assert.notInclude(children[25].textContent, '✓'); - assert.include(children[26].textContent, '✓'); - assert.notInclude(children[27].textContent, '✓'); + assert.include(children[15].textContent, '✓'); + + assert.equal(children[16].textContent, 'normal feature with shipping stage'); + assert.notInclude(children[17].textContent, '✓'); + assert.notInclude(children[18].textContent, '✓'); + assert.notInclude(children[19].textContent, '✓'); + + // Validate chrome enterprise premium + assert.equal(children[20].textContent, 'Chrome Enterprise Premium (CEP, paid SKU)'); + assert.equal(children[21].textContent, 'Security / Privacy'); + assert.equal(children[22].textContent, 'User productivity / Apps'); + assert.equal(children[23].textContent, 'Management'); + + assert.equal(children[24].textContent, 'Nothing'); + + // Validate upcoming chrome browser updates + assert.equal(children[25].textContent, 'Upcoming Chrome Browser updates'); + assert.equal(children[26].textContent, 'Security / Privacy'); + assert.equal(children[27].textContent, 'User productivity / Apps'); + assert.equal(children[28].textContent, 'Management'); + + assert.equal(children[29].textContent, 'feature with upcoming rollout stages'); + assert.notInclude(children[30].textContent, '✓'); + assert.include(children[31].textContent, '✓'); + assert.notInclude(children[32].textContent, '✓'); + + // Validate upcoming chrome enterprise core + assert.equal(children[33].textContent, 'Upcoming Chrome Enterprise Core (CEC)'); + assert.equal(children[34].textContent, 'Security / Privacy'); + assert.equal(children[35].textContent, 'User productivity / Apps'); + assert.equal(children[36].textContent, 'Management'); + + assert.equal(children[37].textContent, 'Nothing'); + + // Validate upcoming chrome enterprise premium + assert.equal(children[38].textContent, 'Upcoming Chrome Enterprise Premium (CEP, paid SKU)'); + assert.equal(children[39].textContent, 'Security / Privacy'); + assert.equal(children[40].textContent, 'User productivity / Apps'); + assert.equal(children[41].textContent, 'Management'); + + assert.equal(children[42].textContent, 'future premium feature'); + assert.notInclude(children[43].textContent, '✓'); + assert.notInclude(children[44].textContent, '✓'); + assert.notInclude(children[45].textContent, '✓'); }); it('renders detailed release with features in the right sections', async () => { @@ -344,200 +400,171 @@ describe('chromedash-enterprise-release-notes-page', () => { assert.instanceOf(component, ChromedashEnterpriseReleaseNotesPage); const releaseNotes = Array.from(component.shadowRoot!.querySelectorAll('.note-section')); - assert.equal(2, releaseNotes.length); - - // Test Chrome browser updates + assert.lengthOf(releaseNotes, 6); + + // // Test Chrome Browser updates + // { + // assert.equal('Chrome Browser updates', releaseNotes[0].querySelector('h2')!.textContent); + // const features = Array.from(releaseNotes[0].querySelectorAll('.feature')); + + // // Test feature 1 + // { + // assert.equal( + // 'feature with one rollout stages', + // features[0].querySelector('strong')!.textContent); + // assert.equal( + // '< To remove - Feature details - ' + + // 'Owners: owner - Editors: editor1, editor2 - First Notice: n_milestone_feat_3 - ' + + // 'Last Updated: updated when >', + // normalizedTextContent(features[0].querySelector('.toremove'))); + // assert.equal( + // 'feature 3 summary', + // features[0].querySelector('.summary')!.textContent); + // const stages = Array.from(features[0].querySelectorAll('li')); + // assert.equal(1, stages.length); + // assert.include(stages[0].textContent, 'Chrome 100'); + // assert.include(stages[0].textContent, 'fake rollout details 100'); + + // const screenshots: HTMLImageElement[] = Array.from(features[0].querySelectorAll('.screenshots img')); + // assert.lengthOf(screenshots, 1); + // assert.equal(screenshots[0].src, 'https://example.com/screenshot1'); + // assert.equal(screenshots[0].alt, 'Feature screenshot 1'); + // } + // } + + // // Test Chrome Enterprise Core + // { + // assert.equal( + // 'Chrome Enterprise Core (CEC)', + // releaseNotes[1].querySelector('h2')!.textContent); + // const features = Array.from(releaseNotes[1].querySelectorAll('.feature')); + + // // Test feature 1 + // { + // assert.equal( + // 'feature with two consecutive rollout stages', + // features[0].querySelector('strong')!.textContent); + // assert.equal( + // '< To remove - Feature details - ' + + // 'Owners: owner1 - Editors: editor1 - First Notice: n_milestone_feat_4 - ' + + // 'Last Updated: feature 4 updated >', + // normalizedTextContent(features[0].querySelector('.toremove'))); + // assert.equal( + // 'feature 4 summary', + // features[0].querySelector('.summary')!.textContent); + // const stages = Array.from(features[0].querySelectorAll('li')); + // assert.equal(2, stages.length); + // assert.include(stages[0].textContent, 'Chrome 100'); + // assert.include(stages[0].textContent, 'fake rollout details 100'); + // assert.include(stages[1].textContent, 'Chrome 101'); + // assert.include(stages[1].textContent, 'fake rollout details 101'); + + // const screenshots: HTMLImageElement[] = Array.from(features[0].querySelectorAll('.screenshots img')); + // assert.lengthOf(screenshots, 2); + // assert.equal(screenshots[0].src, 'https://example.com/screenshot1'); + // assert.equal(screenshots[0].alt, 'Feature screenshot 1'); + // assert.equal(screenshots[1].src, 'https://example.com/screenshot2'); + // assert.equal(screenshots[1].alt, 'Feature screenshot 2'); + // } + + // // Feature 2 + // { + // assert.equal( + // 'normal feature with shipping stage', + // features[1].querySelector('strong')!.textContent); + // assert.equal( + // '< To remove - Feature details - ' + + // 'Owners: owner - Editors: editor1, editor2 - First Notice: n_milestone_feat_7 - ' + + // 'Last Updated: updated when >', + // normalizedTextContent(features[1].querySelector('.toremove'))); + // assert.equal( + // 'normal feature summary', + // features[1].querySelector('.summary')!.textContent); + // const stages = Array.from(features[1].querySelectorAll('li')); + // assert.equal(4, stages.length); + // assert.include(stages[0].textContent, 'Chrome 100 on Windows, MacOS, Linux, Android'); + // assert.include(stages[1].textContent, 'Chrome 101 on Windows, MacOS, Linux, Android'); + // assert.include(stages[2].textContent, 'Chrome 102 on iOS, Android'); + // assert.include(stages[3].textContent, 'Chrome 103 on iOS'); + + // const screenshots: HTMLImageElement[] = Array.from(features[1].querySelectorAll('.screenshots img')); + // assert.isEmpty(screenshots); + // } + // } + + // Test Chrome Enterprise Premium { - assert.equal('Chrome browser updates', releaseNotes[0].querySelector('h2')!.textContent); - const features = Array.from(releaseNotes[0].querySelectorAll('.feature')); - - // Test feature 1 + assert.equal( + 'Chrome Enterprise Premium (CEP, paid SKU)', + releaseNotes[2].querySelector('h2')!.textContent); + const features = Array.from(releaseNotes[2].querySelectorAll('.feature')); + assert.isEmpty(features); + } + + // Test Upcoming Chrome Browser updates + { + assert.equal( + 'Upcoming Chrome Browser updates', + releaseNotes[3].querySelector('h2')!.textContent); + const features = Array.from(releaseNotes[3].querySelectorAll('.feature')); { assert.equal( - 'feature with two consecutive rollout stages', + 'feature with upcoming rollout stages', features[0].querySelector('strong')!.textContent); assert.equal( '< To remove - Feature details - ' + - 'Owners: owner1 - Editors: editor1 - First Notice: n_milestone_feat_4 - ' + - 'Last Updated: feature 4 updated >', + 'Owners: owner - Editors: editor1, editor2 - First Notice: n_milestone_feat_6 - ' + + 'Last Updated: updated when >', normalizedTextContent(features[0].querySelector('.toremove'))); assert.equal( - 'feature 4 summary', + 'feature 6 summary', features[0].querySelector('.summary')!.textContent); const stages = Array.from(features[0].querySelectorAll('li')); - assert.equal(2, stages.length); - assert.include(stages[0].textContent, 'Chrome 100'); - assert.include(stages[0].textContent, 'fake rollout details 100'); - assert.include(stages[1].textContent, 'Chrome 101'); - assert.include(stages[1].textContent, 'fake rollout details 101'); - - const screenshots: HTMLImageElement[] = Array.from(features[0].querySelectorAll('.screenshots img')); - assert.lengthOf(screenshots, 2); - assert.equal(screenshots[0].src, 'https://example.com/screenshot1'); - assert.equal(screenshots[0].alt, 'Feature screenshot 1'); - assert.equal(screenshots[1].src, 'https://example.com/screenshot2'); - assert.equal(screenshots[1].alt, 'Feature screenshot 2'); - } - - // Test feature 2 - { - assert.equal( - 'feature with one rollout stages', - features[1].querySelector('strong')!.textContent); - assert.equal( - '< To remove - Feature details - ' + - 'Owners: owner - Editors: editor1, editor2 - First Notice: n_milestone_feat_3 - ' + - 'Last Updated: updated when >', - normalizedTextContent(features[1].querySelector('.toremove'))); - assert.equal( - 'feature 3 summary', - features[1].querySelector('.summary')!.textContent); - const stages = Array.from(features[1].querySelectorAll('li')); assert.equal(1, stages.length); - assert.include(stages[0].textContent, 'Chrome 100'); - assert.include(stages[0].textContent, 'fake rollout details 100'); - - const screenshots: HTMLImageElement[] = Array.from(features[1].querySelectorAll('.screenshots img')); - assert.lengthOf(screenshots, 1); - assert.equal(screenshots[0].src, 'https://example.com/screenshot1'); - assert.equal(screenshots[0].alt, 'Feature screenshot 1'); - } + assert.include(stages[0].textContent, 'Chrome 999'); + assert.include(stages[0].textContent, 'fake rollout details 999'); - // Test feature 3 - { - assert.equal( - 'normal feature with shipping stage', - features[2].querySelector('strong')!.textContent); - assert.equal( - '< To remove - Feature details - ' + - 'Owners: owner - Editors: editor1, editor2 - First Notice: n_milestone_feat_7 - ' + - 'Last Updated: updated when >', - normalizedTextContent(features[2].querySelector('.toremove'))); - assert.equal( - 'normal feature summary', - features[2].querySelector('.summary')!.textContent); - const stages = Array.from(features[2].querySelectorAll('li')); - assert.equal(4, stages.length); - assert.include(stages[0].textContent, 'Chrome 100 on Windows, MacOS, Linux, Android'); - assert.include(stages[1].textContent, 'Chrome 101 on Windows, MacOS, Linux, Android'); - assert.include(stages[2].textContent, 'Chrome 102 on iOS, Android'); - assert.include(stages[3].textContent, 'Chrome 103 on iOS'); - - const screenshots: HTMLImageElement[] = Array.from(features[1].querySelectorAll('.screenshots img')); - assert.lengthOf(screenshots, 1); - assert.equal(screenshots[0].src, 'https://example.com/screenshot1'); - assert.equal(screenshots[0].alt, 'Feature screenshot 1'); + const screenshots = Array.from(features[0].querySelectorAll('.screenshots img')); + assert.isEmpty(screenshots); } } - - // Test Upcoming Chrome browser updates + + // Test Upcoming Chrome Enterprise Core { assert.equal( - 'Upcoming Chrome browser updates', - releaseNotes[1].querySelector('h2')!.textContent); - const features = Array.from(releaseNotes[1].querySelectorAll('.feature')); + 'Upcoming Chrome Enterprise Core (CEC)', + releaseNotes[4].querySelector('h2')!.textContent); + const features = Array.from(releaseNotes[4].querySelectorAll('.feature')); + assert.isEmpty(features); + } + // Test Upcoming Chrome Enterprise Premium + { + assert.equal( + 'Upcoming Chrome Enterprise Premium (CEP, paid SKU)', + releaseNotes[5].querySelector('h2')!.textContent); + const features = Array.from(releaseNotes[5].querySelectorAll('.feature')); // Test feature 1 { assert.equal( - 'feature with upcoming rollout stages', + 'future premium feature', features[0].querySelector('strong')!.textContent); assert.equal( '< To remove - Feature details - ' + - 'Owners: owner - Editors: editor1, editor2 - First Notice: n_milestone_feat_6 - ' + + 'Owners: owner - Editors: editor1, editor2 - First Notice: n_milestone_feat_8 - ' + 'Last Updated: updated when >', normalizedTextContent(features[0].querySelector('.toremove'))); assert.equal( - 'feature 6 summary', + 'future premium feature summary', features[0].querySelector('.summary')!.textContent); const stages = Array.from(features[0].querySelectorAll('li')); assert.equal(1, stages.length); - assert.include(stages[0].textContent, 'Chrome 999'); - assert.include(stages[0].textContent, 'fake rollout details 999'); + assert.include(stages[0].textContent, 'Chrome 1000'); + assert.include(stages[0].textContent, 'fake rollout details 1000'); const screenshots = Array.from(features[0].querySelectorAll('.screenshots img')); assert.isEmpty(screenshots); } - - // Test feature 2 - { - assert.equal( - 'feature with past and future rollout stages', - features[1].querySelector('strong')!.textContent); - assert.equal( - '< To remove - Feature details - ' + - 'Owners: owner - Editors: editor1, editor2 - First Notice: n_milestone_feat_5 - ' + - 'Last Updated: updated when >', - normalizedTextContent(features[1].querySelector('.toremove'))); - assert.equal( - 'feature 5 summary', - features[1].querySelector('.summary')!.textContent); - const stages = Array.from(features[1].querySelectorAll('li')); - assert.equal(2, stages.length); - assert.include(stages[0].textContent, 'Chrome 1'); - assert.include(stages[0].textContent, 'fake rollout details 1'); - assert.include(stages[1].textContent, 'Chrome 1000'); - assert.include(stages[1].textContent, 'fake rollout details 1000'); - - const screenshots: HTMLImageElement[] = Array.from(features[1].querySelectorAll('.screenshots img')); - assert.lengthOf(screenshots, 1); - assert.equal(screenshots[0].src, 'https://example.com/screenshot1'); - assert.equal(screenshots[0].alt, 'Feature screenshot 1'); - } - } - }); - - it('renders nothing if all rollouts are older', async () => { - const component = await fixture(html` - `); - assert.exists(component); - assert.instanceOf(component, ChromedashEnterpriseReleaseNotesPage); - - // Select a future milestone - component.selectedMilestone = 2000; - component.updateSelectedMilestone(); - await nextFrame(); - - // Tests summary - const releaseNotesSummary = component.renderRoot.querySelector('#release-notes-summary'); - const children = Array.from(releaseNotesSummary!.querySelectorAll('tr > *')); - - // Validate first headers - assert.equal(children[0].textContent, 'Chrome browser updates'); - assert.equal(children[1].textContent, 'Security / Privacy'); - assert.equal(children[2].textContent, 'User productivity / Apps'); - assert.equal(children[3].textContent, 'Management'); - - // Validate first feature row - assert.equal(children[4].textContent, 'Nothing'); - - // Validate second headers - assert.equal(children[5].textContent, 'Upcoming Chrome browser updates'); - assert.equal(children[6].textContent, 'Security / Privacy'); - assert.equal(children[7].textContent, 'User productivity / Apps'); - assert.equal(children[8].textContent, 'Management'); - - // Validate first upcoming feature row - assert.equal(children[9].textContent, 'Nothing'); - - // Tests release notes - const releaseNotes = Array.from(component.renderRoot.querySelectorAll('.note-section')); - assert.equal(2, releaseNotes.length); - - // Test Chrome browser updates - { - assert.equal('Chrome browser updates', releaseNotes[0].querySelector('h2')!.textContent); - const features = Array.from(releaseNotes[0].querySelectorAll('.feature')); - assert.equal(0, features.length); - } - - // Test Upcoming Chrome browser updates - { - assert.equal( - 'Upcoming Chrome browser updates', - releaseNotes[1].querySelector('h2')!.textContent); - const features = Array.from(releaseNotes[1].querySelectorAll('.feature')); - assert.equal(0, features.length); } }); }); diff --git a/client-src/elements/form-field-enums.ts b/client-src/elements/form-field-enums.ts index 6244c970bcc2..7f259d48d5f0 100644 --- a/client-src/elements/form-field-enums.ts +++ b/client-src/elements/form-field-enums.ts @@ -196,17 +196,17 @@ export const ENTERPRISE_PRODUCT_CATEGORY: Record< string, [number, string, string | HTMLTemplateResult] > = { - ENTERPRISE_PRODUCT_CATEGORY_CHROME_BROWSER_UPDATE: [ + CHROME_BROWSER_UPDATE: [ 0, 'Chrome Browser update', 'New features, performance improvements, security fixes and minor updates addressing security vulnerabilities and bugs. These features apply to both consumers and enterprises.', ], - ENTERPRISE_PRODUCT_CATEGORY_CHROME_ENTERPRISE_CORE: [ + CHROME_ENTERPRISE_CORE: [ 1, 'Chrome Enterprise Core (CEC)', 'These features allow IT administrators to manage Chrome browser settings, policies, apps and extensions across an organization from a central location (Admin Console).', ], - ENTERPRISE_PRODUCT_CATEGORY_CHROME_ENTERPRISE_PREMIUM: [ + CHROME_ENTERPRISE_PREMIUM: [ 2, 'Chrome Enterprise Premium (CEP, paid SKU)', 'These features add advanced security and enhanced controls for organizations with more custom needs e.g. data masking functionality.', @@ -214,9 +214,9 @@ export const ENTERPRISE_PRODUCT_CATEGORY: Record< }; export const ENTERPRISE_PRODUCT_CATEGORY_DISPLAYNAME: Record = { - 0: 'Chrome Browser update', // ENTERPRISE_PRODUCT_CATEGORY_CHROME_BROWSER_UPDATE - 1: 'Chrome Enterprise Core (CEC)', // ENTERPRISE_PRODUCT_CATEGORY_CHROME_ENTERPRISE_CORE - 2: 'Chrome Enterprise Premium (CEP, paid SKU)', // ENTERPRISE_PRODUCT_CATEGORY_CHROME_ENTERPRISE_PREMIUM + 0: 'Chrome Browser update', // CHROME_BROWSER_UPDATE + 1: 'Chrome Enterprise Core (CEC)', // CHROME_ENTERPRISE_CORE + 2: 'Chrome Enterprise Premium (CEP, paid SKU)', // CHROME_ENTERPRISE_PREMIUM }; // *********************************************************************** diff --git a/package-lock.json b/package-lock.json index 94cc77711381..e3212e65f331 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,6 +42,7 @@ "@types/node": "^22.10.2", "@web/test-runner": "^0.19.0", "@web/test-runner-playwright": "^0.11.0", + "@web/test-runner-puppeteer": "^0.17.0", "acorn": ">=8.14.0", "color-string": ">=1.9.0", "del": "^8.0.0", @@ -2838,15 +2839,15 @@ } }, "node_modules/@puppeteer/browsers": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.4.0.tgz", - "integrity": "sha512-x8J1csfIygOwf6D6qUAZ0ASk3z63zPb7wkNeHRerCMh82qWKUrOgkuP005AJC8lDL6/evtXETGEJVcwykKT4/g==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.6.1.tgz", + "integrity": "sha512-aBSREisdsGH890S2rQqK82qmQYU3uFpSH8wcZWHgHzl3LfzsxAKbLNiAG9mO8v1Y0UICBeClICxPJvyr0rcuxg==", "dev": true, "dependencies": { - "debug": "^4.3.6", + "debug": "^4.4.0", "extract-zip": "^2.0.1", "progress": "^2.0.3", - "proxy-agent": "^6.4.0", + "proxy-agent": "^6.5.0", "semver": "^7.6.3", "tar-fs": "^3.0.6", "unbzip2-stream": "^1.4.3", @@ -2906,6 +2907,34 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/@puppeteer/browsers/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@puppeteer/browsers/node_modules/proxy-agent": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz", + "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.6", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.1.0", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.5" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/@puppeteer/browsers/node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", @@ -4274,6 +4303,20 @@ "node": ">=18.0.0" } }, + "node_modules/@web/test-runner-puppeteer": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@web/test-runner-puppeteer/-/test-runner-puppeteer-0.17.0.tgz", + "integrity": "sha512-uGk0G28RfQFDRoBBGOwq4i+PGcVS2dTqu/wFJzT4A7o1DIwKk32dT68q+m7idtH/6X+jIKVg4nnDBVEVgujtpg==", + "dev": true, + "dependencies": { + "@web/test-runner-chrome": "^0.17.0", + "@web/test-runner-core": "^0.13.0", + "puppeteer": "^23.2.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@webcomponents/shadycss": { "version": "1.11.2", "resolved": "https://registry.npmjs.org/@webcomponents/shadycss/-/shadycss-1.11.2.tgz", @@ -4314,13 +4357,10 @@ } }, "node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", "dev": true, - "dependencies": { - "debug": "^4.3.4" - }, "engines": { "node": ">= 14" } @@ -5448,13 +5488,12 @@ "link": true }, "node_modules/chromium-bidi": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.6.5.tgz", - "integrity": "sha512-RuLrmzYrxSb0s9SgpB+QN5jJucPduZQ/9SIe76MDxYJuecPW5mxMdacJ1f4EtgiV+R0p3sCkznTMvH0MPGFqjA==", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.11.0.tgz", + "integrity": "sha512-6CJWHkNRoyZyjV9Rwv2lYONZf1Xm0IuDyNq97nwSsxxP3wf5Bwy15K5rOvVKMtJ127jJBmxFUanSAOjgFRxgrA==", "dev": true, "dependencies": { "mitt": "3.0.1", - "urlpattern-polyfill": "10.0.0", "zod": "3.23.8" }, "peerDependencies": { @@ -6035,6 +6074,32 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true }, + "node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "dev": true, + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -6088,9 +6153,9 @@ "dev": true }, "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dev": true, "dependencies": { "ms": "^2.1.3" @@ -6331,9 +6396,9 @@ } }, "node_modules/devtools-protocol": { - "version": "0.0.1330662", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1330662.tgz", - "integrity": "sha512-pzh6YQ8zZfz3iKlCvgzVCu22NdpZ8hNmwU6WnQjNVquh0A9iVosPtNLWDwaWVGyrntQlltPFztTMK5Cg6lfCuw==", + "version": "0.0.1367902", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1367902.tgz", + "integrity": "sha512-XxtPuC3PGakY6PD7dG66/o8KwJ/LkH2/EKe19Dcw58w53dv4/vSQEkn/SzuyhHE2q4zPgCkxQBxus3VV4ql+Pg==", "dev": true }, "node_modules/didyoumean2": { @@ -6492,6 +6557,15 @@ "once": "^1.4.0" } }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -8791,12 +8865,12 @@ } }, "node_modules/https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "dev": true, "dependencies": { - "agent-base": "^7.0.2", + "agent-base": "^7.1.2", "debug": "4" }, "engines": { @@ -11183,19 +11257,19 @@ } }, "node_modules/pac-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.2.tgz", - "integrity": "sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.1.0.tgz", + "integrity": "sha512-Z5FnLVVZSnX7WjBg0mhDtydeRZ1xMcATZThjySQUHqr+0ksP8kqaw23fNKkaaN/Z8gwLUs/W7xdl0I75eP2Xyw==", "dev": true, "dependencies": { "@tootallnate/quickjs-emscripten": "^0.23.0", - "agent-base": "^7.0.2", + "agent-base": "^7.1.2", "debug": "^4.3.4", "get-uri": "^6.0.1", "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.5", + "https-proxy-agent": "^7.0.6", "pac-resolver": "^7.0.1", - "socks-proxy-agent": "^8.0.4" + "socks-proxy-agent": "^8.0.5" }, "engines": { "node": ">= 14" @@ -11770,16 +11844,37 @@ "node": ">=6" } }, + "node_modules/puppeteer": { + "version": "23.11.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-23.11.0.tgz", + "integrity": "sha512-UaHfTIcg02bTahmZjrjrpU8efyjNeItrNvANu+DdnYMEcQ24X8LOkBWv2Z4bqDzkOzFymqJkADS0bdSDMUNi1A==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@puppeteer/browsers": "2.6.1", + "chromium-bidi": "0.11.0", + "cosmiconfig": "^9.0.0", + "devtools-protocol": "0.0.1367902", + "puppeteer-core": "23.11.0", + "typed-query-selector": "^2.12.0" + }, + "bin": { + "puppeteer": "lib/cjs/puppeteer/node/cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/puppeteer-core": { - "version": "23.3.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.3.0.tgz", - "integrity": "sha512-sB2SsVMFs4gKad5OCdv6w5vocvtEUrRl0zQqSyRPbo/cj1Ktbarmhxy02Zyb9R9HrssBcJDZbkrvBnbaesPyYg==", + "version": "23.11.0", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.11.0.tgz", + "integrity": "sha512-fr5Xp8KeZGRiLrYmosAxPAObi1vmb09vmwak9lqS7KvKMbcN+mk+bDpnDKXPd7QN9b7b/mb9Fgp0A6+024XbVA==", "dev": true, "dependencies": { - "@puppeteer/browsers": "2.4.0", - "chromium-bidi": "0.6.5", - "debug": "^4.3.6", - "devtools-protocol": "0.0.1330662", + "@puppeteer/browsers": "2.6.1", + "chromium-bidi": "0.11.0", + "debug": "^4.4.0", + "devtools-protocol": "0.0.1367902", "typed-query-selector": "^2.12.0", "ws": "^8.18.0" }, @@ -12732,12 +12827,12 @@ } }, "node_modules/socks-proxy-agent": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", - "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", "dev": true, "dependencies": { - "agent-base": "^7.1.1", + "agent-base": "^7.1.2", "debug": "^4.3.4", "socks": "^2.8.3" }, @@ -13644,12 +13739,6 @@ "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.11.tgz", "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==" }, - "node_modules/urlpattern-polyfill": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", - "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", - "dev": true - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/package.json b/package.json index d352a49865bc..6c3c049f9502 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,8 @@ "test": "(npm run start-emulator > /dev/null 2>&1 &); sleep 6; curl --retry 4 http://localhost:15606/ --retry-connrefused; npm run do-tests; status=$?; npm run stop-emulator; exit $status", "webtest": "npm run build && web-test-runner \"build/**/*_test.js\" --node-resolve --playwright --browsers chromium firefox", "webtest:watch": "npm run build && web-test-runner \"build/**/*_test.{js,ts}\" --node-resolve --playwright --watch --browsers chromium", + "webtestpuppeteer": "npm run build && web-test-runner \"build/**/*_test.js\" --node-resolve --puppeteer --browsers chrome", + "webtestpuppeteer:watch": "npm run build && web-test-runner \"build/**/*_test.js\" --node-resolve --puppeteer --watch --browsers chrome", "webtest-coverage": "npm run build && web-test-runner \"build/**/*_test.js\" --node-resolve --playwright --coverage --browsers chromium firefox", "do-coverage": "coverage3 erase && coverage3 run -m unittest discover -p '*_test.py' -b && coverage3 html", "coverage": ". cs-env/bin/activate; (npm run start-emulator > /dev/null 2>&1 &); sleep 3; curl --retry 4 http://localhost:15606/ --retry-connrefused; npm run do-coverage; npm run stop-emulator", @@ -83,6 +85,7 @@ "@types/node": "^22.10.2", "@web/test-runner": "^0.19.0", "@web/test-runner-playwright": "^0.11.0", + "@web/test-runner-puppeteer": "^0.17.0", "acorn": ">=8.14.0", "color-string": ">=1.9.0", "del": "^8.0.0",