From 8545aff9962ee17d3412639e87d3e051470e9bbe Mon Sep 17 00:00:00 2001 From: Avi Shah Date: Thu, 28 Nov 2024 11:27:59 +0530 Subject: [PATCH] change storeknox flow to land on inventory first --- app/components/ak-svg/security-bg-img.hbs | 37 ++++++ app/components/ak-svg/security-indicator.hbs | 21 +++ app/components/ak-svg/sm-indicator.hbs | 18 +-- app/components/ak-svg/vapt-indicator.hbs | 21 +++ app/components/ak-svg/vp-indicator.hbs | 21 --- app/components/appknox-wrapper/index.hbs | 1 - app/components/appknox-wrapper/index.ts | 23 ---- app/components/home-page/index.hbs | 1 + app/components/home-page/index.ts | 42 ++++-- .../home-page/product-card/index.hbs | 2 + .../home-page/product-card/index.ts | 11 +- app/components/side-nav/index.hbs | 120 ++++++++---------- app/components/side-nav/index.ts | 16 +-- .../side-nav/product-switcher/index.hbs | 19 ++- .../side-nav/product-switcher/index.scss | 10 +- .../side-nav/product-switcher/index.ts | 61 +++++++-- .../side-nav/security-menu-item/index.hbs | 36 ------ .../side-nav/security-menu-item/index.ts | 23 ---- app/components/storeknox-wrapper/index.ts | 18 +-- .../user-login/perform-mfa/index.ts | 2 +- .../user-login/via-username-password/index.ts | 2 +- app/router.ts | 5 +- app/routes/authenticated/home.ts | 5 +- app/services/organization.ts | 14 ++ app/services/whitelabel.ts | 6 +- cypress/tests/auth.spec.ts | 2 +- tests/acceptance/home-page-test.js | 80 ++++++++++-- tests/acceptance/side-nav-test.js | 65 +++++++++- .../components/appknox-wrapper-test.js | 11 -- .../components/public-api-docs-test.js | 12 ++ .../components/storeknox-wrapper-test.js | 21 ++- translations/en.json | 1 + translations/ja.json | 1 + types/ak-svg.d.ts | 5 +- 34 files changed, 452 insertions(+), 281 deletions(-) create mode 100644 app/components/ak-svg/security-bg-img.hbs create mode 100644 app/components/ak-svg/security-indicator.hbs create mode 100644 app/components/ak-svg/vapt-indicator.hbs delete mode 100644 app/components/ak-svg/vp-indicator.hbs delete mode 100644 app/components/side-nav/security-menu-item/index.hbs delete mode 100644 app/components/side-nav/security-menu-item/index.ts diff --git a/app/components/ak-svg/security-bg-img.hbs b/app/components/ak-svg/security-bg-img.hbs new file mode 100644 index 000000000..87893ba51 --- /dev/null +++ b/app/components/ak-svg/security-bg-img.hbs @@ -0,0 +1,37 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/components/ak-svg/security-indicator.hbs b/app/components/ak-svg/security-indicator.hbs new file mode 100644 index 000000000..05928bb0e --- /dev/null +++ b/app/components/ak-svg/security-indicator.hbs @@ -0,0 +1,21 @@ + + + + \ No newline at end of file diff --git a/app/components/ak-svg/sm-indicator.hbs b/app/components/ak-svg/sm-indicator.hbs index c2d4084d1..05cd2e575 100644 --- a/app/components/ak-svg/sm-indicator.hbs +++ b/app/components/ak-svg/sm-indicator.hbs @@ -1,21 +1,21 @@ \ No newline at end of file diff --git a/app/components/ak-svg/vapt-indicator.hbs b/app/components/ak-svg/vapt-indicator.hbs new file mode 100644 index 000000000..fae808631 --- /dev/null +++ b/app/components/ak-svg/vapt-indicator.hbs @@ -0,0 +1,21 @@ + + + + \ No newline at end of file diff --git a/app/components/ak-svg/vp-indicator.hbs b/app/components/ak-svg/vp-indicator.hbs deleted file mode 100644 index 27551bdd7..000000000 --- a/app/components/ak-svg/vp-indicator.hbs +++ /dev/null @@ -1,21 +0,0 @@ - - - - \ No newline at end of file diff --git a/app/components/appknox-wrapper/index.hbs b/app/components/appknox-wrapper/index.hbs index a909bf736..7ce5763ef 100644 --- a/app/components/appknox-wrapper/index.hbs +++ b/app/components/appknox-wrapper/index.hbs @@ -58,7 +58,6 @@ { - this.isSecurityEnabled = true; - }, - () => { - this.isSecurityEnabled = false; - } - ); - } - @action handleAddEditOrgNameCancel() { this.showAddEditModal = false; diff --git a/app/components/home-page/index.hbs b/app/components/home-page/index.hbs index 3390ebe0c..a24ab6090 100644 --- a/app/components/home-page/index.hbs +++ b/app/components/home-page/index.hbs @@ -62,6 +62,7 @@ @linkText={{t 'takeMeToDashboard'}} @coverBackgroundImage={{productCardDetails.coverImage}} @indicatorSvg={{productCardDetails.indicator}} + @openInNewTab={{productCardDetails.openInNewTab}} /> {{/each}} diff --git a/app/components/home-page/index.ts b/app/components/home-page/index.ts index 7201e34a6..37885ca30 100644 --- a/app/components/home-page/index.ts +++ b/app/components/home-page/index.ts @@ -3,54 +3,72 @@ import Component from '@glimmer/component'; import type IntlService from 'ember-intl/services/intl'; import type OrganizationService from 'irene/services/organization'; -import type ConfigurationService from 'irene/services/configuration'; import type UserAuthService from 'irene/services/user-auth'; +import type WhitelabelService from 'irene/services/whitelabel'; interface productCardDetails { title: string; desc: string; link: string; - indicator: 'ak-svg/sm-indicator' | 'ak-svg/vp-indicator'; - coverImage: 'ak-svg/storeknox-bg-img' | 'ak-svg/appknox-bg-img'; + indicator: + | 'ak-svg/sm-indicator' + | 'ak-svg/vapt-indicator' + | 'ak-svg/security-indicator'; + coverImage: + | 'ak-svg/storeknox-bg-img' + | 'ak-svg/appknox-bg-img' + | 'ak-svg/security-bg-img'; + openInNewTab?: boolean; } export default class HomePageComponent extends Component { @service declare intl: IntlService; @service declare organization: OrganizationService; - @service declare configuration: ConfigurationService; @service declare userAuth: UserAuthService; @service declare session: any; + @service declare ajax: any; + @service declare whitelabel: WhitelabelService; get isStoreknoxEnabled() { return this.organization.selected?.features?.storeknox; } - get orgIsAnEnterprise() { - return this.configuration.serverData.enterprise; + get isWhitelabel() { + return !this.whitelabel.is_appknox_url; } get productCardDetails() { return [ { - title: this.orgIsAnEnterprise - ? this.intl.t('vapt') - : this.intl.t('appknox'), + title: this.isWhitelabel ? this.intl.t('vapt') : this.intl.t('appknox'), desc: this.intl.t('appknoxDesc'), link: 'authenticated.dashboard.projects', - indicator: 'ak-svg/vp-indicator', + indicator: 'ak-svg/vapt-indicator', coverImage: 'ak-svg/appknox-bg-img', }, this.isStoreknoxEnabled && { - title: this.orgIsAnEnterprise + title: this.isWhitelabel ? this.intl.t('appMonitoring') : this.intl.t('storeknox'), desc: this.intl.t('storeknoxDesc'), - link: 'authenticated.storeknox.discover', + link: 'authenticated.storeknox.inventory.app-list', indicator: 'ak-svg/sm-indicator', coverImage: 'ak-svg/storeknox-bg-img', }, + this.isSecurityEnabled && { + title: this.intl.t('securityDashboard'), + desc: this.intl.t('securityDashboardDesc'), + link: 'authenticated.security.projects', + indicator: 'ak-svg/security-indicator', + coverImage: 'ak-svg/security-bg-img', + openInNewTab: true, + }, ].filter(Boolean) as productCardDetails[]; } + + get isSecurityEnabled() { + return this.organization.isSecurityEnabled; + } } declare module '@glint/environment-ember-loose/registry' { diff --git a/app/components/home-page/product-card/index.hbs b/app/components/home-page/product-card/index.hbs index 0f87138b6..8f9b315b7 100644 --- a/app/components/home-page/product-card/index.hbs +++ b/app/components/home-page/product-card/index.hbs @@ -35,6 +35,8 @@ @route={{this.route}} @underline='always' @fontWeight='medium' + target={{if @openInNewTab '_blank'}} + rel={{if @openInNewTab 'noopener noreferrer'}} > {{@linkText}} diff --git a/app/components/home-page/product-card/index.ts b/app/components/home-page/product-card/index.ts index ca45b1980..36f10932c 100644 --- a/app/components/home-page/product-card/index.ts +++ b/app/components/home-page/product-card/index.ts @@ -9,8 +9,15 @@ export interface ProductCardComponentSignature { description: string; linkText: string; route: string; - coverBackgroundImage: 'ak-svg/storeknox-bg-img' | 'ak-svg/appknox-bg-img'; - indicatorSvg: 'ak-svg/sm-indicator' | 'ak-svg/vp-indicator'; + coverBackgroundImage: + | 'ak-svg/storeknox-bg-img' + | 'ak-svg/appknox-bg-img' + | 'ak-svg/security-bg-img'; + indicatorSvg: + | 'ak-svg/sm-indicator' + | 'ak-svg/vapt-indicator' + | 'ak-svg/security-indicator'; + openInNewTab?: boolean; }; Blocks: { default: []; diff --git a/app/components/side-nav/index.hbs b/app/components/side-nav/index.hbs index 75efc1fd8..ac99ab5bb 100644 --- a/app/components/side-nav/index.hbs +++ b/app/components/side-nav/index.hbs @@ -15,7 +15,7 @@ - {{#if this.showStoreknox}} + {{#if (or this.isSecurityEnabled this.showStoreknox)}} {{#each @menuItems as |it|}} - {{#if it.component}} - - {{#let (component it.component) as |Component|}} - - {{/let}} - - - {{else}} - + - - - {{#if it.icon}} - - {{else if it.customIconComponent}} - {{#let (component it.customIconComponent) as |CustomIcon|}} - - {{/let}} - {{/if}} - - - {{#if this.isSidebarExpanded}} - + {{#if it.icon}} + + {{else if it.customIconComponent}} + {{#let (component it.customIconComponent) as |CustomIcon|}} + + {{/let}} {{/if}} + - {{#if (and it.hasBadge this.isSidebarExpanded)}} - - - - {{/if}} - - - {{/if}} + {{#if this.isSidebarExpanded}} + + {{/if}} + + {{#if (and it.hasBadge this.isSidebarExpanded)}} + + + + {{/if}} + + {{/each}} diff --git a/app/components/side-nav/index.ts b/app/components/side-nav/index.ts index 592ed0e38..20d5f90d5 100644 --- a/app/components/side-nav/index.ts +++ b/app/components/side-nav/index.ts @@ -1,5 +1,5 @@ import Component from '@glimmer/component'; -import { inject as service } from '@ember/service'; +import { service } from '@ember/service'; import type IntlService from 'ember-intl/services/intl'; import type MeService from 'irene/services/me'; @@ -22,7 +22,6 @@ export interface SideNavSignature { Args: { menuItems: MenuItem[]; lowerMenuItems?: LowerMenuItem[]; - isSecurityEnabled?: boolean; isCollapsed: boolean; toggleSidebar: () => void; productSwitcherFilterKey: string; @@ -41,7 +40,6 @@ export interface MenuItem { currentWhen?: string; hasBadge?: boolean; badgeLabel?: string; - component?: 'side-nav/security-menu-item'; customIconComponent?: 'ak-svg/public-api-icon'; } @@ -56,14 +54,6 @@ export interface LowerMenuItem { listItemClass?: string; } -export interface SwitcherMenuItem { - id: string; - svg: 'ak-svg/sm-indicator' | 'ak-svg/vp-indicator'; - label: string; - route: string; - key: string; -} - export default class SideNavComponent extends Component { @service declare me: MeService; @service declare organization: OrganizationService; @@ -121,6 +111,10 @@ export default class SideNavComponent extends Component { get showStoreknox() { return this.organization?.selected?.features?.storeknox; } + + get isSecurityEnabled() { + return this.organization.isSecurityEnabled; + } } declare module '@glint/environment-ember-loose/registry' { diff --git a/app/components/side-nav/product-switcher/index.hbs b/app/components/side-nav/product-switcher/index.hbs index 00247f866..06fcf972b 100644 --- a/app/components/side-nav/product-switcher/index.hbs +++ b/app/components/side-nav/product-switcher/index.hbs @@ -59,20 +59,29 @@ {{t 'switchTo'}} - {{#each this.switcherMenuItems as |switcherItem|}} + {{#each this.switcherMenuItems as |item index|}} + {{#if (not-eq index 0)}} + + {{/if}} + - {{#let (component switcherItem.svg) as |SvgIcon|}} - + {{#let (component item.svg) as |SvgIcon|}} + {{/let}} - {{switcherItem.label}} + {{item.label}} diff --git a/app/components/side-nav/product-switcher/index.scss b/app/components/side-nav/product-switcher/index.scss index 8ca2c3874..d605e83e8 100644 --- a/app/components/side-nav/product-switcher/index.scss +++ b/app/components/side-nav/product-switcher/index.scss @@ -2,7 +2,6 @@ width: 100%; display: flex; align-items: center; - cursor: pointer; &.collapsed { justify-content: center; @@ -13,6 +12,7 @@ display: flex; width: 100%; padding: 1em; + cursor: pointer; &.collapsed { justify-content: center; @@ -28,11 +28,12 @@ border: var(--side-nav-product-switcher-border); box-shadow: var(--side-nav-product-switcher-box-shadow); min-width: 200px; + max-width: 220px; background-color: var(--side-nav-product-switcher-bg-main); .switcher-menu-item { width: 100%; - margin: 0.3em 0; + margin: 0.2em 0; padding: 0.75em 1em; justify-content: flex-start; @@ -48,6 +49,11 @@ background-color: var(--side-nav-product-switcher-modal-title-background); border-bottom: var(--side-nav-product-switcher-border); } + + .switcher-menu-item-icon { + height: 24px; + width: 24px; + } } .switcher-popover-arrow { diff --git a/app/components/side-nav/product-switcher/index.ts b/app/components/side-nav/product-switcher/index.ts index 6a1b70934..b43db153f 100644 --- a/app/components/side-nav/product-switcher/index.ts +++ b/app/components/side-nav/product-switcher/index.ts @@ -1,12 +1,25 @@ import Component from '@glimmer/component'; import { action } from '@ember/object'; import { tracked } from '@glimmer/tracking'; -import { inject as service } from '@ember/service'; +import { service } from '@ember/service'; import type IntlService from 'ember-intl/services/intl'; import styles from './index.scss'; -import type { SwitcherMenuItem } from '..'; import type ConfigurationService from 'irene/services/configuration'; +import type WhitelabelService from 'irene/services/whitelabel'; +import type OrganizationService from 'irene/services/organization'; + +interface SwitcherMenuItem { + id: string; + svg: + | 'ak-svg/sm-indicator' + | 'ak-svg/vapt-indicator' + | 'ak-svg/security-indicator'; + label: string; + route: string; + key: string; + openInNewTab?: boolean; +} export interface SideNavProductSwitcherSignature { Args: { @@ -23,6 +36,8 @@ export interface SideNavProductSwitcherSignature { export default class SideNavProductSwitcherComponent extends Component { @service declare intl: IntlService; @service declare configuration: ConfigurationService; + @service declare whitelabel: WhitelabelService; + @service declare organization: OrganizationService; @tracked anchorRef: HTMLElement | null = null; @@ -36,35 +51,53 @@ export default class SideNavProductSwitcherComponent extends Component item.key !== this.args.productSwitcherFilterKey - ); + (item) => item && item.key !== this.args.productSwitcherFilterKey + ) as SwitcherMenuItem[]; } @action onClickSwitcher(event: MouseEvent) { diff --git a/app/components/side-nav/security-menu-item/index.hbs b/app/components/side-nav/security-menu-item/index.hbs deleted file mode 100644 index 7800da3b4..000000000 --- a/app/components/side-nav/security-menu-item/index.hbs +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - {{#unless @isCollapsed}} - - - - - - {{/unless}} - - \ No newline at end of file diff --git a/app/components/side-nav/security-menu-item/index.ts b/app/components/side-nav/security-menu-item/index.ts deleted file mode 100644 index 66eab357d..000000000 --- a/app/components/side-nav/security-menu-item/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -import Component from '@glimmer/component'; - -export interface SideNavSecurityMenuItemSignature { - Args: { - isCollapsed: boolean; - classes: { - menuItemText?: string; - menuItemLink?: string; - menuItemLinkActive?: string; - menuItemTooltip?: string; - }; - }; - Element: HTMLElement; -} - -export default class SideNavSecurityMenuItemComponent extends Component {} - -declare module '@glint/environment-ember-loose/registry' { - export default interface Registry { - 'SideNav::SecurityMenuItem': typeof SideNavSecurityMenuItemComponent; - 'side-nav/security-menu-item': typeof SideNavSecurityMenuItemComponent; - } -} diff --git a/app/components/storeknox-wrapper/index.ts b/app/components/storeknox-wrapper/index.ts index 96159200f..40888cc20 100644 --- a/app/components/storeknox-wrapper/index.ts +++ b/app/components/storeknox-wrapper/index.ts @@ -38,17 +38,19 @@ export default class StoreknoxWrapperComponent extends Component _)[0]; @@ -31,5 +43,7 @@ export default class OrganizationService extends Service { ENV.notifications ); } + + await this.setSecurityDashboardEnabled(); } } diff --git a/app/services/whitelabel.ts b/app/services/whitelabel.ts index 60a719b39..2bb778a98 100644 --- a/app/services/whitelabel.ts +++ b/app/services/whitelabel.ts @@ -70,7 +70,9 @@ export default class WhitelabelService extends Service { return this.configuration.imageData.logo_on_darkbg; } - get show_contact_support() { - return this.window.location.href.includes('secure.appknox.com'); + get is_appknox_url() { + const urls = ['secure.appknox.com']; + + return urls.some((url) => this.window.location.href.includes(url)); } } diff --git a/cypress/tests/auth.spec.ts b/cypress/tests/auth.spec.ts index ec937ee0a..a03c0b96b 100644 --- a/cypress/tests/auth.spec.ts +++ b/cypress/tests/auth.spec.ts @@ -147,7 +147,7 @@ describe('User Login', () => { // Logs user to dashboard via API loginActions.loginWithCredAndSaveSession({ username, password }); - cy.visit('/'); + cy.visit(APPLICATION_ROUTES.projects); // Navigates to project listing route cy.url({ timeout: 15000 }).should('include', APPLICATION_ROUTES.projects); diff --git a/tests/acceptance/home-page-test.js b/tests/acceptance/home-page-test.js index e1713d9f9..54c90880e 100644 --- a/tests/acceptance/home-page-test.js +++ b/tests/acceptance/home-page-test.js @@ -1,10 +1,11 @@ import { module, test } from 'qunit'; -import { click, currentURL, visit } from '@ember/test-helpers'; +import { click, currentURL, findAll, visit } from '@ember/test-helpers'; import { setupMirage } from 'ember-cli-mirage/test-support'; import { t } from 'ember-intl/test-support'; import { setupApplicationTest } from 'ember-qunit'; import Service from '@ember/service'; +import { Response } from 'miragejs'; import { setupRequiredEndpoints } from '../helpers/acceptance-utils'; @@ -67,7 +68,7 @@ module('Acceptance | home page', function (hooks) { .hasText(t('logout')); assert.dom('[data-test-home-page-product-card]').exists({ - count: 2, + count: 3, }); }); @@ -75,17 +76,18 @@ module('Acceptance | home page', function (hooks) { await visit('/dashboard/home'); assert.dom('[data-test-home-page-product-card]').exists({ - count: 2, + count: 3, }); - assert.dom('[data-test-home-page-product-card-title]').exists({ count: 2 }); + assert.dom('[data-test-home-page-product-card-title]').exists({ count: 3 }); const titles = this.element.querySelectorAll( '[data-test-home-page-product-card-title]' ); - assert.strictEqual(titles[0].textContent.trim(), t('appknox')); - assert.strictEqual(titles[1].textContent.trim(), t('storeknox')); + assert.strictEqual(titles[0].textContent.trim(), t('vapt')); + assert.strictEqual(titles[1].textContent.trim(), t('appMonitoring')); + assert.strictEqual(titles[2].textContent.trim(), t('securityDashboard')); const links = this.element.querySelectorAll( '[data-test-home-page-product-card-link]' @@ -93,7 +95,7 @@ module('Acceptance | home page', function (hooks) { assert .dom('[data-test-home-page-product-card-indicator-icon]') - .exists({ count: 2 }); + .exists({ count: 3 }); await click(links[0]); @@ -108,7 +110,7 @@ module('Acceptance | home page', function (hooks) { await visit('/dashboard/home'); assert.dom('[data-test-home-page-product-card]').exists({ - count: 2, + count: 3, }); const links = this.element.querySelectorAll( @@ -117,24 +119,28 @@ module('Acceptance | home page', function (hooks) { assert .dom('[data-test-home-page-product-card-indicator-icon]') - .exists({ count: 2 }); + .exists({ count: 3 }); await click(links[1]); assert.strictEqual( currentURL(), - '/dashboard/storeknox/discover', + '/dashboard/storeknox/inventory/app-list', 'Redirected to storeknox' ); }); - test('it redirects to appknox dashboard if app monitoring is disabled', async function (assert) { + test('it redirects to appknox dashboard if app monitoring and security is disabled', async function (assert) { this.organization.update({ features: { storeknox: false, }, }); + this.server.get('/hudson-api/projects', () => { + return new Response(404); + }); + await visit('/dashboard/home'); assert.strictEqual( @@ -145,4 +151,56 @@ module('Acceptance | home page', function (hooks) { assert.dom('[data-test-side-menu-switcher]').doesNotExist(); }); + + test.each( + 'it should show right product cards', + [ + { storeknox: true, security: false }, + { storeknox: true, security: true }, + { storeknox: false, security: true }, + ], + async function (assert, products) { + this.server.get('/hudson-api/projects', () => { + return products.security ? new Response(200) : new Response(404); + }); + + this.organization.update({ + features: { + storeknox: products.storeknox, + }, + }); + + await visit('/dashboard/home'); + + if (products.security && products.storeknox) { + assert.dom('[data-test-home-page-product-card]').exists({ + count: 3, + }); + } else if (products.security && !products.storeknox) { + assert.dom('[data-test-home-page-product-card]').exists({ + count: 2, + }); + + const productTitles = findAll( + '[data-test-home-page-product-card-title]' + ); + + assert.dom(productTitles[0]).hasText(t('vapt')); + + assert.dom(productTitles[1]).hasText(t('securityDashboard')); + } else if (!products.security && products.storeknox) { + assert.dom('[data-test-home-page-product-card]').exists({ + count: 2, + }); + + const productTitles = findAll( + '[data-test-home-page-product-card-title]' + ); + + assert.dom(productTitles[0]).hasText(t('vapt')); + + assert.dom(productTitles[1]).hasText(t('appMonitoring')); + } + } + ); }); diff --git a/tests/acceptance/side-nav-test.js b/tests/acceptance/side-nav-test.js index 40cb22aa4..609c896c1 100644 --- a/tests/acceptance/side-nav-test.js +++ b/tests/acceptance/side-nav-test.js @@ -1,10 +1,12 @@ import { module, test } from 'qunit'; -import { click, currentURL, visit } from '@ember/test-helpers'; +import { click, currentURL, findAll, visit } from '@ember/test-helpers'; import { setupMirage } from 'ember-cli-mirage/test-support'; import { setupApplicationTest } from 'ember-qunit'; import Service from '@ember/service'; import { setupBrowserFakes } from 'ember-browser-services/test-support'; +import { t } from 'ember-intl/test-support'; +import { Response } from 'miragejs'; import { setupRequiredEndpoints } from '../helpers/acceptance-utils'; @@ -122,14 +124,14 @@ module('Acceptance | side nav test', function (hooks) { 'it should switch between VAPT and Store Monitoring', [ { - expectedUrl: '/dashboard/storeknox/discover', + expectedUrl: '/dashboard/storeknox/inventory/app-list', visitUrl: '/dashboard/projects', icon: 'sm-svg', }, { expectedUrl: '/dashboard/projects', - visitUrl: '/dashboard/storeknox/discover', - icon: 'vp-svg', + visitUrl: '/dashboard/storeknox/inventory/app-list', + icon: 'vapt-svg', }, ], @@ -157,4 +159,59 @@ module('Acceptance | side nav test', function (hooks) { assert.strictEqual(currentURL(), details.expectedUrl); } ); + + test.each( + 'it should show product switcher menu items', + [ + { storeknox: true, security: false }, + { storeknox: true, security: true }, + { storeknox: false, security: true }, + { storeknox: false, security: false }, + ], + async function (assert, products) { + this.server.get('/hudson-api/projects', () => { + return products.security ? new Response(200) : new Response(404); + }); + + this.organization.update({ + features: { + storeknox: products.storeknox, + }, + }); + + await visit('/dashboard/projects'); + + if (!products.security && !products.storeknox) { + assert.dom('[data-test-side-menu-switcher]').doesNotExist(); + } else { + assert.dom('[data-test-side-menu-switcher]').exists(); + + await click('[data-test-side-menu-switcher]'); + + assert.dom('[data-test-side-menu-switcher-modal]').exists(); + + if (products.security && products.storeknox) { + assert + .dom('[data-test-switcher-popover-item-link]') + .exists({ count: 2 }); + + const items = findAll('[data-test-switcher-popover-item-link]'); + + assert.dom(items[0]).hasText(t('appMonitoring')); + + assert.dom(items[1]).hasText(t('securityDashboard')); + } else if (products.storeknox && !products.security) { + assert + .dom('[data-test-switcher-popover-item-link]') + .exists({ count: 1 }) + .hasText(t('appMonitoring')); + } else if (!products.storeknox && products.security) { + assert + .dom('[data-test-switcher-popover-item-link]') + .exists({ count: 1 }) + .hasText(t('securityDashboard')); + } + } + } + ); }); diff --git a/tests/integration/components/appknox-wrapper-test.js b/tests/integration/components/appknox-wrapper-test.js index 9f091bbad..9a6514624 100644 --- a/tests/integration/components/appknox-wrapper-test.js +++ b/tests/integration/components/appknox-wrapper-test.js @@ -56,7 +56,6 @@ const menuItems = ({ market, billing, partner, - security, }) => [ { @@ -78,7 +77,6 @@ const menuItems = ({ hasBadge: true, badgeLabel: t('beta'), }, - security && { label: t('securityDashboard'), icon: 'security' }, ].filter(Boolean); const sections = (enabled) => ({ @@ -86,7 +84,6 @@ const sections = (enabled) => ({ appMonitoring: enabled, market: enabled, partner: enabled, - security: enabled, sbom: enabled, publicApis: enabled, analytics: enabled, @@ -296,14 +293,6 @@ module('Integration | Component | appknox-wrapper', function (hooks) { sbom: sectionConfig.sbom, }; - this.server.get('/hudson-api/projects', () => { - if (sectionConfig.security) { - return new Response(200); - } else { - return new Response(404); - } - }); - await render(hbs``); assert.dom('[data-test-img-logo]').exists(); diff --git a/tests/integration/components/public-api-docs-test.js b/tests/integration/components/public-api-docs-test.js index ef05a0453..e89e7935a 100644 --- a/tests/integration/components/public-api-docs-test.js +++ b/tests/integration/components/public-api-docs-test.js @@ -137,6 +137,12 @@ module('Integration | Component | public-api-docs', function (hooks) { hbs`` ); + await waitUntil(() => { + return find( + '[data-test-publicApiDocs-apis-container]' + ).textContent.includes(this.apiPathName); + }); + assert .dom('[data-test-publicApiDocs-apis-container]') .exists() @@ -147,6 +153,12 @@ module('Integration | Component | public-api-docs', function (hooks) { test('it renders schemas', async function (assert) { await render(hbs``); + await waitUntil(() => { + return find( + '[data-test-publicApiDocs-schemas-container]' + ).textContent.includes(this.schemaName); + }); + assert .dom('[data-test-publicApiDocs-schemas-container]') .exists() diff --git a/tests/integration/components/storeknox-wrapper-test.js b/tests/integration/components/storeknox-wrapper-test.js index 4dc7f4242..3505d657e 100644 --- a/tests/integration/components/storeknox-wrapper-test.js +++ b/tests/integration/components/storeknox-wrapper-test.js @@ -4,7 +4,7 @@ import { setupMirage } from 'ember-cli-mirage/test-support'; import { setupIntl, t } from 'ember-intl/test-support'; import { click, find, findAll, render } from '@ember/test-helpers'; import { hbs } from 'ember-cli-htmlbars'; - +import { setupBrowserFakes } from 'ember-browser-services/test-support'; import Service from '@ember/service'; class NotificationsStub extends Service { @@ -42,20 +42,21 @@ class IntegrationStub extends Service { } const storeknoxMenuItems = [ - { - label: () => t('discovery'), - icon: 'search', - }, { label: () => t('inventory'), icon: 'inventory-2', }, + { + label: () => t('discovery'), + icon: 'search', + }, ].filter(Boolean); module('Integration | Component | storeknox-wrapper', function (hooks) { setupRenderingTest(hooks); setupMirage(hooks); setupIntl(hooks, 'en'); + setupBrowserFakes(hooks, { window: true, localStorage: true }); hooks.beforeEach(async function () { this.server.createList('organization', 1); @@ -81,6 +82,10 @@ module('Integration | Component | storeknox-wrapper', function (hooks) { const organization = this.owner.lookup('service:organization'); + const window = this.owner.lookup('service:browser/window'); + + window.localStorage.setItem('sidebarState', 'expanded'); + this.setProperties({ title: t('storeknox'), organization: organization, @@ -129,12 +134,6 @@ module('Integration | Component | storeknox-wrapper', function (hooks) { assert.dom('[data-test-side-lower-menu-divider]').exists(); - const expandButton = find( - `[data-test-side-lower-menu-item="${t('expand')}"]` - ); - - await click(expandButton); - storeknoxMenuItems.forEach((it, index) => { assert .dom('[data-test-side-menu-item-text]', menuItemEle[index]) diff --git a/translations/en.json b/translations/en.json index f83177e6f..7b1633c2a 100644 --- a/translations/en.json +++ b/translations/en.json @@ -1380,6 +1380,7 @@ "searchTeamByName": "Search by team name", "security": "Security", "securityDashboard": "Security Dashboard", + "securityDashboardDesc": "For security researchers to perform manual assessments (PT)", "selectAnyTeam": "Please select any team", "selectThePath": "Select the path", "selectDevice": "Select the device", diff --git a/translations/ja.json b/translations/ja.json index 8fd2dfc9c..301ca6290 100644 --- a/translations/ja.json +++ b/translations/ja.json @@ -1380,6 +1380,7 @@ "searchTeamByName": "Search by team name", "security": "セキュリティ", "securityDashboard": "Security Dashboard", + "securityDashboardDesc": "For security researchers to perform manual assessments (PT)", "selectAnyTeam": "チームを選択してください", "selectThePath": "Select the path", "selectDevice": "デバイスを選択する", diff --git a/types/ak-svg.d.ts b/types/ak-svg.d.ts index c9e5bfb41..97a46e64b 100644 --- a/types/ak-svg.d.ts +++ b/types/ak-svg.d.ts @@ -44,9 +44,10 @@ export enum AkSvgComponentInvocationByNames { ToggleAutomatedDast, AppknoxBgImg, StoreknoxBgImg, - ConfigurationBgImg, - VpIndicator, + SecurityBgImg, + VaptIndicator, SmIndicator, + SecurityIndicator, } export enum AkSvgComponentInvocationByPaths {