Make settings reset button only reset current level (#3855)

* Update test to expect new behavior (failing)

* Update behavior to match new test expectations

* Make reset button more clear

* Fix eslint issue

* Fix up separate test that relied on old reset logic
This commit is contained in:
Frank Noirot
2024-09-11 09:39:10 -04:00
committed by GitHub
parent a00800bddc
commit 292f89859f
3 changed files with 96 additions and 70 deletions

View File

@ -8,7 +8,7 @@ import {
tearDown, tearDown,
executorInputPath, executorInputPath,
} from './test-utils' } from './test-utils'
import { SaveSettingsPayload } from 'lib/settings/settingsTypes' import { SaveSettingsPayload, SettingsLevel } from 'lib/settings/settingsTypes'
import { TEST_SETTINGS_KEY, TEST_SETTINGS_CORRUPTED } from './storageStates' import { TEST_SETTINGS_KEY, TEST_SETTINGS_CORRUPTED } from './storageStates'
import * as TOML from '@iarna/toml' import * as TOML from '@iarna/toml'
@ -154,16 +154,17 @@ test.describe('Testing settings', () => {
test('Project and user settings can be reset', async ({ page }) => { test('Project and user settings can be reset', async ({ page }) => {
const u = await getUtils(page) const u = await getUtils(page)
await test.step(`Setup`, async () => {
await page.setViewportSize({ width: 1200, height: 500 }) await page.setViewportSize({ width: 1200, height: 500 })
await u.waitForAuthSkipAppStart() await u.waitForAuthSkipAppStart()
await page })
.getByRole('button', { name: 'Start Sketch' })
.waitFor({ state: 'visible' })
// Selectors and constants
const projectSettingsTab = page.getByRole('radio', { name: 'Project' }) const projectSettingsTab = page.getByRole('radio', { name: 'Project' })
const userSettingsTab = page.getByRole('radio', { name: 'User' }) const userSettingsTab = page.getByRole('radio', { name: 'User' })
const resetButton = page.getByRole('button', { const resetButton = (level: SettingsLevel) =>
name: 'Restore default settings', page.getByRole('button', {
name: `Reset ${level}-level settings`,
}) })
const themeColorSetting = page.locator('#themeColor').getByRole('slider') const themeColorSetting = page.locator('#themeColor').getByRole('slider')
const settingValues = { const settingValues = {
@ -171,12 +172,15 @@ test.describe('Testing settings', () => {
user: '120', user: '120',
project: '50', project: '50',
} }
const resetToast = (level: SettingsLevel) =>
page.getByText(`${level}-level settings were reset`)
// Open the settings modal with lower-right button await test.step(`Open the settings modal`, async () => {
await page.getByRole('link', { name: 'Settings' }).last().click() await page.getByRole('link', { name: 'Settings' }).last().click()
await expect( await expect(
page.getByRole('heading', { name: 'Settings', exact: true }) page.getByRole('heading', { name: 'Settings', exact: true })
).toBeVisible() ).toBeVisible()
})
await test.step('Set up theme color', async () => { await test.step('Set up theme color', async () => {
// Verify we're looking at the project-level settings, // Verify we're looking at the project-level settings,
@ -195,37 +199,40 @@ test.describe('Testing settings', () => {
await test.step('Reset project settings', async () => { await test.step('Reset project settings', async () => {
// Click the reset settings button. // Click the reset settings button.
await resetButton.click() await resetButton('project').click()
await expect(page.getByText('Settings restored to default')).toBeVisible() await expect(resetToast('project')).toBeVisible()
await expect( await expect(resetToast('project')).not.toBeVisible()
page.getByText('Settings restored to default')
).not.toBeVisible()
// Verify it is now set to the inherited user value // Verify it is now set to the inherited user value
await expect(themeColorSetting).toHaveValue(settingValues.default) await expect(themeColorSetting).toHaveValue(settingValues.user)
// Check that the user setting also rolled back await test.step(`Check that the user settings did not change`, async () => {
await userSettingsTab.click() await userSettingsTab.click()
await expect(themeColorSetting).toHaveValue(settingValues.default) await expect(themeColorSetting).toHaveValue(settingValues.user)
await projectSettingsTab.click() })
// Set project-level value to 50 again to test the user-level reset await test.step(`Set project-level again to test the user-level reset`, async () => {
await projectSettingsTab.click()
await themeColorSetting.fill(settingValues.project) await themeColorSetting.fill(settingValues.project)
await userSettingsTab.click() await userSettingsTab.click()
}) })
})
await test.step('Reset user settings', async () => { await test.step('Reset user settings', async () => {
// Change the setting and click the reset settings button. // Click the reset settings button.
await themeColorSetting.fill(settingValues.user) await resetButton('user').click()
await resetButton.click()
await expect(resetToast('user')).toBeVisible()
await expect(resetToast('user')).not.toBeVisible()
// Verify it is now set to the default value // Verify it is now set to the default value
await expect(themeColorSetting).toHaveValue(settingValues.default) await expect(themeColorSetting).toHaveValue(settingValues.default)
// Check that the project setting also changed await test.step(`Check that the project settings did not change`, async () => {
await projectSettingsTab.click() await projectSettingsTab.click()
await expect(themeColorSetting).toHaveValue(settingValues.default) await expect(themeColorSetting).toHaveValue(settingValues.project)
})
}) })
}) })
@ -429,25 +436,37 @@ test.describe('Testing settings', () => {
test('Changing modeling default unit', async ({ page }) => { test('Changing modeling default unit', async ({ page }) => {
const u = await getUtils(page) const u = await getUtils(page)
await test.step(`Test setup`, async () => {
await page.setViewportSize({ width: 1200, height: 500 }) await page.setViewportSize({ width: 1200, height: 500 })
await u.waitForAuthSkipAppStart() await u.waitForAuthSkipAppStart()
await page await page
.getByRole('button', { name: 'Start Sketch' }) .getByRole('button', { name: 'Start Sketch' })
.waitFor({ state: 'visible' }) .waitFor({ state: 'visible' })
})
// Selectors and constants
const userSettingsTab = page.getByRole('radio', { name: 'User' }) const userSettingsTab = page.getByRole('radio', { name: 'User' })
const projectSettingsTab = page.getByRole('radio', { name: 'Project' })
const defaultUnitSection = page.getByText(
'default unitRoll back default unitRoll back to match'
)
const defaultUnitRollbackButton = page.getByRole('button', {
name: 'Roll back default unit',
})
// Open the settings modal with lower-right button await test.step(`Open the settings modal`, async () => {
await page.getByRole('link', { name: 'Settings' }).last().click() await page.getByRole('link', { name: 'Settings' }).last().click()
await expect( await expect(
page.getByRole('heading', { name: 'Settings', exact: true }) page.getByRole('heading', { name: 'Settings', exact: true })
).toBeVisible() ).toBeVisible()
const resetButton = page.getByRole('button', {
name: 'Restore default settings',
}) })
// Default unit should be mm
await resetButton.click() await test.step(`Reset unit setting`, async () => {
await userSettingsTab.click()
await defaultUnitSection.hover()
await defaultUnitRollbackButton.click()
await projectSettingsTab.click()
})
await test.step('Change modeling default unit within project tab', async () => { await test.step('Change modeling default unit within project tab', async () => {
const changeUnitOfMeasureInProjectTab = async (unitOfMeasure: string) => { const changeUnitOfMeasureInProjectTab = async (unitOfMeasure: string) => {

View File

@ -12,7 +12,6 @@ import { useLocation, useNavigate } from 'react-router-dom'
import { isDesktop } from 'lib/isDesktop' import { isDesktop } from 'lib/isDesktop'
import { ActionButton } from 'components/ActionButton' import { ActionButton } from 'components/ActionButton'
import { SettingsFieldInput } from './SettingsFieldInput' import { SettingsFieldInput } from './SettingsFieldInput'
import { getInitialDefaultDir } from 'lib/desktop'
import toast from 'react-hot-toast' import toast from 'react-hot-toast'
import { APP_VERSION } from 'routes/Settings' import { APP_VERSION } from 'routes/Settings'
import { PATHS } from 'lib/paths' import { PATHS } from 'lib/paths'
@ -214,14 +213,15 @@ export const AllSettingsFields = forwardRef(
)} )}
<ActionButton <ActionButton
Element="button" Element="button"
onClick={toSync(async () => { onClick={() => {
const defaultDirectory = await getInitialDefaultDir()
send({ send({
type: 'Reset settings', type: 'Reset settings',
defaultDirectory, level: searchParamTab,
}) })
toast.success('Settings restored to default') toast.success(
}, reportRejection)} `Your ${searchParamTab}-level settings were reset`
)
}}
iconStart={{ iconStart={{
icon: 'refresh', icon: 'refresh',
size: 'sm', size: 'sm',
@ -229,7 +229,7 @@ export const AllSettingsFields = forwardRef(
bgClassName: 'bg-destroy-70', bgClassName: 'bg-destroy-70',
}} }}
> >
Restore default settings Reset {searchParamTab}-level settings
</ActionButton> </ActionButton>
</div> </div>
</SettingsSection> </SettingsSection>

View File

@ -8,6 +8,11 @@ import {
SettingsPaths, SettingsPaths,
WildcardSetEvent, WildcardSetEvent,
} from 'lib/settings/settingsTypes' } from 'lib/settings/settingsTypes'
import {
configurationToSettingsPayload,
projectConfigurationToSettingsPayload,
setSettingsAtLevel,
} from 'lib/settings/settingsUtils'
export const settingsMachine = setup({ export const settingsMachine = setup({
types: { types: {
@ -24,7 +29,10 @@ export const settingsMachine = setup({
type: 'set.modeling.units' type: 'set.modeling.units'
data: { level: SettingsLevel; value: BaseUnit } data: { level: SettingsLevel; value: BaseUnit }
} }
| { type: 'Reset settings'; defaultDirectory: string } | {
type: 'Reset settings'
level: SettingsLevel
}
| { type: 'Set all settings'; settings: typeof settings }, | { type: 'Set all settings'; settings: typeof settings },
}, },
actions: { actions: {
@ -37,17 +45,16 @@ export const settingsMachine = setup({
setClientSideSceneUnits: () => {}, setClientSideSceneUnits: () => {},
persistSettings: () => {}, persistSettings: () => {},
resetSettings: assign(({ context, event }) => { resetSettings: assign(({ context, event }) => {
if (!('defaultDirectory' in event)) return {} if (!('level' in event)) return {}
// Reset everything except onboarding status,
// which should be preserved // Create a new, blank payload
const newSettings = createSettings() const newPayload =
if (context.app.onboardingStatus.user) { event.level === 'user'
newSettings.app.onboardingStatus.user = ? configurationToSettingsPayload({})
context.app.onboardingStatus.user : projectConfigurationToSettingsPayload({})
}
// We instead pass in the default directory since it's asynchronous // Reset the settings at that level
// to re-initialize, and that can be done by the caller. const newSettings = setSettingsAtLevel(context, event.level, newPayload)
newSettings.app.projectDirectory.default = event.defaultDirectory
return newSettings return newSettings
}), }),