Skip to content

Commit

Permalink
feat: ACI Notification Banners (#23256)
Browse files Browse the repository at this point in the history
  • Loading branch information
mike-plummer authored Aug 16, 2022
1 parent 19dd523 commit 7412548
Show file tree
Hide file tree
Showing 28 changed files with 885 additions and 31 deletions.
2 changes: 2 additions & 0 deletions packages/app/cypress/component/support/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/// <reference path="../../../../frontend-shared/cypress/support/component.ts" />
import '../../../../frontend-shared/cypress/support/component.ts'
import { registerMountFn } from '@packages/frontend-shared/cypress/support/common'
// ***********************************************************
// This example support/index.ts is processed and
Expand Down
9 changes: 1 addition & 8 deletions packages/app/cypress/e2e/specs_list_flaky.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,7 @@ describe('App: Spec List - Flaky Indicator', () => {

cy.remoteGraphQLIntercept(async (obj) => {
await new Promise((r) => setTimeout(r, 20))
if (obj.result.data && 'cloudProjectBySlug' in obj.result.data) {
obj.result.data.cloudProjectBySlug = {
__typename: 'CloudProject',
retrievedAt: new Date().toISOString(),
id: `id${obj.variables.slug}`,
projectId: 'abc123',
}
} else if (obj.result.data && 'cloudSpecByPath' in obj.result.data) {
if (obj.result.data && 'cloudSpecByPath' in obj.result.data) {
if (obj.variables.specPath.includes('123.spec.js')) {
obj.result.data.cloudSpecByPath = {
__typename: 'CloudProjectSpec',
Expand Down
2 changes: 1 addition & 1 deletion packages/app/cypress/e2e/specs_list_latest_runs.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ describe('App/Cloud Integration - Latest runs and Average duration', { viewportW
cy.get(averageDurationSelector('accounts_new.spec.js')).contains('2:03')
})

it('lazily loads data for off-screen specs', () => {
it('lazily loads data for off-screen specs', { viewportHeight: 500 }, () => {
// make sure the virtualized list didn't load z008.spec.js
cy.get(specRowSelector('z008.spec.js')).should('not.exist')

Expand Down
2 changes: 2 additions & 0 deletions packages/app/cypress/e2e/top-nav.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,7 @@ describe('Growth Prompts Can Open Automatically', () => {
firstOpened: 1609459200000,
lastOpened: 1609459200000,
promptsShown: {},
banners: { _disabled: true },
})
},
)
Expand All @@ -672,6 +673,7 @@ describe('Growth Prompts Can Open Automatically', () => {
firstOpened: 1609459200000,
lastOpened: 1609459200000,
promptsShown: { ci1: 1609459200000 },
banners: { _disabled: true },
})
},
)
Expand Down
167 changes: 166 additions & 1 deletion packages/app/src/specs/SpecsListBanners.cy.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import SpecsListBanners from './SpecsListBanners.vue'
import { ref } from 'vue'
import type { Ref } from 'vue'
import { SpecsListBannersFragmentDoc } from '../generated/graphql-test'
import { SpecsListBannersFragment, SpecsListBannersFragmentDoc } from '../generated/graphql-test'
import interval from 'human-interval'
import { CloudUserStubs, CloudProjectStubs } from '@packages/graphql/test/stubCloudTypes'
import { AllowedState, BannerIds } from '@packages/types'
import { assignIn, set } from 'lodash'

const AlertSelector = 'alert-header'
const AlertCloseBtnSelector = 'alert-suffix-icon'

type BannerKey = keyof typeof BannerIds
type BannerId = typeof BannerIds[BannerKey]

describe('<SpecsListBanners />', () => {
const validateBaseRender = () => {
it('should render as expected', () => {
Expand Down Expand Up @@ -48,6 +55,75 @@ describe('<SpecsListBanners />', () => {
})
}

const stateWithFirstOpenedDaysAgo = (days: number) => {
return {
firstOpened: Date.now() - interval(`${days} days`),
}
}

const mountWithState = (query: Partial<SpecsListBannersFragment>, state?: Partial<AllowedState>, props?: object) => {
cy.mountFragment(SpecsListBannersFragmentDoc, {
onResult: (result) => {
assignIn(result, query)
set(result, 'currentProject.savedState', state)
},
render: (gql) => <SpecsListBanners gql={gql} {...props} />,
})
}

const validateSmartNotificationBehaviors = (bannerId: BannerId, bannerTestId: string, gql: Partial<SpecsListBannersFragment>) => {
it('should not render when using cypress < 4 days', () => {
mountWithState(gql, stateWithFirstOpenedDaysAgo(3))

cy.get(`[data-cy="${bannerTestId}"]`).should('not.exist')
})

it('should not render when previously-dismissed', () => {
mountWithState(gql, {
...stateWithFirstOpenedDaysAgo(4),
banners: {
[bannerId]: {
dismissed: Date.now(),
},
},
})

cy.get(`[data-cy="${bannerTestId}"]`).should('not.exist')
})

context('banner conditions are met and when cypress use >= 4 days', () => {
it('should render when not previously-dismissed', () => {
mountWithState(gql, stateWithFirstOpenedDaysAgo(4))
cy.get(`[data-cy="${bannerTestId}"]`).should('be.visible')
})

it('should be preempted by spec not found banner', () => {
mountWithState(gql, stateWithFirstOpenedDaysAgo(4), { isSpecNotFound: true })
cy.get(`[data-cy="${bannerTestId}"]`).should('not.exist')
})

it('should be preempted by offline warning banner', () => {
mountWithState(gql, stateWithFirstOpenedDaysAgo(4), { isOffline: true })
cy.get(`[data-cy="${bannerTestId}"]`).should('not.exist')
})

it('should be preempted by fetch error banner', () => {
mountWithState(gql, stateWithFirstOpenedDaysAgo(4), { isFetchError: true })
cy.get(`[data-cy="${bannerTestId}"]`).should('not.exist')
})

it('should be preempted by project not found banner', () => {
mountWithState(gql, stateWithFirstOpenedDaysAgo(4), { isProjectNotFound: true })
cy.get(`[data-cy="${bannerTestId}"]`).should('not.exist')
})

it('should be preempted by request access banner', () => {
mountWithState(gql, stateWithFirstOpenedDaysAgo(4), { isProjectUnauthorized: true })
cy.get(`[data-cy="${bannerTestId}"]`).should('not.exist')
})
})
}

describe('spec not found', () => {
const visible: any = ref(true)

Expand Down Expand Up @@ -141,6 +217,7 @@ describe('<SpecsListBanners />', () => {
message: 'test',
hasRequestedAccess: false,
},
savedState: {},
}
},
render: (gql) => <SpecsListBanners gql={gql} isProjectUnauthorized={visible} />,
Expand Down Expand Up @@ -170,6 +247,7 @@ describe('<SpecsListBanners />', () => {
message: 'test',
hasRequestedAccess: true,
},
savedState: {},
}
},
render: (gql) => <SpecsListBanners gql={gql} isProjectUnauthorized={visible} hasRequestedAccess />,
Expand All @@ -181,4 +259,91 @@ describe('<SpecsListBanners />', () => {
validateCloseOnPropChange(visible)
validateReopenOnPropChange(visible)
})

describe('login', () => {
const gql: Partial<SpecsListBannersFragment> = {
cloudViewer: null,
cachedUser: null,
currentProject: {
__typename: 'CurrentProject',
id: 'abc123',
} as any,
}

validateSmartNotificationBehaviors(BannerIds.ACI_082022_LOGIN, 'login-banner', gql)
})

describe('create organization', () => {
const gql: Partial<SpecsListBannersFragment> = {
cloudViewer: {
...CloudUserStubs.me,
firstOrganization: {
__typename: 'CloudOrganizationConnection',
nodes: [],
},
},
currentProject: {
__typename: 'CurrentProject',
id: 'abc123',
} as any,
}

beforeEach(() => {
cy.gqlStub.Query.cloudViewer = gql.cloudViewer as any
})

validateSmartNotificationBehaviors(BannerIds.ACI_082022_CREATE_ORG, 'create-organization-banner', gql)
})

describe('connect project', () => {
const gql: Partial<SpecsListBannersFragment> = {
cloudViewer: {
...CloudUserStubs.me,
firstOrganization: {
__typename: 'CloudOrganizationConnection',
nodes: [{ __typename: 'CloudOrganization', id: '987' }],
},
},
currentProject: {
__typename: 'CurrentProject',
id: 'abc123',
projectId: null,
} as any,
}

validateSmartNotificationBehaviors(BannerIds.ACI_082022_CONNECT_PROJECT, 'connect-project-banner', gql)
})

describe('record', () => {
const gql: Partial<SpecsListBannersFragment> = {
cloudViewer: {
...CloudUserStubs.me,
firstOrganization: {
__typename: 'CloudOrganizationConnection',
nodes: [{ __typename: 'CloudOrganization', id: '987' }],
},
},
currentProject: {
__typename: 'CurrentProject',
id: 'abc123',
title: 'my-test-project',
currentTestingType: 'component',
projectId: 'abcd',
cloudProject: {
...CloudProjectStubs.componentProject,
runs: {
__typename: 'CloudRunConnection',
nodes: [],
},
},
} as any,
}

beforeEach(() => {
cy.gqlStub.Query.currentProject = gql.currentProject as any
cy.gqlStub.Query.cloudViewer = gql.cloudViewer as any
})

validateSmartNotificationBehaviors(BannerIds.ACI_082022_RECORD, 'record-banner', gql)
})
})
Loading

5 comments on commit 7412548

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 7412548 Aug 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the linux x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.7.0/linux-x64/develop-741254803fb567a2371f6d26c7de5386f127fb39/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 7412548 Aug 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the linux arm64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.7.0/linux-arm64/develop-741254803fb567a2371f6d26c7de5386f127fb39/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 7412548 Aug 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the darwin arm64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.7.0/darwin-arm64/develop-741254803fb567a2371f6d26c7de5386f127fb39/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 7412548 Aug 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the darwin x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.7.0/darwin-x64/develop-741254803fb567a2371f6d26c7de5386f127fb39/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 7412548 Aug 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the win32 x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.7.0/win32-x64/develop-741254803fb567a2371f6d26c7de5386f127fb39/cypress.tgz

Please sign in to comment.