Skip to content

Commit

Permalink
fix: correct invalid stored preference for in-app notifications (#27237)
Browse files Browse the repository at this point in the history
  • Loading branch information
warrensplayer authored Jul 7, 2023
1 parent c921fdf commit a3e4a8a
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 4 deletions.
1 change: 1 addition & 0 deletions cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ _Released 07/18/2023 (PENDING)_

**Bugfixes:**

- Fixed invalid stored preference when enabling in-app notifications that could cause the application to crash. Fixes [#27228](https://github.com/cypress-io/cypress/issues/27228).
- Fixed an issue with the Typescript types of [`cy.screenshot()`](https://docs.cypress.io/api/commands/screenshot). Fixed in [#27130](https://github.com/cypress-io/cypress/pull/27130).

## 12.17.0
Expand Down
11 changes: 9 additions & 2 deletions packages/app/src/settings/device/NotificationSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue'
import { computed, ref, watchEffect } from 'vue'
import { gql, useMutation } from '@urql/vue'
import { useI18n } from '@cy/i18n'
import Switch from '@packages/frontend-shared/src/components/Switch.vue'
Expand Down Expand Up @@ -157,7 +157,14 @@ const switches = [
},
]
const listRef = ref(props.gql.localSettings.preferences.notifyWhenRunCompletes)
const listRef = ref()
// allow for gql value to load when navigating straight here from EnableNotificationsBanner
watchEffect(() => {
if (!listRef.value) {
listRef.value = props.gql.localSettings.preferences.notifyWhenRunCompletes
}
})
const statuses = [
{ id: 'passed', label: t('settingsPage.notifications.passed') },
Expand Down
20 changes: 19 additions & 1 deletion packages/data-context/src/actions/LocalSettingsActions.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { AllowedState, defaultPreferences, Editor } from '@packages/types'
import { AllowedState, defaultPreferences, Editor, NotifyCompletionStatuses } from '@packages/types'
import pDefer from 'p-defer'
import _ from 'lodash'
import Debug from 'debug'

import type { DataContext } from '..'

const debug = Debug('cypress:data-context:actions:LocalSettingsActions')

export interface LocalSettingsApiShape {
getAvailableEditors(): Promise<Editor[]>

Expand Down Expand Up @@ -47,6 +50,8 @@ export class LocalSettingsActions {
return
}

debug('refresh local settings')

const dfd = pDefer<Editor[]>()

this.ctx.coreData.localSettings.refreshing = dfd.promise
Expand All @@ -60,6 +65,19 @@ export class LocalSettingsActions {
...(await this.ctx._apis.localSettingsApi.getPreferences()),
}

const preferences = this.ctx.coreData.localSettings.preferences

// Fix bad value for notifyWhenRunCompletes. See https://github.com/cypress-io/cypress/issues/27228
if (typeof preferences.notifyWhenRunCompletes === 'boolean') {
if (preferences.notifyWhenRunCompletes === true) {
preferences.notifyWhenRunCompletes = [...NotifyCompletionStatuses]
} else {
preferences.notifyWhenRunCompletes = []
}

await this.ctx._apis.localSettingsApi.setPreferences(preferences)
}

dfd.resolve()
}
}
2 changes: 2 additions & 0 deletions packages/data-context/src/sources/VersionsDataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ export class VersionsDataSource {
return pkg.version
}

debug('#getLatestVersion')

const preferences = await this.ctx.localSettingsApi.getPreferences()
const notificationPreferences: ('started' | 'failing' | 'passed' | 'failed' | 'cancelled' | 'errored')[] = [
...preferences.notifyWhenRunCompletes ?? [],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { expect } from 'chai'
import sinon from 'sinon'
import { LocalSettingsActions } from '../../../src/actions/LocalSettingsActions'
import { createTestDataContext } from '../helper'
import type { DataContext } from '../../../src'
import { NotifyCompletionStatuses } from '@packages/types'

describe('LocalSettingsActions', () => {
let ctx: DataContext
let actions: LocalSettingsActions

beforeEach(() => {
sinon.restore()

ctx = createTestDataContext('open')

actions = new LocalSettingsActions(ctx)
})

context('refreshLocalSettings', () => {
context('notifyWhenRunCompletes', () => {
it('should fix false value', async () => {
ctx._apis.localSettingsApi.getPreferences = sinon.stub().resolves({
//@ts-ignore
notifyWhenRunCompletes: false,
})

await actions.refreshLocalSettings()

expect(ctx.coreData.localSettings.preferences.notifyWhenRunCompletes).to.eql([])
})

it('should fix true value', async () => {
ctx._apis.localSettingsApi.getPreferences = sinon.stub().resolves({
//@ts-ignore
notifyWhenRunCompletes: true,
})

await actions.refreshLocalSettings()

expect(ctx.coreData.localSettings.preferences.notifyWhenRunCompletes).to.eql([...NotifyCompletionStatuses])
})

it('should leave value alone if value is an array', async () => {
ctx._apis.localSettingsApi.getPreferences = sinon.stub().resolves({
//@ts-ignore
notifyWhenRunCompletes: ['errored'],
})

await actions.refreshLocalSettings()

expect(ctx.coreData.localSettings.preferences.notifyWhenRunCompletes).to.eql(['errored'])
})

it('should pass through default value if not set ', async () => {
ctx._apis.localSettingsApi.getPreferences = sinon.stub().resolves({})

await actions.refreshLocalSettings()

expect(ctx.coreData.localSettings.preferences.notifyWhenRunCompletes).to.eql(['failed'])
})
})
})
})
2 changes: 2 additions & 0 deletions packages/data-context/test/unit/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ export function createTestDataContext (mode: DataContextConfig['mode'] = 'run',
majorVersionWelcomeDismissed: { [MAJOR_VERSION_FOR_CONTENT]: 123456 },
notifyWhenRunCompletes: ['failed'],
}),
getAvailableEditors: sinon.stub(),
setPreferences: sinon.stub(),
} as unknown as LocalSettingsApiShape,
authApi: {
logIn: sinon.stub().throws('not stubbed'),
Expand Down
4 changes: 3 additions & 1 deletion packages/types/src/preferences.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type { BannersState, Editor, MajorVersionWelcomeDismissed } from '.'

export type NotifyWhenRunCompletes = 'passed' | 'failed' | 'cancelled' | 'errored'
export const NotifyCompletionStatuses = ['passed', 'failed', 'cancelled', 'errored'] as const

export type NotifyWhenRunCompletes = typeof NotifyCompletionStatuses[number]

export const defaultPreferences: AllowedState = {
autoScrollingEnabled: true,
Expand Down

5 comments on commit a3e4a8a

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on a3e4a8a Jul 7, 2023

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 build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/12.17.1/linux-arm64/develop-a3e4a8a6067531ffcb1f85598bee9e3d69810fd1/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on a3e4a8a Jul 7, 2023

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 build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/12.17.1/linux-x64/develop-a3e4a8a6067531ffcb1f85598bee9e3d69810fd1/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on a3e4a8a Jul 7, 2023

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 build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/12.17.1/darwin-arm64/develop-a3e4a8a6067531ffcb1f85598bee9e3d69810fd1/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on a3e4a8a Jul 7, 2023

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 build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/12.17.1/darwin-x64/develop-a3e4a8a6067531ffcb1f85598bee9e3d69810fd1/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on a3e4a8a Jul 7, 2023

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 build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/12.17.1/win32-x64/develop-a3e4a8a6067531ffcb1f85598bee9e3d69810fd1/cypress.tgz

Please sign in to comment.