* 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>
		
			
				
	
	
		
			199 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			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',
 | 
						|
        })
 | 
						|
      })
 | 
						|
    })
 | 
						|
  })
 | 
						|
})
 |