Files
modeling-app/e2e/playwright/onboarding-tests.spec.ts
Frank Noirot 3b7b4f85a1 Update onboarding to V1 browser and desktop flows (#6714)
* Remove unused `telemetryLoader`

* Remove onboarding redirect behavior

* Allow subRoute to be passed to navigateToProject

* Replace warning dialog routes with toasts

* Wire up new utilities and toasts to UI components

* Add home sidebar buttons for tutorial flow

* Rename menu item

* Add flex-1 so home-layout fills available space

* Remove onboarding avatar tests, they are becoming irrelevant

* Consolidate onboarding tests to one longer one

and update it to not use pixel color checks, and use fixtures.

* Shorten warning toast button text

* tsc, lint, and circular deps

* Update circular dep file

* Fix mistakes made in circular update tweaking

* One more dumb created circular dep

* Update src/routes/Onboarding/utils.tsx

Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>

* Fix narrow screen home layout breaking

* fix: kevin, navigation routes fixed

* fix: filename parsing is correct now for onboarding with the last file sep

* Fix e2e test state checks that are diff on Linux

* Create onboarding project entirely through systemIOMachine

* Fix Windows path construction

* Make utility to verify a string is an onboarding value

* Little biome formatting suggestion fix

* Units onboarding step was not using OnboardingButtons

* Add type checking of next and previous status, fix useNextClick

* Update `OnboardingStatus` type on WASM side

* Make onboarding different on browser and web, placeholder component

* Show proof of concept with custom content per route

* Make text type args not insta dismiss when you click anywhere

* Make some utility hooks for the onboarding

* Update requestedProjectName along with requestedProjectName

* Build out a rough draft of desktop onboarding

* Remove unused onboarding route files

* Build out rough draft of browser onboarding content

* @jgomez720 browser flow feedback

* @jgomez420 desktop feedback

* tsc and lints

* Tweaks

* Import is dead, long live Add files

* What's up with my inability to type "highlight"?

* Codespell and String casting

* Update browser sample to be axial fan

* lint and tsc

* codespell again

* Remove unused nightmare function `useDemoCode`

* Add a few unit tests

* Update desktop to use bulk file creation from #6747

* Oops overwrote main.kcl on the modify with text-to-cad step

* Undo the dumb use of `sep` that I introduced

* Fix up project test

which was fragile to the number of steps in the onboarding smh

* Fix up onboarding flow test

* typo

---------

Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
2025-05-09 00:37:21 +00:00

199 lines
7.1 KiB
TypeScript

import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Onboarding tests', () => {
test('Desktop onboarding flow works', async ({
page,
homePage,
toolbar,
editor,
scene,
tronApp,
}) => {
if (!tronApp) {
fail()
}
// Because our default test settings have the onboardingStatus set to 'dismissed',
// we must set it to empty for the tests where we want to see the onboarding UI.
await tronApp.cleanProjectDir({
app: {
onboarding_status: '',
},
})
const tutorialWelcomeHeading = page.getByText(
'Welcome to Zoo Design Studio'
)
const nextButton = page.getByTestId('onboarding-next')
const prevButton = page.getByTestId('onboarding-prev')
const userMenuButton = toolbar.userSidebarButton
const userMenuSettingsButton = page.getByRole('button', {
name: 'User settings',
})
const settingsHeading = page.getByRole('heading', {
name: 'Settings',
exact: true,
})
const restartOnboardingSettingsButton = page.getByRole('button', {
name: 'Replay onboarding',
})
const helpMenuButton = page.getByRole('button', {
name: 'Help and resources',
})
const helpMenuRestartOnboardingButton = page.getByRole('button', {
name: 'Replay onboarding tutorial',
})
const postDismissToast = page.getByText(
'Click the question mark in the lower-right corner if you ever want to redo the tutorial!'
)
await test.step('Test initial home page view, showing a tutorial button', async () => {
await expect(homePage.tutorialBtn).toBeVisible()
await homePage.expectState({
projectCards: [],
sortBy: 'last-modified-desc',
})
})
await test.step('Create a blank project and verify no onboarding chrome is shown', async () => {
await homePage.goToModelingScene()
await expect(toolbar.projectName).toContainText('testDefault')
await expect(tutorialWelcomeHeading).not.toBeVisible()
await editor.expectEditor.toContain('@settings(defaultLengthUnit = in)', {
shouldNormalise: true,
})
await scene.connectionEstablished()
await expect(toolbar.startSketchBtn).toBeEnabled({ timeout: 15_000 })
})
await test.step('Go home and verify we still see the tutorial button, then begin it.', async () => {
await toolbar.logoLink.click()
await expect(homePage.tutorialBtn).toBeVisible()
await homePage.expectState({
projectCards: [
{
title: 'testDefault',
fileCount: 1,
},
],
sortBy: 'last-modified-desc',
})
await homePage.tutorialBtn.click()
})
// This is web-only.
// TODO: write a new test just for the onboarding in browser
// await test.step('Ensure the onboarding request toast appears', async () => {
// await expect(page.getByTestId('onboarding-toast')).toBeVisible()
// await page.getByTestId('onboarding-next').click()
// })
await test.step('Ensure we see the welcome screen in a new project', async () => {
await expect(toolbar.projectName).toContainText('tutorial-project')
await expect(tutorialWelcomeHeading).toBeVisible()
await scene.connectionEstablished()
await expect(toolbar.startSketchBtn).toBeEnabled({ timeout: 15_000 })
})
await test.step('Test the clicking through the onboarding flow', async () => {
await test.step('Going forward', async () => {
while ((await nextButton.innerText()) !== 'Finish') {
await nextButton.hover()
await nextButton.click()
}
})
await test.step('Going backward', async () => {
while ((await prevButton.innerText()) !== 'Dismiss') {
await prevButton.hover()
await prevButton.click()
}
})
// Dismiss the onboarding
await test.step('Dismiss the onboarding', async () => {
await prevButton.hover()
await prevButton.click()
await expect(page.getByTestId('onboarding-content')).not.toBeVisible()
await expect(postDismissToast).toBeVisible()
await expect.poll(() => page.url()).not.toContain('/onboarding')
})
})
await test.step('Resetting onboarding from inside project should always overwrite `tutorial-project`', async () => {
await test.step('Reset onboarding from settings', async () => {
await userMenuButton.click()
await userMenuSettingsButton.click()
await expect(settingsHeading).toBeVisible()
await expect(restartOnboardingSettingsButton).toBeVisible()
await restartOnboardingSettingsButton.click()
})
await test.step('Gets to the onboarding start', async () => {
await expect(toolbar.projectName).toContainText('tutorial-project')
await expect(tutorialWelcomeHeading).toBeVisible()
await scene.connectionEstablished()
await expect(toolbar.startSketchBtn).toBeEnabled({ timeout: 15_000 })
})
await test.step('Dismiss the onboarding', async () => {
await postDismissToast.waitFor({ state: 'hidden' })
await page.keyboard.press('Escape')
await expect(postDismissToast).toBeVisible()
await expect(page.getByTestId('onboarding-content')).not.toBeVisible()
await expect.poll(() => page.url()).not.toContain('/onboarding')
})
await test.step('Verify no new projects were created', async () => {
await toolbar.logoLink.click()
await expect(homePage.tutorialBtn).not.toBeVisible()
await homePage.expectState({
projectCards: [
{ title: 'tutorial-project', fileCount: 7 },
{
title: 'testDefault',
fileCount: 1,
},
],
sortBy: 'last-modified-desc',
})
})
})
await test.step('Resetting onboarding from home help menu overwrites the `tutorial-project`', async () => {
await helpMenuButton.click()
await helpMenuRestartOnboardingButton.click()
await test.step('Gets to the onboarding start', async () => {
await expect(toolbar.projectName).toContainText('tutorial-project')
await expect(tutorialWelcomeHeading).toBeVisible()
await scene.connectionEstablished()
await expect(toolbar.startSketchBtn).toBeEnabled({ timeout: 15_000 })
})
await test.step('Dismiss the onboarding', async () => {
await postDismissToast.waitFor({ state: 'hidden' })
await page.keyboard.press('Escape')
await expect(postDismissToast).toBeVisible()
await expect(page.getByTestId('onboarding-content')).not.toBeVisible()
await expect.poll(() => page.url()).not.toContain('/onboarding')
})
await test.step('Verify no new projects were created', async () => {
await toolbar.logoLink.click()
await expect(homePage.tutorialBtn).not.toBeVisible()
await homePage.expectState({
projectCards: [
{ title: 'tutorial-project', fileCount: 7 },
{
title: 'testDefault',
fileCount: 1,
},
],
sortBy: 'last-modified-desc',
})
})
})
})
})