Pass onboarding tests
This commit is contained in:
@ -26,8 +26,7 @@ test(
|
|||||||
),
|
),
|
||||||
])
|
])
|
||||||
}),
|
}),
|
||||||
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
|
||||||
|
|
||||||
page.on('console', console.log)
|
page.on('console', console.log)
|
||||||
|
|
||||||
@ -87,7 +86,10 @@ test(
|
|||||||
await expect(successToastMessage).toBeVisible()
|
await expect(successToastMessage).toBeVisible()
|
||||||
await expect(exportingToastMessage).not.toBeVisible()
|
await expect(exportingToastMessage).not.toBeVisible()
|
||||||
|
|
||||||
const firstFileFullPath = path.resolve(getPlaywrightDownloadDir(page), exportFileName)
|
const firstFileFullPath = path.resolve(
|
||||||
|
getPlaywrightDownloadDir(page),
|
||||||
|
exportFileName
|
||||||
|
)
|
||||||
await test.step('Check the export size', async () => {
|
await test.step('Check the export size', async () => {
|
||||||
await expect
|
await expect
|
||||||
.poll(
|
.poll(
|
||||||
@ -162,7 +164,10 @@ test(
|
|||||||
expect(exportingToastMessage).not.toBeVisible(),
|
expect(exportingToastMessage).not.toBeVisible(),
|
||||||
]))
|
]))
|
||||||
|
|
||||||
const secondFileFullPath = path.resolve(getPlaywrightDownloadDir(page), exportFileName)
|
const secondFileFullPath = path.resolve(
|
||||||
|
getPlaywrightDownloadDir(page),
|
||||||
|
exportFileName
|
||||||
|
)
|
||||||
await test.step('Check the export size', async () => {
|
await test.step('Check the export size', async () => {
|
||||||
await expect
|
await expect
|
||||||
.poll(
|
.poll(
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,7 @@
|
|||||||
import { test, expect } from './zoo-test'
|
import { test, expect } from './zoo-test'
|
||||||
import * as fsp from 'fs/promises'
|
import * as fsp from 'fs/promises'
|
||||||
import * as fs from 'fs'
|
import * as fs from 'fs'
|
||||||
import {
|
import { createProject, executorInputPath, getUtils } from './test-utils'
|
||||||
createProject,
|
|
||||||
executorInputPath,
|
|
||||||
getUtils,
|
|
||||||
} from './test-utils'
|
|
||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
import { FILE_EXT } from 'lib/constants'
|
import { FILE_EXT } from 'lib/constants'
|
||||||
|
|
||||||
@ -127,9 +123,7 @@ test.describe('when using the file tree to', () => {
|
|||||||
const settingsOpenButton = page.getByRole('link', {
|
const settingsOpenButton = page.getByRole('link', {
|
||||||
name: 'settings Settings',
|
name: 'settings Settings',
|
||||||
})
|
})
|
||||||
const settingsCloseButton = page.getByTestId(
|
const settingsCloseButton = page.getByTestId('settings-close-button')
|
||||||
'settings-close-button'
|
|
||||||
)
|
|
||||||
await settingsOpenButton.click()
|
await settingsOpenButton.click()
|
||||||
await settingsCloseButton.click()
|
await settingsCloseButton.click()
|
||||||
})
|
})
|
||||||
@ -168,10 +162,7 @@ test.describe('when using the file tree to', () => {
|
|||||||
test(
|
test(
|
||||||
'create a new file with the same name as an existing file cancels the operation',
|
'create a new file with the same name as an existing file cancels the operation',
|
||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
async (
|
async ({ context, page, homePage, scene, editor, toolbar }, testInfo) => {
|
||||||
{ context, page, homePage, scene, editor, toolbar },
|
|
||||||
testInfo
|
|
||||||
) => {
|
|
||||||
const projectName = 'cube'
|
const projectName = 'cube'
|
||||||
const mainFile = 'main.kcl'
|
const mainFile = 'main.kcl'
|
||||||
const secondFile = 'cylinder.kcl'
|
const secondFile = 'cylinder.kcl'
|
||||||
@ -578,20 +569,17 @@ test.describe('Renaming in the file tree', () => {
|
|||||||
await page.keyboard.press('Enter')
|
await page.keyboard.press('Enter')
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step(
|
await test.step('Verify the folder is renamed, and no navigation occurred', async () => {
|
||||||
'Verify the folder is renamed, and no navigation occurred',
|
const url = page.url()
|
||||||
async () => {
|
expect(url).toContain('main.kcl')
|
||||||
const url = page.url()
|
expect(url).not.toContain('folderToRename')
|
||||||
expect(url).toContain('main.kcl')
|
|
||||||
expect(url).not.toContain('folderToRename')
|
|
||||||
|
|
||||||
await expect(projectMenuButton).toContainText('main.kcl')
|
await expect(projectMenuButton).toContainText('main.kcl')
|
||||||
await expect(renamedFolder).toBeVisible()
|
await expect(renamedFolder).toBeVisible()
|
||||||
await expect(folderToRename).not.toBeAttached()
|
await expect(folderToRename).not.toBeAttached()
|
||||||
expect(checkUnRenamedFolderFS()).toBeFalsy()
|
expect(checkUnRenamedFolderFS()).toBeFalsy()
|
||||||
expect(checkRenamedFolderFS()).toBeTruthy()
|
expect(checkRenamedFolderFS()).toBeTruthy()
|
||||||
}
|
})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -676,26 +664,23 @@ test.describe('Renaming in the file tree', () => {
|
|||||||
await page.keyboard.press('Enter')
|
await page.keyboard.press('Enter')
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step(
|
await test.step('Verify the folder is renamed, and navigated to new path', async () => {
|
||||||
'Verify the folder is renamed, and navigated to new path',
|
const urlSnippet = encodeURIComponent(
|
||||||
async () => {
|
join(newFolderName, 'someFileWithin.kcl')
|
||||||
const urlSnippet = encodeURIComponent(
|
)
|
||||||
join(newFolderName, 'someFileWithin.kcl')
|
await page.waitForURL(new RegExp(urlSnippet))
|
||||||
)
|
await expect(projectMenuButton).toContainText('someFileWithin.kcl')
|
||||||
await page.waitForURL(new RegExp(urlSnippet))
|
await expect(renamedFolder).toBeVisible()
|
||||||
await expect(projectMenuButton).toContainText('someFileWithin.kcl')
|
await expect(folderToRename).not.toBeAttached()
|
||||||
await expect(renamedFolder).toBeVisible()
|
|
||||||
await expect(folderToRename).not.toBeAttached()
|
|
||||||
|
|
||||||
// URL is synchronous, so we check the other stuff first
|
// URL is synchronous, so we check the other stuff first
|
||||||
const url = page.url()
|
const url = page.url()
|
||||||
expect(url).not.toContain('main.kcl')
|
expect(url).not.toContain('main.kcl')
|
||||||
expect(url).toContain(newFolderName)
|
expect(url).toContain(newFolderName)
|
||||||
expect(url).toContain('someFileWithin.kcl')
|
expect(url).toContain('someFileWithin.kcl')
|
||||||
expect(checkUnRenamedFolderFS()).toBeFalsy()
|
expect(checkUnRenamedFolderFS()).toBeFalsy()
|
||||||
expect(checkRenamedFolderFS()).toBeTruthy()
|
expect(checkRenamedFolderFS()).toBeTruthy()
|
||||||
}
|
})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@ -730,20 +715,17 @@ test.describe('Deleting items from the file pane', () => {
|
|||||||
const deleteMenuItem = page.getByRole('button', { name: 'Delete' })
|
const deleteMenuItem = page.getByRole('button', { name: 'Delete' })
|
||||||
const deleteConfirmation = page.getByTestId('delete-confirmation')
|
const deleteConfirmation = page.getByTestId('delete-confirmation')
|
||||||
|
|
||||||
await test.step(
|
await test.step('Open project and navigate to fileToDelete.kcl', async () => {
|
||||||
'Open project and navigate to fileToDelete.kcl',
|
await projectCard.click()
|
||||||
async () => {
|
await u.waitForPageLoad()
|
||||||
await projectCard.click()
|
await u.openFilePanel()
|
||||||
await u.waitForPageLoad()
|
|
||||||
await u.openFilePanel()
|
|
||||||
|
|
||||||
await fileToDelete.click()
|
await fileToDelete.click()
|
||||||
await u.waitForPageLoad()
|
await u.waitForPageLoad()
|
||||||
await u.openKclCodePanel()
|
await u.openKclCodePanel()
|
||||||
await expect(u.codeLocator).toContainText('getOppositeEdge(thing)')
|
await expect(u.codeLocator).toContainText('getOppositeEdge(thing)')
|
||||||
await u.closeKclCodePanel()
|
await u.closeKclCodePanel()
|
||||||
}
|
})
|
||||||
)
|
|
||||||
|
|
||||||
await test.step('Delete fileToDelete.kcl', async () => {
|
await test.step('Delete fileToDelete.kcl', async () => {
|
||||||
await fileToDelete.click({ button: 'right' })
|
await fileToDelete.click({ button: 'right' })
|
||||||
@ -857,21 +839,18 @@ test.describe('Deleting items from the file pane', () => {
|
|||||||
const deleteMenuItem = page.getByRole('button', { name: 'Delete' })
|
const deleteMenuItem = page.getByRole('button', { name: 'Delete' })
|
||||||
const deleteConfirmation = page.getByTestId('delete-confirmation')
|
const deleteConfirmation = page.getByTestId('delete-confirmation')
|
||||||
|
|
||||||
await test.step(
|
await test.step('Open project and navigate into folderToDelete', async () => {
|
||||||
'Open project and navigate into folderToDelete',
|
await projectCard.click()
|
||||||
async () => {
|
await u.waitForPageLoad()
|
||||||
await projectCard.click()
|
await expect(projectMenuButton).toContainText('main.kcl')
|
||||||
await u.waitForPageLoad()
|
await u.closeKclCodePanel()
|
||||||
await expect(projectMenuButton).toContainText('main.kcl')
|
await u.openFilePanel()
|
||||||
await u.closeKclCodePanel()
|
|
||||||
await u.openFilePanel()
|
|
||||||
|
|
||||||
await folderToDelete.click()
|
await folderToDelete.click()
|
||||||
await expect(fileWithinFolder).toBeVisible()
|
await expect(fileWithinFolder).toBeVisible()
|
||||||
await fileWithinFolder.click()
|
await fileWithinFolder.click()
|
||||||
await expect(projectMenuButton).toContainText('someFileWithin.kcl')
|
await expect(projectMenuButton).toContainText('someFileWithin.kcl')
|
||||||
}
|
})
|
||||||
)
|
|
||||||
|
|
||||||
await test.step('Delete folderToDelete', async () => {
|
await test.step('Delete folderToDelete', async () => {
|
||||||
await folderToDelete.click({ button: 'right' })
|
await folderToDelete.click({ button: 'right' })
|
||||||
@ -881,21 +860,15 @@ test.describe('Deleting items from the file pane', () => {
|
|||||||
await deleteConfirmation.click()
|
await deleteConfirmation.click()
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step(
|
await test.step('Check deletion and navigation to main.kcl', async () => {
|
||||||
'Check deletion and navigation to main.kcl',
|
await expect(folderToDelete).not.toBeAttached()
|
||||||
async () => {
|
await expect(fileWithinFolder).not.toBeAttached()
|
||||||
await expect(folderToDelete).not.toBeAttached()
|
await expect(projectMenuButton).toContainText('main.kcl')
|
||||||
await expect(fileWithinFolder).not.toBeAttached()
|
})
|
||||||
await expect(projectMenuButton).toContainText('main.kcl')
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
test.fixme(
|
test.fixme('TODO - delete folder we are in, with no main.kcl', async () => {})
|
||||||
'TODO - delete folder we are in, with no main.kcl',
|
|
||||||
async () => {}
|
|
||||||
)
|
|
||||||
|
|
||||||
// Copied from tests above.
|
// Copied from tests above.
|
||||||
test(
|
test(
|
||||||
@ -903,20 +876,22 @@ test.describe('Deleting items from the file pane', () => {
|
|||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page }, testInfo) => {
|
||||||
const TEST_PROJECT_NAME = 'Test Project'
|
const TEST_PROJECT_NAME = 'Test Project'
|
||||||
const { dir: projectsDirName } = await context.folderSetupFn(async (dir) => {
|
const { dir: projectsDirName } = await context.folderSetupFn(
|
||||||
await fsp.mkdir(join(dir, TEST_PROJECT_NAME), { recursive: true })
|
async (dir) => {
|
||||||
await fsp.mkdir(join(dir, TEST_PROJECT_NAME, 'folderToDelete'), {
|
await fsp.mkdir(join(dir, TEST_PROJECT_NAME), { recursive: true })
|
||||||
recursive: true,
|
await fsp.mkdir(join(dir, TEST_PROJECT_NAME, 'folderToDelete'), {
|
||||||
})
|
recursive: true,
|
||||||
await fsp.copyFile(
|
})
|
||||||
executorInputPath('basic_fillet_cube_end.kcl'),
|
await fsp.copyFile(
|
||||||
join(dir, TEST_PROJECT_NAME, 'main.kcl')
|
executorInputPath('basic_fillet_cube_end.kcl'),
|
||||||
)
|
join(dir, TEST_PROJECT_NAME, 'main.kcl')
|
||||||
await fsp.copyFile(
|
)
|
||||||
executorInputPath('cylinder.kcl'),
|
await fsp.copyFile(
|
||||||
join(dir, TEST_PROJECT_NAME, 'folderToDelete', 'someFileWithin.kcl')
|
executorInputPath('cylinder.kcl'),
|
||||||
)
|
join(dir, TEST_PROJECT_NAME, 'folderToDelete', 'someFileWithin.kcl')
|
||||||
})
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
|
|
||||||
@ -930,33 +905,27 @@ test.describe('Deleting items from the file pane', () => {
|
|||||||
has: page.getByRole('button', { name: 'someFileWithin.kcl' }),
|
has: page.getByRole('button', { name: 'someFileWithin.kcl' }),
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step(
|
await test.step('Open project and navigate into folderToDelete', async () => {
|
||||||
'Open project and navigate into folderToDelete',
|
await projectCard.click()
|
||||||
async () => {
|
await u.waitForPageLoad()
|
||||||
await projectCard.click()
|
await expect(projectMenuButton).toContainText('main.kcl')
|
||||||
await u.waitForPageLoad()
|
await u.closeKclCodePanel()
|
||||||
await expect(projectMenuButton).toContainText('main.kcl')
|
await u.openFilePanel()
|
||||||
await u.closeKclCodePanel()
|
|
||||||
await u.openFilePanel()
|
|
||||||
|
|
||||||
await folderToDelete.click()
|
await folderToDelete.click()
|
||||||
await expect(fileWithinFolder).toBeVisible()
|
await expect(fileWithinFolder).toBeVisible()
|
||||||
await fileWithinFolder.click()
|
await fileWithinFolder.click()
|
||||||
await expect(projectMenuButton).toContainText('someFileWithin.kcl')
|
await expect(projectMenuButton).toContainText('someFileWithin.kcl')
|
||||||
}
|
})
|
||||||
)
|
|
||||||
|
|
||||||
// Point of divergence. Delete the project folder and see if it goes back
|
// Point of divergence. Delete the project folder and see if it goes back
|
||||||
// to the home view.
|
// to the home view.
|
||||||
await test.step(
|
await test.step('Delete projectsDirName/<project-name> externally', async () => {
|
||||||
'Delete projectsDirName/<project-name> externally',
|
await fsp.rm(join(projectsDirName, TEST_PROJECT_NAME), {
|
||||||
async () => {
|
recursive: true,
|
||||||
await fsp.rm(join(projectsDirName, TEST_PROJECT_NAME), {
|
force: true,
|
||||||
recursive: true,
|
})
|
||||||
force: true,
|
})
|
||||||
})
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
await test.step('Check the app is back on the home view', async () => {
|
await test.step('Check the app is back on the home view', async () => {
|
||||||
const projectsDirLink = page.getByText('Loaded from')
|
const projectsDirLink = page.getByText('Loaded from')
|
||||||
@ -971,20 +940,22 @@ test.describe('Deleting items from the file pane', () => {
|
|||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page }, testInfo) => {
|
||||||
const TEST_PROJECT_NAME = 'Test Project'
|
const TEST_PROJECT_NAME = 'Test Project'
|
||||||
const { dir: projectsDirName } = await context.folderSetupFn(async (dir) => {
|
const { dir: projectsDirName } = await context.folderSetupFn(
|
||||||
await fsp.mkdir(join(dir, TEST_PROJECT_NAME), { recursive: true })
|
async (dir) => {
|
||||||
await fsp.mkdir(join(dir, TEST_PROJECT_NAME, 'folderToDelete'), {
|
await fsp.mkdir(join(dir, TEST_PROJECT_NAME), { recursive: true })
|
||||||
recursive: true,
|
await fsp.mkdir(join(dir, TEST_PROJECT_NAME, 'folderToDelete'), {
|
||||||
})
|
recursive: true,
|
||||||
await fsp.copyFile(
|
})
|
||||||
executorInputPath('basic_fillet_cube_end.kcl'),
|
await fsp.copyFile(
|
||||||
join(dir, TEST_PROJECT_NAME, 'main.kcl')
|
executorInputPath('basic_fillet_cube_end.kcl'),
|
||||||
)
|
join(dir, TEST_PROJECT_NAME, 'main.kcl')
|
||||||
await fsp.copyFile(
|
)
|
||||||
executorInputPath('cylinder.kcl'),
|
await fsp.copyFile(
|
||||||
join(dir, TEST_PROJECT_NAME, 'folderToDelete', 'someFileWithin.kcl')
|
executorInputPath('cylinder.kcl'),
|
||||||
)
|
join(dir, TEST_PROJECT_NAME, 'folderToDelete', 'someFileWithin.kcl')
|
||||||
})
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
|
|
||||||
@ -998,35 +969,29 @@ test.describe('Deleting items from the file pane', () => {
|
|||||||
has: page.getByRole('button', { name: 'someFileWithin.kcl' }),
|
has: page.getByRole('button', { name: 'someFileWithin.kcl' }),
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step(
|
await test.step('Open project and navigate into folderToDelete', async () => {
|
||||||
'Open project and navigate into folderToDelete',
|
await projectCard.click()
|
||||||
async () => {
|
await u.waitForPageLoad()
|
||||||
await projectCard.click()
|
await expect(projectMenuButton).toContainText('main.kcl')
|
||||||
await u.waitForPageLoad()
|
|
||||||
await expect(projectMenuButton).toContainText('main.kcl')
|
|
||||||
|
|
||||||
await u.openFilePanel()
|
await u.openFilePanel()
|
||||||
|
|
||||||
await folderToDelete.click()
|
await folderToDelete.click()
|
||||||
await expect(fileWithinFolder).toBeVisible()
|
await expect(fileWithinFolder).toBeVisible()
|
||||||
await fileWithinFolder.click()
|
await fileWithinFolder.click()
|
||||||
await expect(projectMenuButton).toContainText('someFileWithin.kcl')
|
await expect(projectMenuButton).toContainText('someFileWithin.kcl')
|
||||||
}
|
})
|
||||||
)
|
|
||||||
|
|
||||||
await test.step(
|
await test.step('Delete projectsDirName/<project-name> externally', async () => {
|
||||||
'Delete projectsDirName/<project-name> externally',
|
await fsp.rm(
|
||||||
async () => {
|
join(
|
||||||
await fsp.rm(
|
projectsDirName,
|
||||||
join(
|
TEST_PROJECT_NAME,
|
||||||
projectsDirName,
|
'folderToDelete',
|
||||||
TEST_PROJECT_NAME,
|
'someFileWithin.kcl'
|
||||||
'folderToDelete',
|
|
||||||
'someFileWithin.kcl'
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
)
|
})
|
||||||
|
|
||||||
await test.step('Check the file is gone in the file tree', async () => {
|
await test.step('Check the file is gone in the file tree', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
@ -1034,194 +999,182 @@ test.describe('Deleting items from the file pane', () => {
|
|||||||
).not.toContainText('someFileWithin.kcl')
|
).not.toContainText('someFileWithin.kcl')
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step(
|
await test.step('Check the file is back in the file tree after typing in code editor', async () => {
|
||||||
'Check the file is back in the file tree after typing in code editor',
|
await u.pasteCodeInEditor('hello = 1')
|
||||||
async () => {
|
await expect(
|
||||||
await u.pasteCodeInEditor('hello = 1')
|
page.getByTestId('file-pane-scroll-container')
|
||||||
await expect(
|
).toContainText('someFileWithin.kcl')
|
||||||
page.getByTestId('file-pane-scroll-container')
|
})
|
||||||
).toContainText('someFileWithin.kcl')
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test.describe(
|
test.describe('Undo and redo do not keep history when navigating between files', () => {
|
||||||
'Undo and redo do not keep history when navigating between files',
|
test(
|
||||||
() => {
|
`open a file, change something, open a different file, hitting undo should do nothing`,
|
||||||
test(
|
{ tag: '@electron' },
|
||||||
`open a file, change something, open a different file, hitting undo should do nothing`,
|
async ({ context, page }, testInfo) => {
|
||||||
{ tag: '@electron' },
|
await context.folderSetupFn(async (dir) => {
|
||||||
async ({ context, page }, testInfo) => {
|
const testDir = join(dir, 'testProject')
|
||||||
await context.folderSetupFn(async (dir) => {
|
await fsp.mkdir(testDir, { recursive: true })
|
||||||
const testDir = join(dir, 'testProject')
|
await fsp.copyFile(
|
||||||
await fsp.mkdir(testDir, { recursive: true })
|
executorInputPath('cylinder.kcl'),
|
||||||
await fsp.copyFile(
|
join(testDir, 'main.kcl')
|
||||||
executorInputPath('cylinder.kcl'),
|
)
|
||||||
join(testDir, 'main.kcl')
|
await fsp.copyFile(
|
||||||
)
|
executorInputPath('basic_fillet_cube_end.kcl'),
|
||||||
await fsp.copyFile(
|
join(testDir, 'other.kcl')
|
||||||
executorInputPath('basic_fillet_cube_end.kcl'),
|
)
|
||||||
join(testDir, 'other.kcl')
|
})
|
||||||
)
|
const u = await getUtils(page)
|
||||||
})
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
const u = await getUtils(page)
|
page.on('console', console.log)
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
|
||||||
page.on('console', console.log)
|
|
||||||
|
|
||||||
// Constants and locators
|
// Constants and locators
|
||||||
const projectCard = page.getByText('testProject')
|
const projectCard = page.getByText('testProject')
|
||||||
const otherFile = page
|
const otherFile = page
|
||||||
.getByRole('listitem')
|
.getByRole('listitem')
|
||||||
.filter({ has: page.getByRole('button', { name: 'other.kcl' }) })
|
.filter({ has: page.getByRole('button', { name: 'other.kcl' }) })
|
||||||
|
|
||||||
await test.step(
|
await test.step('Open project and make a change to the file', async () => {
|
||||||
'Open project and make a change to the file',
|
await projectCard.click()
|
||||||
async () => {
|
await u.waitForPageLoad()
|
||||||
await projectCard.click()
|
|
||||||
await u.waitForPageLoad()
|
|
||||||
|
|
||||||
// Get the text in the code locator.
|
// Get the text in the code locator.
|
||||||
const originalText = await u.codeLocator.innerText()
|
const originalText = await u.codeLocator.innerText()
|
||||||
// Click in the editor and add some new lines.
|
// Click in the editor and add some new lines.
|
||||||
await u.codeLocator.click()
|
await u.codeLocator.click()
|
||||||
|
|
||||||
await page.keyboard.type(`sketch001 = startSketchOn('XY')
|
await page.keyboard.type(`sketch001 = startSketchOn('XY')
|
||||||
some other shit`)
|
some other shit`)
|
||||||
|
|
||||||
// Ensure the content in the editor changed.
|
// Ensure the content in the editor changed.
|
||||||
const newContent = await u.codeLocator.innerText()
|
const newContent = await u.codeLocator.innerText()
|
||||||
|
|
||||||
expect(originalText !== newContent)
|
expect(originalText !== newContent)
|
||||||
}
|
})
|
||||||
|
|
||||||
|
await test.step('navigate to other.kcl', async () => {
|
||||||
|
await u.openFilePanel()
|
||||||
|
|
||||||
|
await otherFile.click()
|
||||||
|
await u.waitForPageLoad()
|
||||||
|
await u.openKclCodePanel()
|
||||||
|
await expect(u.codeLocator).toContainText('getOppositeEdge(thing)')
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('hit undo', async () => {
|
||||||
|
// Get the original content of the file.
|
||||||
|
const originalText = await u.codeLocator.innerText()
|
||||||
|
// Now hit undo
|
||||||
|
await page.keyboard.down('ControlOrMeta')
|
||||||
|
await page.keyboard.press('KeyZ')
|
||||||
|
await page.keyboard.up('ControlOrMeta')
|
||||||
|
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
await expect(u.codeLocator).toContainText(originalText)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
test(
|
||||||
|
`open a file, change something, undo it, open a different file, hitting redo should do nothing`,
|
||||||
|
{ tag: '@electron' },
|
||||||
|
// Skip on windows i think the keybindings are different for redo.
|
||||||
|
async ({ context, page }, testInfo) => {
|
||||||
|
await context.folderSetupFn(async (dir) => {
|
||||||
|
const testDir = join(dir, 'testProject')
|
||||||
|
await fsp.mkdir(testDir, { recursive: true })
|
||||||
|
await fsp.copyFile(
|
||||||
|
executorInputPath('cylinder.kcl'),
|
||||||
|
join(testDir, 'main.kcl')
|
||||||
)
|
)
|
||||||
|
await fsp.copyFile(
|
||||||
await test.step('navigate to other.kcl', async () => {
|
executorInputPath('basic_fillet_cube_end.kcl'),
|
||||||
await u.openFilePanel()
|
join(testDir, 'other.kcl')
|
||||||
|
|
||||||
await otherFile.click()
|
|
||||||
await u.waitForPageLoad()
|
|
||||||
await u.openKclCodePanel()
|
|
||||||
await expect(u.codeLocator).toContainText('getOppositeEdge(thing)')
|
|
||||||
})
|
|
||||||
|
|
||||||
await test.step('hit undo', async () => {
|
|
||||||
// Get the original content of the file.
|
|
||||||
const originalText = await u.codeLocator.innerText()
|
|
||||||
// Now hit undo
|
|
||||||
await page.keyboard.down('ControlOrMeta')
|
|
||||||
await page.keyboard.press('KeyZ')
|
|
||||||
await page.keyboard.up('ControlOrMeta')
|
|
||||||
|
|
||||||
await page.waitForTimeout(100)
|
|
||||||
await expect(u.codeLocator).toContainText(originalText)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
test(
|
|
||||||
`open a file, change something, undo it, open a different file, hitting redo should do nothing`,
|
|
||||||
{ tag: '@electron' },
|
|
||||||
// Skip on windows i think the keybindings are different for redo.
|
|
||||||
async ({ context, page }, testInfo) => {
|
|
||||||
await context.folderSetupFn(async (dir) => {
|
|
||||||
const testDir = join(dir, 'testProject')
|
|
||||||
await fsp.mkdir(testDir, { recursive: true })
|
|
||||||
await fsp.copyFile(
|
|
||||||
executorInputPath('cylinder.kcl'),
|
|
||||||
join(testDir, 'main.kcl')
|
|
||||||
)
|
|
||||||
await fsp.copyFile(
|
|
||||||
executorInputPath('basic_fillet_cube_end.kcl'),
|
|
||||||
join(testDir, 'other.kcl')
|
|
||||||
)
|
|
||||||
})
|
|
||||||
const u = await getUtils(page)
|
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
|
||||||
page.on('console', console.log)
|
|
||||||
|
|
||||||
// Constants and locators
|
|
||||||
const projectCard = page.getByText('testProject')
|
|
||||||
const otherFile = page
|
|
||||||
.getByRole('listitem')
|
|
||||||
.filter({ has: page.getByRole('button', { name: 'other.kcl' }) })
|
|
||||||
|
|
||||||
const badContent = 'this shit'
|
|
||||||
await test.step(
|
|
||||||
'Open project and make a change to the file',
|
|
||||||
async () => {
|
|
||||||
await projectCard.click()
|
|
||||||
await u.waitForPageLoad()
|
|
||||||
|
|
||||||
// Get the text in the code locator.
|
|
||||||
const originalText = await u.codeLocator.innerText()
|
|
||||||
// Click in the editor and add some new lines.
|
|
||||||
await u.codeLocator.click()
|
|
||||||
|
|
||||||
await page.keyboard.type(badContent)
|
|
||||||
|
|
||||||
// Ensure the content in the editor changed.
|
|
||||||
const newContent = await u.codeLocator.innerText()
|
|
||||||
|
|
||||||
expect(originalText !== newContent)
|
|
||||||
|
|
||||||
// Now hit undo
|
|
||||||
await page.keyboard.down('ControlOrMeta')
|
|
||||||
await page.keyboard.press('KeyZ')
|
|
||||||
await page.keyboard.up('ControlOrMeta')
|
|
||||||
|
|
||||||
await page.waitForTimeout(100)
|
|
||||||
await expect(u.codeLocator).toContainText(originalText)
|
|
||||||
await expect(u.codeLocator).not.toContainText(badContent)
|
|
||||||
|
|
||||||
// Hit redo.
|
|
||||||
await page.keyboard.down('Shift')
|
|
||||||
await page.keyboard.down('ControlOrMeta')
|
|
||||||
await page.keyboard.press('KeyZ')
|
|
||||||
await page.keyboard.up('ControlOrMeta')
|
|
||||||
await page.keyboard.up('Shift')
|
|
||||||
|
|
||||||
await page.waitForTimeout(100)
|
|
||||||
await expect(u.codeLocator).toContainText(originalText)
|
|
||||||
await expect(u.codeLocator).toContainText(badContent)
|
|
||||||
|
|
||||||
// Now hit undo
|
|
||||||
await page.keyboard.down('ControlOrMeta')
|
|
||||||
await page.keyboard.press('KeyZ')
|
|
||||||
await page.keyboard.up('ControlOrMeta')
|
|
||||||
|
|
||||||
await page.waitForTimeout(100)
|
|
||||||
await expect(u.codeLocator).toContainText(originalText)
|
|
||||||
await expect(u.codeLocator).not.toContainText(badContent)
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
})
|
||||||
|
const u = await getUtils(page)
|
||||||
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
|
page.on('console', console.log)
|
||||||
|
|
||||||
await test.step('navigate to other.kcl', async () => {
|
// Constants and locators
|
||||||
await u.openFilePanel()
|
const projectCard = page.getByText('testProject')
|
||||||
|
const otherFile = page
|
||||||
|
.getByRole('listitem')
|
||||||
|
.filter({ has: page.getByRole('button', { name: 'other.kcl' }) })
|
||||||
|
|
||||||
await otherFile.click()
|
const badContent = 'this shit'
|
||||||
await u.waitForPageLoad()
|
await test.step('Open project and make a change to the file', async () => {
|
||||||
await u.openKclCodePanel()
|
await projectCard.click()
|
||||||
await expect(u.codeLocator).toContainText('getOppositeEdge(thing)')
|
await u.waitForPageLoad()
|
||||||
await expect(u.codeLocator).not.toContainText(badContent)
|
|
||||||
})
|
|
||||||
|
|
||||||
await test.step('hit redo', async () => {
|
// Get the text in the code locator.
|
||||||
// Get the original content of the file.
|
const originalText = await u.codeLocator.innerText()
|
||||||
const originalText = await u.codeLocator.innerText()
|
// Click in the editor and add some new lines.
|
||||||
// Now hit redo
|
await u.codeLocator.click()
|
||||||
await page.keyboard.down('Shift')
|
|
||||||
await page.keyboard.down('ControlOrMeta')
|
|
||||||
await page.keyboard.press('KeyZ')
|
|
||||||
await page.keyboard.up('ControlOrMeta')
|
|
||||||
await page.keyboard.up('Shift')
|
|
||||||
|
|
||||||
await page.waitForTimeout(100)
|
await page.keyboard.type(badContent)
|
||||||
await expect(u.codeLocator).toContainText(originalText)
|
|
||||||
await expect(u.codeLocator).not.toContainText(badContent)
|
// Ensure the content in the editor changed.
|
||||||
})
|
const newContent = await u.codeLocator.innerText()
|
||||||
}
|
|
||||||
)
|
expect(originalText !== newContent)
|
||||||
}
|
|
||||||
)
|
// Now hit undo
|
||||||
|
await page.keyboard.down('ControlOrMeta')
|
||||||
|
await page.keyboard.press('KeyZ')
|
||||||
|
await page.keyboard.up('ControlOrMeta')
|
||||||
|
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
await expect(u.codeLocator).toContainText(originalText)
|
||||||
|
await expect(u.codeLocator).not.toContainText(badContent)
|
||||||
|
|
||||||
|
// Hit redo.
|
||||||
|
await page.keyboard.down('Shift')
|
||||||
|
await page.keyboard.down('ControlOrMeta')
|
||||||
|
await page.keyboard.press('KeyZ')
|
||||||
|
await page.keyboard.up('ControlOrMeta')
|
||||||
|
await page.keyboard.up('Shift')
|
||||||
|
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
await expect(u.codeLocator).toContainText(originalText)
|
||||||
|
await expect(u.codeLocator).toContainText(badContent)
|
||||||
|
|
||||||
|
// Now hit undo
|
||||||
|
await page.keyboard.down('ControlOrMeta')
|
||||||
|
await page.keyboard.press('KeyZ')
|
||||||
|
await page.keyboard.up('ControlOrMeta')
|
||||||
|
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
await expect(u.codeLocator).toContainText(originalText)
|
||||||
|
await expect(u.codeLocator).not.toContainText(badContent)
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('navigate to other.kcl', async () => {
|
||||||
|
await u.openFilePanel()
|
||||||
|
|
||||||
|
await otherFile.click()
|
||||||
|
await u.waitForPageLoad()
|
||||||
|
await u.openKclCodePanel()
|
||||||
|
await expect(u.codeLocator).toContainText('getOppositeEdge(thing)')
|
||||||
|
await expect(u.codeLocator).not.toContainText(badContent)
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('hit redo', async () => {
|
||||||
|
// Get the original content of the file.
|
||||||
|
const originalText = await u.codeLocator.innerText()
|
||||||
|
// Now hit redo
|
||||||
|
await page.keyboard.down('Shift')
|
||||||
|
await page.keyboard.down('ControlOrMeta')
|
||||||
|
await page.keyboard.press('KeyZ')
|
||||||
|
await page.keyboard.up('ControlOrMeta')
|
||||||
|
await page.keyboard.up('Shift')
|
||||||
|
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
await expect(u.codeLocator).toContainText(originalText)
|
||||||
|
await expect(u.codeLocator).not.toContainText(badContent)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
@ -1,14 +1,7 @@
|
|||||||
import { test, expect } from '@playwright/test'
|
import { test, expect } from './zoo-test'
|
||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
import fsp from 'fs/promises'
|
import fsp from 'fs/promises'
|
||||||
import {
|
import { getUtils, executorInputPath, createProject } from './test-utils'
|
||||||
getUtils,
|
|
||||||
setup,
|
|
||||||
setupElectron,
|
|
||||||
tearDown,
|
|
||||||
executorInputPath,
|
|
||||||
createProject,
|
|
||||||
} from './test-utils'
|
|
||||||
import { bracket } from 'lib/exampleKcl'
|
import { bracket } from 'lib/exampleKcl'
|
||||||
import { onboardingPaths } from 'routes/Onboarding/paths'
|
import { onboardingPaths } from 'routes/Onboarding/paths'
|
||||||
import {
|
import {
|
||||||
@ -21,34 +14,30 @@ import {
|
|||||||
import * as TOML from '@iarna/toml'
|
import * as TOML from '@iarna/toml'
|
||||||
import { expectPixelColor } from './fixtures/sceneFixture'
|
import { expectPixelColor } from './fixtures/sceneFixture'
|
||||||
|
|
||||||
test.beforeEach(async ({ context, page }, testInfo) => {
|
// Because onboarding relies on an app setting we need to set it as incompletel
|
||||||
if (testInfo.tags.includes('@electron')) {
|
// for all these tests.
|
||||||
return
|
|
||||||
}
|
|
||||||
await setup(context, page)
|
|
||||||
})
|
|
||||||
|
|
||||||
test.afterEach(async ({ page }, testInfo) => {
|
|
||||||
await tearDown(page, testInfo)
|
|
||||||
})
|
|
||||||
|
|
||||||
test.describe('Onboarding tests', () => {
|
test.describe('Onboarding tests', () => {
|
||||||
test('Onboarding code is shown in the editor', async ({ page }) => {
|
test(
|
||||||
const u = await getUtils(page)
|
'Onboarding code is shown in the editor',
|
||||||
|
{
|
||||||
// Override beforeEach test setup
|
appSettings: {
|
||||||
await page.addInitScript(
|
app: {
|
||||||
async ({ settingsKey }) => {
|
onboardingStatus: 'incomplete',
|
||||||
// Give no initial code, so that the onboarding start is shown immediately
|
},
|
||||||
localStorage.removeItem('persistCode')
|
|
||||||
localStorage.removeItem(settingsKey)
|
|
||||||
},
|
},
|
||||||
{ settingsKey: TEST_SETTINGS_KEY }
|
cleanProjectDir: true,
|
||||||
)
|
},
|
||||||
|
async ({ context, page, homePage }) => {
|
||||||
|
const u = await getUtils(page)
|
||||||
|
|
||||||
await page.setViewportSize({ width: 1200, height: 1000 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
await homePage.goToModelingScene()
|
||||||
|
|
||||||
await u.waitForAuthSkipAppStart()
|
// Test that the onboarding pane loaded
|
||||||
|
await expect(
|
||||||
|
page.getByText('Welcome to Modeling App! This')
|
||||||
|
).toBeVisible()
|
||||||
|
|
||||||
// Test that the onboarding pane loaded
|
// Test that the onboarding pane loaded
|
||||||
await expect(page.getByText('Welcome to Modeling App! This')).toBeVisible()
|
await expect(page.getByText('Welcome to Modeling App! This')).toBeVisible()
|
||||||
@ -65,22 +54,20 @@ test.describe('Onboarding tests', () => {
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'Desktop: fresh onboarding executes and loads',
|
'Desktop: fresh onboarding executes and loads',
|
||||||
{ tag: '@electron' },
|
{
|
||||||
async ({ browserName: _ }, testInfo) => {
|
tag: '@electron',
|
||||||
const { electronApp, page } = await setupElectron({
|
appSettings: {
|
||||||
testInfo,
|
app: {
|
||||||
appSettings: {
|
onboardingStatus: 'incomplete',
|
||||||
app: {
|
|
||||||
onboardingStatus: 'incomplete',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
cleanProjectDir: true,
|
},
|
||||||
})
|
cleanProjectDir: true,
|
||||||
|
},
|
||||||
|
async ({ page, homePage }, testInfo) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
|
|
||||||
const viewportSize = { width: 1200, height: 1000 }
|
const viewportSize = { width: 1200, height: 500 }
|
||||||
await page.setViewportSize(viewportSize)
|
await page.setBodyDimensions(viewportSize)
|
||||||
|
|
||||||
await test.step(`Create a project and open to the onboarding`, async () => {
|
await test.step(`Create a project and open to the onboarding`, async () => {
|
||||||
await createProject({ name: 'project-link', page })
|
await createProject({ name: 'project-link', page })
|
||||||
@ -108,337 +95,368 @@ test.describe('Onboarding tests', () => {
|
|||||||
|
|
||||||
//await expectPixelColor(page, modelColor, XYPlanePoint, 8)
|
//await expectPixelColor(page, modelColor, XYPlanePoint, 8)
|
||||||
})
|
})
|
||||||
|
|
||||||
await electronApp.close()
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
test('Code resets after confirmation', async ({ page }) => {
|
test(
|
||||||
const initialCode = `sketch001 = startSketchOn('XZ')`
|
'Code resets after confirmation',
|
||||||
|
{
|
||||||
// Load the page up with some code so we see the confirmation warning
|
appSettings: {
|
||||||
// when we go to replay onboarding
|
app: {
|
||||||
await page.addInitScript((code) => {
|
onboardingStatus: 'incomplete',
|
||||||
localStorage.setItem('persistCode', code)
|
},
|
||||||
}, initialCode)
|
|
||||||
|
|
||||||
const u = await getUtils(page)
|
|
||||||
await page.setViewportSize({ width: 1200, height: 1000 })
|
|
||||||
await u.waitForAuthSkipAppStart()
|
|
||||||
|
|
||||||
// Replay the onboarding
|
|
||||||
await page.getByRole('link', { name: 'Settings' }).last().click()
|
|
||||||
const replayButton = page.getByRole('button', { name: 'Replay onboarding' })
|
|
||||||
await expect(replayButton).toBeVisible()
|
|
||||||
await replayButton.click()
|
|
||||||
|
|
||||||
// Ensure we see the warning, and that the code has not yet updated
|
|
||||||
await expect(
|
|
||||||
page.getByText('Replaying onboarding resets your code')
|
|
||||||
).toBeVisible()
|
|
||||||
await expect(page.locator('.cm-content')).toHaveText(initialCode)
|
|
||||||
|
|
||||||
const nextButton = page.getByTestId('onboarding-next')
|
|
||||||
await expect(nextButton).toBeVisible()
|
|
||||||
await nextButton.click()
|
|
||||||
|
|
||||||
// Ensure we see the introduction and that the code has been reset
|
|
||||||
await expect(page.getByText('Welcome to Modeling App!')).toBeVisible()
|
|
||||||
await expect(page.locator('.cm-content')).toContainText('// Shelf Bracket')
|
|
||||||
|
|
||||||
// Ensure we persisted the code to local storage.
|
|
||||||
// Playwright's addInitScript method unfortunately will reset
|
|
||||||
// this code if we try reloading the page as a test,
|
|
||||||
// so this is our best way to test persistence afaik.
|
|
||||||
expect(
|
|
||||||
await page.evaluate(() => {
|
|
||||||
return localStorage.getItem('persistCode')
|
|
||||||
})
|
|
||||||
).toContain('// Shelf Bracket')
|
|
||||||
|
|
||||||
// Make sure the model loaded
|
|
||||||
const XYPlanePoint = { x: 986, y: 522 } as const
|
|
||||||
const modelColor: [number, number, number] = [76, 76, 76]
|
|
||||||
await page.mouse.move(XYPlanePoint.x, XYPlanePoint.y)
|
|
||||||
await expectPixelColor(page, modelColor, XYPlanePoint, 8)
|
|
||||||
})
|
|
||||||
|
|
||||||
test('Click through each onboarding step', async ({ page }) => {
|
|
||||||
const u = await getUtils(page)
|
|
||||||
|
|
||||||
// Override beforeEach test setup
|
|
||||||
await page.addInitScript(
|
|
||||||
async ({ settingsKey, settings }) => {
|
|
||||||
// Give no initial code, so that the onboarding start is shown immediately
|
|
||||||
localStorage.setItem('persistCode', '')
|
|
||||||
localStorage.setItem(settingsKey, settings)
|
|
||||||
},
|
},
|
||||||
{
|
cleanProjectDir: true,
|
||||||
settingsKey: TEST_SETTINGS_KEY,
|
},
|
||||||
settings: TOML.stringify({ settings: TEST_SETTINGS_ONBOARDING_START }),
|
async ({ context, page, homePage }) => {
|
||||||
}
|
const initialCode = `sketch001 = startSketchOn('XZ')`
|
||||||
)
|
|
||||||
|
|
||||||
await page.setViewportSize({ width: 1200, height: 1080 })
|
// Load the page up with some code so we see the confirmation warning
|
||||||
|
// when we go to replay onboarding
|
||||||
|
await context.addInitScript((code) => {
|
||||||
|
localStorage.setItem('persistCode', code)
|
||||||
|
}, initialCode)
|
||||||
|
|
||||||
await u.waitForAuthSkipAppStart()
|
const u = await getUtils(page)
|
||||||
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
await homePage.goToModelingScene()
|
||||||
|
|
||||||
// Test that the onboarding pane loaded
|
// Replay the onboarding
|
||||||
await expect(page.getByText('Welcome to Modeling App! This')).toBeVisible()
|
await page.getByRole('link', { name: 'Settings' }).last().click()
|
||||||
|
const replayButton = page.getByRole('button', {
|
||||||
|
name: 'Replay onboarding',
|
||||||
|
})
|
||||||
|
await expect(replayButton).toBeVisible()
|
||||||
|
await replayButton.click()
|
||||||
|
|
||||||
const nextButton = page.getByTestId('onboarding-next')
|
// Ensure we see the warning, and that the code has not yet updated
|
||||||
|
await expect(
|
||||||
|
page.getByText('Would you like to create')
|
||||||
|
).toBeVisible()
|
||||||
|
await expect(page.locator('.cm-content')).toHaveText(initialCode)
|
||||||
|
|
||||||
while ((await nextButton.innerText()) !== 'Finish') {
|
const nextButton = page.getByTestId('onboarding-next')
|
||||||
await expect(nextButton).toBeVisible()
|
await nextButton.hover()
|
||||||
await nextButton.click()
|
await nextButton.click()
|
||||||
|
|
||||||
|
// Ensure we see the introduction and that the code has been reset
|
||||||
|
await expect(page.getByText('Welcome to Modeling App!')).toBeVisible()
|
||||||
|
await expect(page.locator('.cm-content')).toContainText(
|
||||||
|
'// Shelf Bracket'
|
||||||
|
)
|
||||||
|
|
||||||
|
// There used to be old code here that checked if we stored the reset
|
||||||
|
// code into localStorage but that isnt the case on desktop. It gets
|
||||||
|
// saved to the file system, which we have other tests for.
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// Finish the onboarding
|
test(
|
||||||
await expect(nextButton).toBeVisible()
|
'Click through each onboarding step',
|
||||||
await nextButton.click()
|
{
|
||||||
|
appSettings: {
|
||||||
// Test that the onboarding pane is gone
|
app: {
|
||||||
await expect(page.getByTestId('onboarding-content')).not.toBeVisible()
|
onboardingStatus: 'incomplete',
|
||||||
await expect(page.url()).not.toContain('onboarding')
|
},
|
||||||
|
|
||||||
await u.openAndClearDebugPanel()
|
|
||||||
await u.expectCmdLog('[data-message-type="execution-done"]')
|
|
||||||
await u.closeDebugPanel()
|
|
||||||
|
|
||||||
// TODO: jess to fix
|
|
||||||
// Make sure the model loaded
|
|
||||||
//const XYPlanePoint = { x: 774, y: 516 } as const
|
|
||||||
// const modelColor: [number, number, number] = [129, 129, 129]
|
|
||||||
// await page.mouse.move(XYPlanePoint.x, XYPlanePoint.y)
|
|
||||||
// await expectPixelColor(page, modelColor, XYPlanePoint, 20)
|
|
||||||
})
|
|
||||||
|
|
||||||
test('Onboarding redirects and code updating', async ({ page }) => {
|
|
||||||
const u = await getUtils(page)
|
|
||||||
|
|
||||||
// Override beforeEach test setup
|
|
||||||
await page.addInitScript(
|
|
||||||
async ({ settingsKey, settings }) => {
|
|
||||||
// Give some initial code, so we can test that it's cleared
|
|
||||||
localStorage.setItem('persistCode', 'sigmaAllow = 15000')
|
|
||||||
localStorage.setItem(settingsKey, settings)
|
|
||||||
},
|
},
|
||||||
{
|
},
|
||||||
settingsKey: TEST_SETTINGS_KEY,
|
async ({ context, page, homePage }) => {
|
||||||
settings: TOML.stringify({ settings: TEST_SETTINGS_ONBOARDING_EXPORT }),
|
const u = await getUtils(page)
|
||||||
|
|
||||||
|
// Override beforeEach test setup
|
||||||
|
await context.addInitScript(
|
||||||
|
async ({ settingsKey, settings }) => {
|
||||||
|
// Give no initial code, so that the onboarding start is shown immediately
|
||||||
|
localStorage.setItem('persistCode', '')
|
||||||
|
localStorage.setItem(settingsKey, settings)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
settingsKey: TEST_SETTINGS_KEY,
|
||||||
|
settings: TOML.stringify({
|
||||||
|
settings: TEST_SETTINGS_ONBOARDING_START,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
await page.setBodyDimensions({ width: 1200, height: 1080 })
|
||||||
|
await homePage.goToModelingScene()
|
||||||
|
|
||||||
|
// Test that the onboarding pane loaded
|
||||||
|
await expect(
|
||||||
|
page.getByText('Welcome to Modeling App! This')
|
||||||
|
).toBeVisible()
|
||||||
|
|
||||||
|
const nextButton = page.getByTestId('onboarding-next')
|
||||||
|
|
||||||
|
while ((await nextButton.innerText()) !== 'Finish') {
|
||||||
|
await nextButton.hover()
|
||||||
|
await nextButton.click()
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
// Finish the onboarding
|
||||||
|
await nextButton.hover()
|
||||||
|
await nextButton.click()
|
||||||
|
|
||||||
await u.waitForAuthSkipAppStart()
|
// Test that the onboarding pane is gone
|
||||||
|
await expect(page.getByTestId('onboarding-content')).not.toBeVisible()
|
||||||
// Test that the redirect happened
|
await expect.poll(() => page.url()).not.toContain('/onboarding')
|
||||||
await expect(page.url().split(':3000').slice(-1)[0]).toBe(
|
|
||||||
`/file/%2Fbrowser%2Fmain.kcl/onboarding/export`
|
|
||||||
)
|
|
||||||
|
|
||||||
// Test that you come back to this page when you refresh
|
|
||||||
await page.reload()
|
|
||||||
await expect(page.url().split(':3000').slice(-1)[0]).toBe(
|
|
||||||
`/file/%2Fbrowser%2Fmain.kcl/onboarding/export`
|
|
||||||
)
|
|
||||||
|
|
||||||
// Test that the onboarding pane loaded
|
|
||||||
const title = page.locator('[data-testid="onboarding-content"]')
|
|
||||||
await expect(title).toBeAttached()
|
|
||||||
|
|
||||||
// Test that the code changes when you advance to the next step
|
|
||||||
await page.locator('[data-testid="onboarding-next"]').click()
|
|
||||||
await expect(page.locator('.cm-content')).toHaveText('')
|
|
||||||
|
|
||||||
// Test that the code is not empty when you click on the next step
|
|
||||||
await page.locator('[data-testid="onboarding-next"]').click()
|
|
||||||
await expect(page.locator('.cm-content')).toHaveText(/.+/)
|
|
||||||
})
|
|
||||||
|
|
||||||
test('Onboarding code gets reset to demo on Interactive Numbers step', async ({
|
|
||||||
page,
|
|
||||||
}) => {
|
|
||||||
test.skip(
|
|
||||||
process.platform === 'darwin',
|
|
||||||
"Skip on macOS, because Playwright isn't behaving the same as the actual browser"
|
|
||||||
)
|
|
||||||
const u = await getUtils(page)
|
|
||||||
const badCode = `// This is bad code we shouldn't see`
|
|
||||||
// Override beforeEach test setup
|
|
||||||
await page.addInitScript(
|
|
||||||
async ({ settingsKey, settings, badCode }) => {
|
|
||||||
localStorage.setItem('persistCode', badCode)
|
|
||||||
localStorage.setItem(settingsKey, settings)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
settingsKey: TEST_SETTINGS_KEY,
|
|
||||||
settings: TOML.stringify({
|
|
||||||
settings: TEST_SETTINGS_ONBOARDING_PARAMETRIC_MODELING,
|
|
||||||
}),
|
|
||||||
badCode,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
await page.setViewportSize({ width: 1200, height: 1080 })
|
|
||||||
await u.waitForAuthSkipAppStart()
|
|
||||||
|
|
||||||
await page.waitForURL('**' + onboardingPaths.PARAMETRIC_MODELING, {
|
|
||||||
waitUntil: 'domcontentloaded',
|
|
||||||
})
|
|
||||||
|
|
||||||
const bracketNoNewLines = bracket.replace(/\n/g, '')
|
|
||||||
|
|
||||||
// Check the code got reset on load
|
|
||||||
await expect(page.locator('#code-pane')).toBeVisible()
|
|
||||||
await expect(u.codeLocator).toHaveText(bracketNoNewLines, {
|
|
||||||
timeout: 10_000,
|
|
||||||
})
|
|
||||||
|
|
||||||
// Mess with the code again
|
|
||||||
await u.codeLocator.selectText()
|
|
||||||
await u.codeLocator.fill(badCode)
|
|
||||||
await expect(u.codeLocator).toHaveText(badCode)
|
|
||||||
|
|
||||||
// Click to the next step
|
|
||||||
await page.locator('[data-testid="onboarding-next"]').click()
|
|
||||||
await page.waitForURL('**' + onboardingPaths.INTERACTIVE_NUMBERS, {
|
|
||||||
waitUntil: 'domcontentloaded',
|
|
||||||
})
|
|
||||||
|
|
||||||
// Check that the code has been reset
|
|
||||||
await expect(u.codeLocator).toHaveText(bracketNoNewLines)
|
|
||||||
})
|
|
||||||
|
|
||||||
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,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const u = await getUtils(page)
|
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
|
||||||
await u.waitForAuthSkipAppStart()
|
|
||||||
|
|
||||||
await page.waitForURL('**/file/**', { waitUntil: 'domcontentloaded' })
|
|
||||||
|
|
||||||
// Test that the text in this step is correct
|
|
||||||
const avatarLocator = await page
|
|
||||||
.getByTestId('user-sidebar-toggle')
|
|
||||||
.locator('img')
|
|
||||||
const onboardingOverlayLocator = await 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')
|
|
||||||
|
|
||||||
// This is to force the avatar to 404.
|
|
||||||
// For our test image (only triggers locally. on CI, it's Kurt's /
|
|
||||||
// gravatar image )
|
|
||||||
await page.route('/cat.jpg', async (route) => {
|
|
||||||
await route.fulfill({
|
|
||||||
status: 404,
|
|
||||||
contentType: 'text/plain',
|
|
||||||
body: 'Not Found!',
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
// 404 the CI avatar image
|
|
||||||
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("Avatar text doesn't mention avatar when no avatar", async ({
|
|
||||||
page,
|
|
||||||
}) => {
|
|
||||||
// Override beforeEach test setup
|
|
||||||
await page.addInitScript(
|
|
||||||
async ({ settingsKey, settings }) => {
|
|
||||||
localStorage.setItem(settingsKey, settings)
|
|
||||||
localStorage.setItem('FORCE_NO_IMAGE', 'FORCE_NO_IMAGE')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
settingsKey: TEST_SETTINGS_KEY,
|
|
||||||
settings: TOML.stringify({
|
|
||||||
settings: TEST_SETTINGS_ONBOARDING_USER_MENU,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const u = await getUtils(page)
|
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
|
||||||
await u.waitForAuthSkipAppStart()
|
|
||||||
|
|
||||||
await page.waitForURL('**/file/**', { waitUntil: 'domcontentloaded' })
|
|
||||||
|
|
||||||
// Test that the text in this step is correct
|
|
||||||
const sidebar = page.getByTestId('user-sidebar-toggle')
|
|
||||||
const avatar = sidebar.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(avatar).not.toBeVisible()
|
|
||||||
await expect(onboardingOverlayLocator).toBeVisible()
|
|
||||||
await expect(onboardingOverlayLocator).toContainText('the menu button')
|
|
||||||
|
|
||||||
// Test we mention what else is in this menu for https://github.com/KittyCAD/modeling-app/issues/2939
|
|
||||||
// which doesn't deserver its own full test spun up
|
|
||||||
const userMenuFeatures = [
|
|
||||||
'manage your account',
|
|
||||||
'report a bug',
|
|
||||||
'request a feature',
|
|
||||||
'sign out',
|
|
||||||
]
|
|
||||||
for (const feature of userMenuFeatures) {
|
|
||||||
await expect(onboardingOverlayLocator).toContainText(feature)
|
|
||||||
}
|
}
|
||||||
})
|
)
|
||||||
|
|
||||||
|
test(
|
||||||
|
'Onboarding redirects and code updating',
|
||||||
|
{
|
||||||
|
appSettings: {
|
||||||
|
app: {
|
||||||
|
onboardingStatus: '/export',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cleanProjectDir: true,
|
||||||
|
},
|
||||||
|
async ({ context, page, homePage }) => {
|
||||||
|
const u = await getUtils(page)
|
||||||
|
|
||||||
|
const originalCode = 'sigmaAllow = 15000'
|
||||||
|
|
||||||
|
// Override beforeEach test setup
|
||||||
|
await context.addInitScript(
|
||||||
|
async ({ settingsKey, settings }) => {
|
||||||
|
// Give some initial code, so we can test that it's cleared
|
||||||
|
localStorage.setItem('persistCode', originalCode)
|
||||||
|
localStorage.setItem(settingsKey, settings)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
settingsKey: TEST_SETTINGS_KEY,
|
||||||
|
settings: TOML.stringify({
|
||||||
|
settings: TEST_SETTINGS_ONBOARDING_EXPORT,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
await homePage.goToModelingScene()
|
||||||
|
|
||||||
|
// Test that the redirect happened
|
||||||
|
await expect.poll(() => page.url()).toContain('/onboarding/export')
|
||||||
|
|
||||||
|
// Test that you come back to this page when you refresh
|
||||||
|
await page.reload()
|
||||||
|
await expect.poll(() => page.url()).toContain('/onboarding/export')
|
||||||
|
|
||||||
|
// Test that the code changes when you advance to the next step
|
||||||
|
await page.getByTestId('onboarding-next').hover()
|
||||||
|
await page.getByTestId('onboarding-next').click()
|
||||||
|
|
||||||
|
// Test that the onboarding pane loaded
|
||||||
|
const title = page.locator('[data-testid="onboarding-content"]')
|
||||||
|
await expect(title).toBeAttached()
|
||||||
|
|
||||||
|
await expect(page.locator('.cm-content')).not.toHaveText(originalCode)
|
||||||
|
|
||||||
|
// Test that the code is not empty when you click on the next step
|
||||||
|
await page.locator('[data-testid="onboarding-next"]').hover()
|
||||||
|
await page.locator('[data-testid="onboarding-next"]').click()
|
||||||
|
await expect(page.locator('.cm-content')).toHaveText(/.+/)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
test(
|
||||||
|
'Onboarding code gets reset to demo on Interactive Numbers step',
|
||||||
|
{
|
||||||
|
appSettings: {
|
||||||
|
app: {
|
||||||
|
onboardingStatus: '/parametric-modeling',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cleanProjectDir: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
async ({ context, page, homePage }) => {
|
||||||
|
const u = await getUtils(page)
|
||||||
|
const badCode = `// This is bad code we shouldn't see`
|
||||||
|
|
||||||
|
await page.setBodyDimensions({ width: 1200, height: 1080 })
|
||||||
|
await homePage.goToModelingScene()
|
||||||
|
|
||||||
|
await expect.poll(() => page.url()).toContain(onboardingPaths.PARAMETRIC_MODELING)
|
||||||
|
|
||||||
|
const bracketNoNewLines = bracket.replace(/\n/g, '')
|
||||||
|
|
||||||
|
// Check the code got reset on load
|
||||||
|
await expect(page.locator('#code-pane')).toBeVisible()
|
||||||
|
await expect(u.codeLocator).toHaveText(bracketNoNewLines, {
|
||||||
|
timeout: 10_000,
|
||||||
|
})
|
||||||
|
|
||||||
|
// Mess with the code again
|
||||||
|
await u.codeLocator.selectText()
|
||||||
|
await u.codeLocator.fill(badCode)
|
||||||
|
await expect(u.codeLocator).toHaveText(badCode)
|
||||||
|
|
||||||
|
// Click to the next step
|
||||||
|
await page.locator('[data-testid="onboarding-next"]').hover()
|
||||||
|
await page.locator('[data-testid="onboarding-next"]').click()
|
||||||
|
await page.waitForURL('**' + onboardingPaths.INTERACTIVE_NUMBERS, {
|
||||||
|
waitUntil: 'domcontentloaded',
|
||||||
|
})
|
||||||
|
|
||||||
|
// Check that the code has been reset
|
||||||
|
await expect(u.codeLocator).toHaveText(bracketNoNewLines)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// (lee) The two avatar tests are weird because even on main, we don't have
|
||||||
|
// anything to do with the avatar inside the onboarding test. Due to the
|
||||||
|
// low impact of an avatar not showing I'm changing this to fixme.
|
||||||
|
test.fixme(
|
||||||
|
'Avatar text updates depending on image load success',
|
||||||
|
{
|
||||||
|
appSettings: {
|
||||||
|
app: {
|
||||||
|
onboardingStatus: 'incomplete',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cleanProjectDir: true,
|
||||||
|
},
|
||||||
|
async ({ context, page, homePage }) => {
|
||||||
|
// Override beforeEach test setup
|
||||||
|
await context.addInitScript(
|
||||||
|
async ({ settingsKey, settings }) => {
|
||||||
|
localStorage.setItem(settingsKey, settings)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
settingsKey: TEST_SETTINGS_KEY,
|
||||||
|
settings: TOML.stringify({
|
||||||
|
settings: TEST_SETTINGS_ONBOARDING_USER_MENU,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const u = await getUtils(page)
|
||||||
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
await homePage.goToModelingScene()
|
||||||
|
|
||||||
|
// Test that the text in this step is correct
|
||||||
|
const avatarLocator = await page
|
||||||
|
.getByTestId('user-sidebar-toggle')
|
||||||
|
.locator('img')
|
||||||
|
const onboardingOverlayLocator = await 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')
|
||||||
|
|
||||||
|
// This is to force the avatar to 404.
|
||||||
|
// For our test image (only triggers locally. on CI, it's Kurt's /
|
||||||
|
// gravatar image )
|
||||||
|
await page.route('/cat.jpg', async (route) => {
|
||||||
|
await route.fulfill({
|
||||||
|
status: 404,
|
||||||
|
contentType: 'text/plain',
|
||||||
|
body: 'Not Found!',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// 404 the CI avatar image
|
||||||
|
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.fixme(
|
||||||
|
"Avatar text doesn't mention avatar when no avatar",
|
||||||
|
{
|
||||||
|
appSettings: {
|
||||||
|
app: {
|
||||||
|
onboardingStatus: 'incomplete',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cleanProjectDir: true,
|
||||||
|
},
|
||||||
|
async ({ context, page, homePage }) => {
|
||||||
|
// Override beforeEach test setup
|
||||||
|
await context.addInitScript(
|
||||||
|
async ({ settingsKey, settings }) => {
|
||||||
|
localStorage.setItem(settingsKey, settings)
|
||||||
|
localStorage.setItem('FORCE_NO_IMAGE', 'FORCE_NO_IMAGE')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
settingsKey: TEST_SETTINGS_KEY,
|
||||||
|
settings: TOML.stringify({
|
||||||
|
settings: TEST_SETTINGS_ONBOARDING_USER_MENU,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const u = await getUtils(page)
|
||||||
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
await homePage.goToModelingScene()
|
||||||
|
|
||||||
|
// Test that the text in this step is correct
|
||||||
|
const sidebar = page.getByTestId('user-sidebar-toggle')
|
||||||
|
const avatar = sidebar.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(avatar).not.toBeVisible()
|
||||||
|
await expect(onboardingOverlayLocator).toBeVisible()
|
||||||
|
await expect(onboardingOverlayLocator).toContainText('the menu button')
|
||||||
|
|
||||||
|
// Test we mention what else is in this menu for https://github.com/KittyCAD/modeling-app/issues/2939
|
||||||
|
// which doesn't deserver its own full test spun up
|
||||||
|
const userMenuFeatures = [
|
||||||
|
'manage your account',
|
||||||
|
'report a bug',
|
||||||
|
'request a feature',
|
||||||
|
'sign out',
|
||||||
|
]
|
||||||
|
for (const feature of userMenuFeatures) {
|
||||||
|
await expect(onboardingOverlayLocator).toContainText(feature)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test.fixme(
|
test.fixme(
|
||||||
'Restarting onboarding on desktop takes one attempt',
|
'Restarting onboarding on desktop takes one attempt',
|
||||||
{ tag: '@electron' },
|
{
|
||||||
async ({ browser: _ }, testInfo) => {
|
appSettings: {
|
||||||
const { electronApp, page } = await setupElectron({
|
app: {
|
||||||
testInfo,
|
onboardingStatus: 'dismissed',
|
||||||
folderSetupFn: async (dir) => {
|
|
||||||
const routerTemplateDir = join(dir, 'router-template-slate')
|
|
||||||
await fsp.mkdir(routerTemplateDir, { recursive: true })
|
|
||||||
await fsp.copyFile(
|
|
||||||
executorInputPath('router-template-slate.kcl'),
|
|
||||||
join(routerTemplateDir, 'main.kcl')
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
cleanProjectDir: true,
|
||||||
|
},
|
||||||
|
async ({ context, page, homePage }, testInfo) => {
|
||||||
|
await context.folderSetupFn(async (dir) => {
|
||||||
|
const routerTemplateDir = join(dir, 'router-template-slate')
|
||||||
|
await fsp.mkdir(routerTemplateDir, { recursive: true })
|
||||||
|
await fsp.copyFile(
|
||||||
|
executorInputPath('router-template-slate.kcl'),
|
||||||
|
join(routerTemplateDir, 'main.kcl')
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Our constants
|
// Our constants
|
||||||
@ -450,9 +468,8 @@ test.fixme(
|
|||||||
const restartOnboardingButton = page.getByRole('button', {
|
const restartOnboardingButton = page.getByRole('button', {
|
||||||
name: 'Reset onboarding',
|
name: 'Reset onboarding',
|
||||||
})
|
})
|
||||||
const restartConfirmationButton = page.getByRole('button', {
|
const nextButton = page.getByTestId('onboarding-next')
|
||||||
name: 'Make a new project',
|
|
||||||
})
|
|
||||||
const tutorialProjectIndicator = page
|
const tutorialProjectIndicator = page
|
||||||
.getByTestId('project-sidebar-toggle')
|
.getByTestId('project-sidebar-toggle')
|
||||||
.filter({ hasText: 'Tutorial Project 00' })
|
.filter({ hasText: 'Tutorial Project 00' })
|
||||||
@ -471,7 +488,7 @@ test.fixme(
|
|||||||
})
|
})
|
||||||
|
|
||||||
await test.step('Navigate into project', async () => {
|
await test.step('Navigate into project', async () => {
|
||||||
await page.setViewportSize({ width: 1200, height: 1000 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
|
||||||
page.on('console', console.log)
|
page.on('console', console.log)
|
||||||
|
|
||||||
@ -487,8 +504,8 @@ test.fixme(
|
|||||||
await helpMenuButton.click()
|
await helpMenuButton.click()
|
||||||
await restartOnboardingButton.click()
|
await restartOnboardingButton.click()
|
||||||
|
|
||||||
await expect(restartConfirmationButton).toBeVisible()
|
await nextButton.hover()
|
||||||
await restartConfirmationButton.click()
|
await nextButton.click()
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('Confirm that the onboarding has restarted', async () => {
|
await test.step('Confirm that the onboarding has restarted', async () => {
|
||||||
@ -520,11 +537,9 @@ test.fixme(
|
|||||||
|
|
||||||
await restartOnboardingSettingsButton.click()
|
await restartOnboardingSettingsButton.click()
|
||||||
// Since the code is empty, we should not see the confirmation dialog
|
// Since the code is empty, we should not see the confirmation dialog
|
||||||
await expect(restartConfirmationButton).not.toBeVisible()
|
await expect(nextButton).not.toBeVisible()
|
||||||
await expect(tutorialProjectIndicator).toBeVisible()
|
await expect(tutorialProjectIndicator).toBeVisible()
|
||||||
await expect(tutorialModalText).toBeVisible()
|
await expect(tutorialModalText).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
await electronApp.close()
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -696,10 +696,7 @@ export const makeTemplate: (
|
|||||||
const PLAYWRIGHT_DOWNLOAD_DIR = 'downloads-during-playwright'
|
const PLAYWRIGHT_DOWNLOAD_DIR = 'downloads-during-playwright'
|
||||||
|
|
||||||
export const getPlaywrightDownloadDir = (page: Page) => {
|
export const getPlaywrightDownloadDir = (page: Page) => {
|
||||||
return path.resolve(
|
return path.resolve(page.TEST_SETTINGS_FILE_KEY, PLAYWRIGHT_DOWNLOAD_DIR)
|
||||||
page.TEST_SETTINGS_FILE_KEY,
|
|
||||||
PLAYWRIGHT_DOWNLOAD_DIR
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const moveDownloadedFileTo = async (page: Page, toLocation: string) => {
|
const moveDownloadedFileTo = async (page: Page, toLocation: string) => {
|
||||||
|
@ -28,7 +28,12 @@ export function test(desc, objOrFn, fnMaybe) {
|
|||||||
const tronApp = new AuthenticatedTronApp(context, page, testInfo)
|
const tronApp = new AuthenticatedTronApp(context, page, testInfo)
|
||||||
|
|
||||||
const fixtures: Fixtures = { cmdBar, editor, toolbar, scene, homePage }
|
const fixtures: Fixtures = { cmdBar, editor, toolbar, scene, homePage }
|
||||||
await tronApp.initialise({ fixtures })
|
const options = {
|
||||||
|
fixtures,
|
||||||
|
appSettings: objOrFn?.appSettings,
|
||||||
|
cleanProjectDir: objOrFn?.cleanProjectDir,
|
||||||
|
}
|
||||||
|
await tronApp.initialise(options)
|
||||||
|
|
||||||
// We need to patch this because addInitScript will bind too late in our
|
// We need to patch this because addInitScript will bind too late in our
|
||||||
// electron tests, never running. We need to call reload() after each call
|
// electron tests, never running. We need to call reload() after each call
|
||||||
|
Reference in New Issue
Block a user