Franknoirot/onboarding avatar text (#2726)
* Add failing playwright test * Fix the problem to get the test passing * Give the avatar button a tooltip too
This commit is contained in:
@ -18,6 +18,7 @@ import {
|
|||||||
TEST_SETTINGS_ONBOARDING_EXPORT,
|
TEST_SETTINGS_ONBOARDING_EXPORT,
|
||||||
TEST_SETTINGS_ONBOARDING_START,
|
TEST_SETTINGS_ONBOARDING_START,
|
||||||
TEST_CODE_GIZMO,
|
TEST_CODE_GIZMO,
|
||||||
|
TEST_SETTINGS_ONBOARDING_USER_MENU,
|
||||||
} from './storageStates'
|
} from './storageStates'
|
||||||
import * as TOML from '@iarna/toml'
|
import * as TOML from '@iarna/toml'
|
||||||
import { LineInputsType } from 'lang/std/sketchcombos'
|
import { LineInputsType } from 'lang/std/sketchcombos'
|
||||||
@ -1394,6 +1395,54 @@ test.describe('Onboarding tests', () => {
|
|||||||
await page.locator('[data-testid="onboarding-next"]').click()
|
await page.locator('[data-testid="onboarding-next"]').click()
|
||||||
await expect(page.locator('.cm-content')).toHaveText(/.+/)
|
await expect(page.locator('.cm-content')).toHaveText(/.+/)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('Avatar text updates depending on image load success', async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
// Override beforeEach test setup
|
||||||
|
await page.addInitScript(
|
||||||
|
async ({ settingsKey, settings }) => {
|
||||||
|
localStorage.setItem(settingsKey, settings)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
settingsKey: TEST_SETTINGS_KEY,
|
||||||
|
settings: TOML.stringify({
|
||||||
|
settings: TEST_SETTINGS_ONBOARDING_USER_MENU,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
await page.setViewportSize({ width: 1200, height: 1080 })
|
||||||
|
await page.goto('/')
|
||||||
|
await page.waitForURL('**/file/**', { waitUntil: 'domcontentloaded' })
|
||||||
|
|
||||||
|
// Test that the text in this step is correct
|
||||||
|
const avatarLocator = page.getByTestId('user-sidebar-toggle').locator('img')
|
||||||
|
const onboardingOverlayLocator = page
|
||||||
|
.getByTestId('onboarding-content')
|
||||||
|
.locator('div')
|
||||||
|
.nth(1)
|
||||||
|
|
||||||
|
// Expect the avatar to be visible and for the text to reference it
|
||||||
|
await expect(avatarLocator).toBeVisible()
|
||||||
|
await expect(onboardingOverlayLocator).toBeVisible()
|
||||||
|
await expect(onboardingOverlayLocator).toContainText('your avatar')
|
||||||
|
|
||||||
|
await page.route('https://lh3.googleusercontent.com/**', async (route) => {
|
||||||
|
await route.fulfill({
|
||||||
|
status: 404,
|
||||||
|
contentType: 'text/plain',
|
||||||
|
body: 'Not Found!',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
await page.reload({ waitUntil: 'domcontentloaded' })
|
||||||
|
|
||||||
|
// Now expect the text to be different
|
||||||
|
await expect(avatarLocator).not.toBeVisible()
|
||||||
|
await expect(onboardingOverlayLocator).toBeVisible()
|
||||||
|
await expect(onboardingOverlayLocator).toContainText('the menu button')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test.describe('Testing selections', () => {
|
test.describe('Testing selections', () => {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { SaveSettingsPayload } from 'lib/settings/settingsTypes'
|
import { SaveSettingsPayload } from 'lib/settings/settingsTypes'
|
||||||
import { Themes } from 'lib/theme'
|
import { Themes } from 'lib/theme'
|
||||||
|
import { onboardingPaths } from 'routes/Onboarding/paths'
|
||||||
|
|
||||||
export const TEST_SETTINGS_KEY = '/settings.toml'
|
export const TEST_SETTINGS_KEY = '/settings.toml'
|
||||||
export const TEST_SETTINGS = {
|
export const TEST_SETTINGS = {
|
||||||
@ -22,9 +23,14 @@ export const TEST_SETTINGS = {
|
|||||||
},
|
},
|
||||||
} satisfies Partial<SaveSettingsPayload>
|
} satisfies Partial<SaveSettingsPayload>
|
||||||
|
|
||||||
|
export const TEST_SETTINGS_ONBOARDING_USER_MENU = {
|
||||||
|
...TEST_SETTINGS,
|
||||||
|
app: { ...TEST_SETTINGS.app, onboardingStatus: onboardingPaths.USER_MENU },
|
||||||
|
} satisfies Partial<SaveSettingsPayload>
|
||||||
|
|
||||||
export const TEST_SETTINGS_ONBOARDING_EXPORT = {
|
export const TEST_SETTINGS_ONBOARDING_EXPORT = {
|
||||||
...TEST_SETTINGS,
|
...TEST_SETTINGS,
|
||||||
app: { ...TEST_SETTINGS.app, onboardingStatus: '/export' },
|
app: { ...TEST_SETTINGS.app, onboardingStatus: onboardingPaths.EXPORT },
|
||||||
} satisfies Partial<SaveSettingsPayload>
|
} satisfies Partial<SaveSettingsPayload>
|
||||||
|
|
||||||
export const TEST_SETTINGS_ONBOARDING_START = {
|
export const TEST_SETTINGS_ONBOARDING_START = {
|
||||||
|
@ -39,7 +39,7 @@ const UserSidebarMenu = ({ user }: { user?: User }) => {
|
|||||||
<Popover className="relative">
|
<Popover className="relative">
|
||||||
{user?.image && !imageLoadFailed ? (
|
{user?.image && !imageLoadFailed ? (
|
||||||
<Popover.Button
|
<Popover.Button
|
||||||
className="border-0 rounded-full w-fit min-w-max p-0 group"
|
className="relative border-0 rounded-full w-fit min-w-max p-0 group"
|
||||||
data-testid="user-sidebar-toggle"
|
data-testid="user-sidebar-toggle"
|
||||||
>
|
>
|
||||||
<div className="rounded-full border overflow-hidden">
|
<div className="rounded-full border overflow-hidden">
|
||||||
@ -51,6 +51,9 @@ const UserSidebarMenu = ({ user }: { user?: User }) => {
|
|||||||
onError={() => setImageLoadFailed(true)}
|
onError={() => setImageLoadFailed(true)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<Tooltip position="bottom-right" delay={1000}>
|
||||||
|
User menu
|
||||||
|
</Tooltip>
|
||||||
</Popover.Button>
|
</Popover.Button>
|
||||||
) : (
|
) : (
|
||||||
<ActionButton
|
<ActionButton
|
||||||
@ -59,7 +62,7 @@ const UserSidebarMenu = ({ user }: { user?: User }) => {
|
|||||||
className="border-transparent !px-0"
|
className="border-transparent !px-0"
|
||||||
data-testid="user-sidebar-toggle"
|
data-testid="user-sidebar-toggle"
|
||||||
>
|
>
|
||||||
<Tooltip position="left" delay={1000}>
|
<Tooltip position="bottom-right" delay={1000}>
|
||||||
User menu
|
User menu
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { OnboardingButtons, useDismiss, useNextClick } from '.'
|
import { OnboardingButtons, useDismiss, useNextClick } from '.'
|
||||||
import { onboardingPaths } from 'routes/Onboarding/paths'
|
import { onboardingPaths } from 'routes/Onboarding/paths'
|
||||||
import { useStore } from '../../useStore'
|
import { useStore } from '../../useStore'
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
|
||||||
export default function UserMenu() {
|
export default function UserMenu() {
|
||||||
const { buttonDownInStream } = useStore((s) => ({
|
const { buttonDownInStream } = useStore((s) => ({
|
||||||
@ -8,6 +9,20 @@ export default function UserMenu() {
|
|||||||
}))
|
}))
|
||||||
const dismiss = useDismiss()
|
const dismiss = useDismiss()
|
||||||
const next = useNextClick(onboardingPaths.PROJECT_MENU)
|
const next = useNextClick(onboardingPaths.PROJECT_MENU)
|
||||||
|
const [avatarErrored, setAvatarErrored] = useState(false)
|
||||||
|
const buttonDescription = !avatarErrored ? 'your avatar' : 'the menu button'
|
||||||
|
|
||||||
|
// Set up error handling for the user's avatar image,
|
||||||
|
// so the onboarding text can be updated if it fails to load.
|
||||||
|
useEffect(() => {
|
||||||
|
const element = globalThis.document.querySelector(
|
||||||
|
'[data-testid="user-sidebar-toggle"] img'
|
||||||
|
)
|
||||||
|
|
||||||
|
if (element?.tagName === 'IMG') {
|
||||||
|
element.addEventListener('error', () => setAvatarErrored(true))
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed grid justify-center items-start inset-0 z-50 pointer-events-none">
|
<div className="fixed grid justify-center items-start inset-0 z-50 pointer-events-none">
|
||||||
@ -20,8 +35,8 @@ export default function UserMenu() {
|
|||||||
<section className="flex-1">
|
<section className="flex-1">
|
||||||
<h2 className="text-2xl font-bold">User Menu</h2>
|
<h2 className="text-2xl font-bold">User Menu</h2>
|
||||||
<p className="my-4">
|
<p className="my-4">
|
||||||
Click your avatar on the upper right to open the user menu. You can
|
Click {buttonDescription} in the upper right to open the user menu.
|
||||||
change your settings, sign out, or request a feature.
|
You can change your settings, sign out, or request a feature.
|
||||||
</p>
|
</p>
|
||||||
<p className="my-4">
|
<p className="my-4">
|
||||||
We only support global settings at the moment, but we are working to
|
We only support global settings at the moment, but we are working to
|
||||||
|
Reference in New Issue
Block a user