Continue running broken tests for Axiom metrics (#5883)

* Install Vector on Ubuntu to log failed test to Axiom

* Allow flaky tests to run on main for Axiom metrics

* Enable problematic tests on a dedicated branch
This commit is contained in:
Jace Browning
2025-03-20 16:28:08 -04:00
committed by GitHub
parent 09c6f51141
commit 2c6404f671
23 changed files with 2173 additions and 2145 deletions

View File

@ -4,27 +4,27 @@
set -euo pipefail
if [[ ! -f "test-results/.last-run.json" ]]; then
# if no last run artifact, than run plawright normally
# If no last run artifact, than run Playwright normally
echo "run playwright normally"
if [[ "$3" == *ubuntu* ]]; then
xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- yarn test:playwright:electron:ubuntu -- --shard=$1/$2 || true
elif [[ "$3" == *windows* ]]; then
yarn test:playwright:electron:windows -- --shard=$1/$2 || true
elif [[ "$3" == *macos* ]]; then
yarn test:playwright:electron:macos -- --shard=$1/$2 || true
else
echo "Do not run playwright. Unable to detect os runtime."
exit 1
fi
# # send to axiom
node playwrightProcess.mjs | tee /tmp/github-actions.log > /dev/null 2>&1
if [[ "$3" == *ubuntu* ]]; then
xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- yarn test:playwright:electron:ubuntu -- --shard=$1/$2 || true
elif [[ "$3" == *windows* ]]; then
yarn test:playwright:electron:windows -- --shard=$1/$2 || true
elif [[ "$3" == *macos* ]]; then
yarn test:playwright:electron:macos -- --shard=$1/$2 || true
else
echo "Do not run Playwright. Unable to detect os runtime."
exit 1
fi
# Log failures for Axiom to pick up
node playwrightProcess.mjs > /tmp/github-actions.log
fi
retry=1
max_retrys=1
max_retries=1
# retry failed tests, doing our own retries because using inbuilt playwright retries causes connection issues
while [[ $retry -le $max_retrys ]]; do
# Retry failed tests, doing our own retries because using inbuilt Playwright retries causes connection issues
while [[ $retry -le $max_retries ]]; do
if [[ -f "test-results/.last-run.json" ]]; then
failed_tests=$(jq '.failedTests | length' test-results/.last-run.json)
if [[ $failed_tests -gt 0 ]]; then
@ -40,8 +40,8 @@ while [[ $retry -le $max_retrys ]]; do
echo "Do not run playwright. Unable to detect os runtime."
exit 1
fi
# send to axiom
node playwrightProcess.mjs | tee /tmp/github-actions.log > /dev/null 2>&1
# Log failures for Axiom to pick up
node playwrightProcess.mjs > /tmp/github-actions.log
retry=$((retry + 1))
else
echo "retried=false" >>$GITHUB_OUTPUT
@ -58,7 +58,7 @@ echo "retried=false" >>$GITHUB_OUTPUT
if [[ -f "test-results/.last-run.json" ]]; then
failed_tests=$(jq '.failedTests | length' test-results/.last-run.json)
if [[ $failed_tests -gt 0 ]]; then
# if it still fails after 3 retrys, then fail the job
# If it still fails after 3 retries, then fail the job
exit 1
fi
fi

View File

@ -340,14 +340,22 @@ jobs:
if: needs.conditions.outputs.should-run == 'true'
run: yarn tronb:vite:dev
- name: Install good sed
if: startsWith(matrix.os, 'macos')
- name: Install vector
if: contains(matrix.os, 'ubuntu')
shell: bash
run: |
brew install gnu-sed
echo "/opt/homebrew/opt/gnu-sed/libexec/gnubin" >> $GITHUB_PATH
# TODO: Add back axiom logs
curl --proto '=https' --tlsv1.2 -sSfL https://sh.vector.dev > /tmp/vector.sh
chmod +x /tmp/vector.sh
/tmp/vector.sh -y -no-modify-path
mkdir -p /tmp/vector
cp .github/workflows/vector.toml /tmp/vector.toml
sed -i "s#GITHUB_WORKFLOW#${GITHUB_WORKFLOW}#g" /tmp/vector.toml
sed -i "s#GITHUB_REPOSITORY#${GITHUB_REPOSITORY}#g" /tmp/vector.toml
sed -i "s#GITHUB_SHA#${GITHUB_SHA}#g" /tmp/vector.toml
sed -i "s#GITHUB_REF_NAME#${GITHUB_REF_NAME}#g" /tmp/vector.toml
sed -i "s#GH_ACTIONS_AXIOM_TOKEN#${{secrets.GH_ACTIONS_AXIOM_TOKEN}}#g" /tmp/vector.toml
cat /tmp/vector.toml
${HOME}/.vector/bin/vector --config /tmp/vector.toml &
- uses: actions/download-artifact@v4
if: ${{ needs.conditions.outputs.should-run == 'true' && !cancelled() && (success() || failure()) }}

View File

@ -153,7 +153,8 @@ async function doBasicSketch(
}
test.describe('Basic sketch', { tag: ['@skipWin'] }, () => {
test.fixme('code pane open at start', async ({ page, homePage }) => {
test('code pane open at start', async ({ page, homePage }) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
await doBasicSketch(page, homePage, ['code'])
})

View File

@ -46,11 +46,12 @@ test.describe('Code pane and errors', { tag: ['@skipWin'] }, () => {
await expect(codePaneButtonHolder).toContainText('notification')
})
test.skip('Opening and closing the code pane will consistently show error diagnostics', async ({
test('Opening and closing the code pane will consistently show error diagnostics', async ({
page,
homePage,
editor,
}) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
const u = await getUtils(page)
// Load the app with the working starter code
@ -119,45 +120,47 @@ test.describe('Code pane and errors', { tag: ['@skipWin'] }, () => {
await expect(page.locator('.cm-tooltip').first()).toBeVisible()
})
test.fixme(
'When error is not in view you can click the badge to scroll to it',
async ({ page, homePage, context }) => {
// Load the app with the working starter code
await context.addInitScript((code) => {
localStorage.setItem('persistCode', code)
}, TEST_CODE_LONG_WITH_ERROR_OUT_OF_VIEW)
test('When error is not in view you can click the badge to scroll to it', async ({
page,
homePage,
context,
}) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
// Load the app with the working starter code
await context.addInitScript((code) => {
localStorage.setItem('persistCode', code)
}, TEST_CODE_LONG_WITH_ERROR_OUT_OF_VIEW)
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await page.waitForTimeout(1000)
await page.waitForTimeout(1000)
// Ensure badge is present
const codePaneButtonHolder = page.locator('#code-button-holder')
await expect(codePaneButtonHolder).toContainText('notification')
// Ensure badge is present
const codePaneButtonHolder = page.locator('#code-button-holder')
await expect(codePaneButtonHolder).toContainText('notification')
// Ensure we have no errors in the gutter, since error out of view.
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
// Ensure we have no errors in the gutter, since error out of view.
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
// Click the badge.
const badge = page.locator('#code-badge')
await expect(badge).toBeVisible()
await badge.click()
// Click the badge.
const badge = page.locator('#code-badge')
await expect(badge).toBeVisible()
await badge.click()
// Ensure we have an error diagnostic.
await expect(page.locator('.cm-lint-marker-error').first()).toBeVisible()
// Ensure we have an error diagnostic.
await expect(page.locator('.cm-lint-marker-error').first()).toBeVisible()
// Hover over the error to see the error message
await page.hover('.cm-lint-marker-error')
await expect(
page
.getByText(
'Modeling command failed: [ApiError { error_code: InternalEngine, message: "Solid3D revolve failed: sketch profile must lie entirely on one side of the revolution axis" }]'
)
.first()
).toBeVisible()
}
)
// Hover over the error to see the error message
await page.hover('.cm-lint-marker-error')
await expect(
page
.getByText(
'Modeling command failed: [ApiError { error_code: InternalEngine, message: "Solid3D revolve failed: sketch profile must lie entirely on one side of the revolution axis" }]'
)
.first()
).toBeVisible()
})
test('When error is not in view WITH LINTS you can click the badge to scroll to it', async ({
context,

View File

@ -47,7 +47,8 @@ test.describe('Command bar tests', { tag: ['@skipWin'] }, () => {
})
// TODO: fix this test after the electron migration
test.fixme('Fillet from command bar', async ({ page, homePage }) => {
test('Fillet from command bar', async ({ page, homePage }) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',

View File

@ -635,14 +635,16 @@ test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
})
test.fixme(
'error with 2 source ranges gets 2 diagnostics',
async ({ page, homePage }) => {
const u = await getUtils(page)
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`length = .750
test('error with 2 source ranges gets 2 diagnostics', async ({
page,
homePage,
}) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
const u = await getUtils(page)
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`length = .750
width = 0.500
height = 0.500
dia = 4
@ -657,53 +659,52 @@ test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
return squareHoleSketch
}
`
)
})
await page.setBodyDimensions({ width: 1000, height: 500 })
)
})
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await page.waitForTimeout(1000)
await homePage.goToModelingScene()
await u.waitForPageLoad()
await page.waitForTimeout(1000)
await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel()
await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel()
// check no error to begin with
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
// check no error to begin with
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
// Click on the bottom of the code editor to add a new line
await u.codeLocator.click()
await page.keyboard.press('ArrowDown')
await page.keyboard.press('ArrowDown')
await page.keyboard.press('ArrowDown')
await page.keyboard.press('ArrowDown')
await page.keyboard.press('ArrowDown')
await page.keyboard.press('ArrowDown')
await page.keyboard.press('ArrowDown')
await page.keyboard.press('ArrowDown')
await page.keyboard.press('ArrowDown')
await page.keyboard.press('ArrowDown')
await page.keyboard.press('ArrowDown')
await page.keyboard.press('ArrowDown')
await page.keyboard.press('ArrowDown')
await page.keyboard.press('Enter')
await page.keyboard.type(`extrusion = startSketchOn('XY')
// Click on the bottom of the code editor to add a new line
await u.codeLocator.click()
await page.keyboard.press('ArrowDown')
await page.keyboard.press('ArrowDown')
await page.keyboard.press('ArrowDown')
await page.keyboard.press('ArrowDown')
await page.keyboard.press('ArrowDown')
await page.keyboard.press('ArrowDown')
await page.keyboard.press('ArrowDown')
await page.keyboard.press('ArrowDown')
await page.keyboard.press('ArrowDown')
await page.keyboard.press('ArrowDown')
await page.keyboard.press('ArrowDown')
await page.keyboard.press('ArrowDown')
await page.keyboard.press('ArrowDown')
await page.keyboard.press('Enter')
await page.keyboard.type(`extrusion = startSketchOn('XY')
|> circle(center: [0, 0], radius: dia/2)
|> hole(squareHole(length, width, height), %)
|> extrude(length = height)`)
// error in gutter
await expect(page.locator('.cm-lint-marker-error').first()).toBeVisible()
await page.hover('.cm-lint-marker-error:first-child')
await expect(
page.getByText('Expected 2 arguments, got 3').first()
).toBeVisible()
// error in gutter
await expect(page.locator('.cm-lint-marker-error').first()).toBeVisible()
await page.hover('.cm-lint-marker-error:first-child')
await expect(
page.getByText('Expected 2 arguments, got 3').first()
).toBeVisible()
// Make sure there are two diagnostics
await expect(page.locator('.cm-lint-marker-error')).toHaveCount(2)
}
)
// Make sure there are two diagnostics
await expect(page.locator('.cm-lint-marker-error')).toHaveCount(2)
})
test('if your kcl gets an error from the engine it is inlined', async ({
context,
page,
@ -1121,10 +1122,11 @@ test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
}
)
test.fixme(
test(
`Can use the import stdlib function on a local OBJ file`,
{ tag: '@electron' },
async ({ page, context }, testInfo) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
await context.folderSetupFn(async (dir) => {
const bracketDir = join(dir, 'cube')
await fsp.mkdir(bracketDir, { recursive: true })

View File

@ -266,12 +266,13 @@ test.describe('when using the file tree to', () => {
}
)
test.fixme(
test(
'loading small file, then large, then back to small',
{
tag: '@electron',
},
async ({ page }, testInfo) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
const {
panesOpen,
pasteCodeInEditor,

View File

@ -319,237 +319,240 @@ test.describe('Onboarding tests', () => {
// (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',
async ({ context, page, homePage, tronApp }) => {
if (!tronApp) {
fail()
}
await tronApp.cleanProjectDir({
app: {
onboarding_status: '',
},
})
// Override beforeEach test setup
await context.addInitScript(
async ({ settingsKey, settings }) => {
localStorage.setItem(settingsKey, settings)
},
{
settingsKey: TEST_SETTINGS_KEY,
settings: settingsToToml({
settings: TEST_SETTINGS_ONBOARDING_USER_MENU,
}),
}
)
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
// 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')
// 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",
async ({ context, page, homePage, tronApp }) => {
if (!tronApp) {
fail()
}
await tronApp.cleanProjectDir({
app: {
onboarding_status: '',
},
})
// 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: settingsToToml({
settings: TEST_SETTINGS_ONBOARDING_USER_MENU,
}),
}
)
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(
'Restarting onboarding on desktop takes one attempt',
async ({ context, page, tronApp }) => {
test('Avatar text updates depending on image load success', async ({
context,
page,
homePage,
tronApp,
}) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
if (!tronApp) {
fail()
}
await tronApp.cleanProjectDir({
app: {
onboarding_status: 'dismissed',
onboarding_status: '',
},
})
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')
)
})
// Override beforeEach test setup
await context.addInitScript(
async ({ settingsKey, settings }) => {
localStorage.setItem(settingsKey, settings)
},
{
settingsKey: TEST_SETTINGS_KEY,
settings: settingsToToml({
settings: TEST_SETTINGS_ONBOARDING_USER_MENU,
}),
}
)
// Our constants
const u = await getUtils(page)
const projectCard = page.getByText('router-template-slate')
const helpMenuButton = page.getByRole('button', {
name: 'Help and resources',
})
const restartOnboardingButton = page.getByRole('button', {
name: 'Reset onboarding',
})
const nextButton = page.getByTestId('onboarding-next')
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
const tutorialProjectIndicator = page
.getByTestId('project-sidebar-toggle')
.filter({ hasText: 'Tutorial Project 00' })
const tutorialModalText = page.getByText('Welcome to Modeling App!')
const tutorialDismissButton = page.getByRole('button', { name: 'Dismiss' })
const userMenuButton = page.getByTestId('user-sidebar-toggle')
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',
})
// 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)
await test.step('Navigate into project', async () => {
await expect(
page.getByRole('heading', { name: 'Your Projects' })
).toBeVisible()
await expect(projectCard).toBeVisible()
await projectCard.click()
await u.waitForPageLoad()
})
// 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 test.step('Restart the onboarding from help menu', async () => {
await helpMenuButton.click()
await restartOnboardingButton.click()
await nextButton.hover()
await nextButton.click()
})
await test.step('Confirm that the onboarding has restarted', async () => {
await expect(tutorialProjectIndicator).toBeVisible()
await expect(tutorialModalText).toBeVisible()
// Make sure the model loaded
const XYPlanePoint = { x: 988, y: 523 } as const
const modelColor: [number, number, number] = [76, 76, 76]
await page.mouse.move(XYPlanePoint.x, XYPlanePoint.y)
await expectPixelColor(page, modelColor, XYPlanePoint, 8)
await tutorialDismissButton.click()
// Make sure model still there.
await expectPixelColor(page, modelColor, XYPlanePoint, 8)
})
await test.step('Clear code and restart onboarding from settings', async () => {
await u.openKclCodePanel()
await expect(u.codeLocator).toContainText('// Shelf Bracket')
await u.codeLocator.selectText()
await u.codeLocator.fill('')
await test.step('Navigate to settings', async () => {
await userMenuButton.click()
await userMenuSettingsButton.click()
await expect(settingsHeading).toBeVisible()
await expect(restartOnboardingSettingsButton).toBeVisible()
// 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!',
})
await restartOnboardingSettingsButton.click()
// Since the code is empty, we should not see the confirmation dialog
await expect(nextButton).not.toBeVisible()
await expect(tutorialProjectIndicator).toBeVisible()
await expect(tutorialModalText).toBeVisible()
})
// 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 ({
context,
page,
homePage,
tronApp,
}) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
if (!tronApp) {
fail()
}
await tronApp.cleanProjectDir({
app: {
onboarding_status: '',
},
})
// 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: settingsToToml({
settings: TEST_SETTINGS_ONBOARDING_USER_MENU,
}),
}
)
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('Restarting onboarding on desktop takes one attempt', async ({
context,
page,
tronApp,
}) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
if (!tronApp) {
fail()
}
)
await tronApp.cleanProjectDir({
app: {
onboarding_status: 'dismissed',
},
})
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
const u = await getUtils(page)
const projectCard = page.getByText('router-template-slate')
const helpMenuButton = page.getByRole('button', {
name: 'Help and resources',
})
const restartOnboardingButton = page.getByRole('button', {
name: 'Reset onboarding',
})
const nextButton = page.getByTestId('onboarding-next')
const tutorialProjectIndicator = page
.getByTestId('project-sidebar-toggle')
.filter({ hasText: 'Tutorial Project 00' })
const tutorialModalText = page.getByText('Welcome to Modeling App!')
const tutorialDismissButton = page.getByRole('button', { name: 'Dismiss' })
const userMenuButton = page.getByTestId('user-sidebar-toggle')
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',
})
await test.step('Navigate into project', async () => {
await expect(
page.getByRole('heading', { name: 'Your Projects' })
).toBeVisible()
await expect(projectCard).toBeVisible()
await projectCard.click()
await u.waitForPageLoad()
})
await test.step('Restart the onboarding from help menu', async () => {
await helpMenuButton.click()
await restartOnboardingButton.click()
await nextButton.hover()
await nextButton.click()
})
await test.step('Confirm that the onboarding has restarted', async () => {
await expect(tutorialProjectIndicator).toBeVisible()
await expect(tutorialModalText).toBeVisible()
// Make sure the model loaded
const XYPlanePoint = { x: 988, y: 523 } as const
const modelColor: [number, number, number] = [76, 76, 76]
await page.mouse.move(XYPlanePoint.x, XYPlanePoint.y)
await expectPixelColor(page, modelColor, XYPlanePoint, 8)
await tutorialDismissButton.click()
// Make sure model still there.
await expectPixelColor(page, modelColor, XYPlanePoint, 8)
})
await test.step('Clear code and restart onboarding from settings', async () => {
await u.openKclCodePanel()
await expect(u.codeLocator).toContainText('// Shelf Bracket')
await u.codeLocator.selectText()
await u.codeLocator.fill('')
await test.step('Navigate to settings', async () => {
await userMenuButton.click()
await userMenuSettingsButton.click()
await expect(settingsHeading).toBeVisible()
await expect(restartOnboardingSettingsButton).toBeVisible()
})
await restartOnboardingSettingsButton.click()
// Since the code is empty, we should not see the confirmation dialog
await expect(nextButton).not.toBeVisible()
await expect(tutorialProjectIndicator).toBeVisible()
await expect(tutorialModalText).toBeVisible()
})
})

View File

@ -850,157 +850,160 @@ openSketch = startSketchOn('XY')
})
})
test.fixme(
`Shift-click to select and deselect sketch segments`,
async ({ page, homePage, scene, editor }) => {
// Locators
const firstPointLocation = { x: 200, y: 100 }
const secondPointLocation = { x: 800, y: 100 }
const thirdPointLocation = { x: 800, y: 400 }
const fristSegmentLocation = { x: 750, y: 100 }
const secondSegmentLocation = { x: 800, y: 150 }
const planeLocation = { x: 700, y: 200 }
test(`Shift-click to select and deselect sketch segments`, async ({
page,
homePage,
scene,
editor,
}) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
// Locators
const firstPointLocation = { x: 200, y: 100 }
const secondPointLocation = { x: 800, y: 100 }
const thirdPointLocation = { x: 800, y: 400 }
const fristSegmentLocation = { x: 750, y: 100 }
const secondSegmentLocation = { x: 800, y: 150 }
const planeLocation = { x: 700, y: 200 }
// Click helpers
const [clickFirstPoint] = scene.makeMouseHelpers(
firstPointLocation.x,
firstPointLocation.y
)
const [clickSecondPoint] = scene.makeMouseHelpers(
secondPointLocation.x,
secondPointLocation.y
)
const [clickThirdPoint] = scene.makeMouseHelpers(
thirdPointLocation.x,
thirdPointLocation.y
)
const [clickFirstSegment] = scene.makeMouseHelpers(
fristSegmentLocation.x,
fristSegmentLocation.y
)
const [clickSecondSegment] = scene.makeMouseHelpers(
secondSegmentLocation.x,
secondSegmentLocation.y
)
const [clickPlane] = scene.makeMouseHelpers(
planeLocation.x,
planeLocation.y
)
// Click helpers
const [clickFirstPoint] = scene.makeMouseHelpers(
firstPointLocation.x,
firstPointLocation.y
)
const [clickSecondPoint] = scene.makeMouseHelpers(
secondPointLocation.x,
secondPointLocation.y
)
const [clickThirdPoint] = scene.makeMouseHelpers(
thirdPointLocation.x,
thirdPointLocation.y
)
const [clickFirstSegment] = scene.makeMouseHelpers(
fristSegmentLocation.x,
fristSegmentLocation.y
)
const [clickSecondSegment] = scene.makeMouseHelpers(
secondSegmentLocation.x,
secondSegmentLocation.y
)
const [clickPlane] = scene.makeMouseHelpers(
planeLocation.x,
planeLocation.y
)
// Colors
const edgeColorWhite: [number, number, number] = [220, 220, 220]
const edgeColorBlue: [number, number, number] = [20, 20, 200]
const backgroundColor: [number, number, number] = [30, 30, 30]
const tolerance = 40
const timeout = 150
// Colors
const edgeColorWhite: [number, number, number] = [220, 220, 220]
const edgeColorBlue: [number, number, number] = [20, 20, 200]
const backgroundColor: [number, number, number] = [30, 30, 30]
const tolerance = 40
const timeout = 150
// Setup
await test.step(`Initial test setup`, async () => {
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
// Setup
await test.step(`Initial test setup`, async () => {
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
// Wait for the scene and stream to load
// Wait for the scene and stream to load
await scene.expectPixelColor(
backgroundColor,
secondPointLocation,
tolerance
)
})
await test.step('Select and deselect a single sketch segment', async () => {
await test.step('Get into sketch mode', async () => {
await editor.closePane()
await page.waitForTimeout(timeout)
await page.getByRole('button', { name: 'Start Sketch' }).click()
await page.waitForTimeout(timeout)
await clickPlane()
await page.waitForTimeout(1000)
})
await test.step('Draw sketch', async () => {
await clickFirstPoint()
await page.waitForTimeout(timeout)
await clickSecondPoint()
await page.waitForTimeout(timeout)
await clickThirdPoint()
await page.waitForTimeout(timeout)
})
await test.step('Deselect line tool', async () => {
const btnLine = page.getByTestId('line')
const btnLineAriaPressed = await btnLine.getAttribute('aria-pressed')
if (btnLineAriaPressed === 'true') {
await btnLine.click()
}
await page.waitForTimeout(timeout)
})
await test.step('Select the first segment', async () => {
await page.waitForTimeout(timeout)
await clickFirstSegment()
await page.waitForTimeout(timeout)
await scene.expectPixelColor(
backgroundColor,
secondPointLocation,
edgeColorBlue,
fristSegmentLocation,
tolerance
)
await scene.expectPixelColor(
edgeColorWhite,
secondSegmentLocation,
tolerance
)
})
await test.step('Select and deselect a single sketch segment', async () => {
await test.step('Get into sketch mode', async () => {
await editor.closePane()
await page.waitForTimeout(timeout)
await page.getByRole('button', { name: 'Start Sketch' }).click()
await page.waitForTimeout(timeout)
await clickPlane()
await page.waitForTimeout(1000)
})
await test.step('Draw sketch', async () => {
await clickFirstPoint()
await page.waitForTimeout(timeout)
await clickSecondPoint()
await page.waitForTimeout(timeout)
await clickThirdPoint()
await page.waitForTimeout(timeout)
})
await test.step('Deselect line tool', async () => {
const btnLine = page.getByTestId('line')
const btnLineAriaPressed = await btnLine.getAttribute('aria-pressed')
if (btnLineAriaPressed === 'true') {
await btnLine.click()
}
await page.waitForTimeout(timeout)
})
await test.step('Select the first segment', async () => {
await page.waitForTimeout(timeout)
await clickFirstSegment()
await page.waitForTimeout(timeout)
await scene.expectPixelColor(
edgeColorBlue,
fristSegmentLocation,
tolerance
)
await scene.expectPixelColor(
edgeColorWhite,
secondSegmentLocation,
tolerance
)
})
await test.step('Select the second segment (Shift-click)', async () => {
await page.keyboard.down('Shift')
await page.waitForTimeout(timeout)
await clickSecondSegment()
await page.waitForTimeout(timeout)
await page.keyboard.up('Shift')
await scene.expectPixelColor(
edgeColorBlue,
fristSegmentLocation,
tolerance
)
await scene.expectPixelColor(
edgeColorBlue,
secondSegmentLocation,
tolerance
)
})
await test.step('Deselect the first segment', async () => {
await page.keyboard.down('Shift')
await page.waitForTimeout(timeout)
await clickFirstSegment()
await page.waitForTimeout(timeout)
await page.keyboard.up('Shift')
await scene.expectPixelColor(
edgeColorWhite,
fristSegmentLocation,
tolerance
)
await scene.expectPixelColor(
edgeColorBlue,
secondSegmentLocation,
tolerance
)
})
await test.step('Deselect the second segment', async () => {
await page.keyboard.down('Shift')
await page.waitForTimeout(timeout)
await clickSecondSegment()
await page.waitForTimeout(timeout)
await page.keyboard.up('Shift')
await scene.expectPixelColor(
edgeColorWhite,
fristSegmentLocation,
tolerance
)
await scene.expectPixelColor(
edgeColorWhite,
secondSegmentLocation,
tolerance
)
})
await test.step('Select the second segment (Shift-click)', async () => {
await page.keyboard.down('Shift')
await page.waitForTimeout(timeout)
await clickSecondSegment()
await page.waitForTimeout(timeout)
await page.keyboard.up('Shift')
await scene.expectPixelColor(
edgeColorBlue,
fristSegmentLocation,
tolerance
)
await scene.expectPixelColor(
edgeColorBlue,
secondSegmentLocation,
tolerance
)
})
}
)
await test.step('Deselect the first segment', async () => {
await page.keyboard.down('Shift')
await page.waitForTimeout(timeout)
await clickFirstSegment()
await page.waitForTimeout(timeout)
await page.keyboard.up('Shift')
await scene.expectPixelColor(
edgeColorWhite,
fristSegmentLocation,
tolerance
)
await scene.expectPixelColor(
edgeColorBlue,
secondSegmentLocation,
tolerance
)
})
await test.step('Deselect the second segment', async () => {
await page.keyboard.down('Shift')
await page.waitForTimeout(timeout)
await clickSecondSegment()
await page.waitForTimeout(timeout)
await page.keyboard.up('Shift')
await scene.expectPixelColor(
edgeColorWhite,
fristSegmentLocation,
tolerance
)
await scene.expectPixelColor(
edgeColorWhite,
secondSegmentLocation,
tolerance
)
})
})
})
test(`Offset plane point-and-click`, async ({
context,

View File

@ -1244,10 +1244,11 @@ test(
}
)
test.fixme(
test(
'Deleting projects, can delete individual project, can still create projects after deleting all',
{ tag: '@electron' },
async ({ context, page }, testInfo) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
const projectData = [
['router-template-slate', 'cylinder.kcl'],
['bracket', 'focusrite_scarlett_mounting_braket.kcl'],
@ -1466,10 +1467,11 @@ test(
}
)
test.fixme(
test(
'When the project folder is empty, user can create new project and open it.',
{ tag: '@electron' },
async ({ page }, testInfo) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 })
@ -2050,10 +2052,11 @@ test(
)
// Flaky
test.fixme(
test(
'Original project name persist after onboarding',
{ tag: '@electron' },
async ({ page }, testInfo) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
await page.setBodyDimensions({ width: 1200, height: 500 })
const getAllProjects = () => page.getByTestId('project-link').all()

View File

@ -196,60 +196,65 @@ test.describe('Prompt-to-edit tests', { tag: '@skipWin' }, () => {
})
})
test.fixme(
`manual code selection rename`,
async ({ context, homePage, cmdBar, editor, page, scene }) => {
const body1CapCoords = { x: 571, y: 311 }
test(`manual code selection rename`, async ({
context,
homePage,
cmdBar,
editor,
page,
scene,
}) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
const body1CapCoords = { x: 571, y: 311 }
await context.addInitScript((file) => {
localStorage.setItem('persistCode', file)
}, file)
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await context.addInitScript((file) => {
localStorage.setItem('persistCode', file)
}, file)
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
const submittingToast = page.getByText('Submitting to Text-to-CAD API...')
const successToast = page.getByText('Prompt to edit successful')
const acceptBtn = page.getByRole('button', { name: 'checkmark Accept' })
const submittingToast = page.getByText('Submitting to Text-to-CAD API...')
const successToast = page.getByText('Prompt to edit successful')
const acceptBtn = page.getByRole('button', { name: 'checkmark Accept' })
await test.step('wait for scene to load and select code in editor', async () => {
// Find and select the text "sketch002" in the editor
await editor.selectText('sketch002')
await test.step('wait for scene to load and select code in editor', async () => {
// Find and select the text "sketch002" in the editor
await editor.selectText('sketch002')
// Verify the selection was made
await editor.expectState({
highlightedCode: '',
activeLines: ["sketch002 = startSketchOn('XZ')"],
diagnostics: [],
})
// Verify the selection was made
await editor.expectState({
highlightedCode: '',
activeLines: ["sketch002 = startSketchOn('XZ')"],
diagnostics: [],
})
})
await test.step('fire off edit prompt', async () => {
await scene.expectPixelColor([134, 134, 134], body1CapCoords, 15)
await cmdBar.openCmdBar('promptToEdit')
await page
.getByTestId('cmd-bar-arg-value')
.fill('Please rename to mySketch001')
await page.waitForTimeout(100)
await cmdBar.progressCmdBar()
await expect(submittingToast).toBeVisible()
await expect(submittingToast).not.toBeVisible({
timeout: 2 * 60_000,
})
await expect(successToast).toBeVisible()
await test.step('fire off edit prompt', async () => {
await scene.expectPixelColor([134, 134, 134], body1CapCoords, 15)
await cmdBar.openCmdBar('promptToEdit')
await page
.getByTestId('cmd-bar-arg-value')
.fill('Please rename to mySketch001')
await page.waitForTimeout(100)
await cmdBar.progressCmdBar()
await expect(submittingToast).toBeVisible()
await expect(submittingToast).not.toBeVisible({
timeout: 2 * 60_000,
})
await expect(successToast).toBeVisible()
})
await test.step('verify rename change and accept it', async () => {
await editor.expectEditor.toContain('mySketch001 = startSketchOn')
await editor.expectEditor.not.toContain('sketch002 = startSketchOn')
await editor.expectEditor.toContain(
'extrude002 = extrude(mySketch001, length = 50)'
)
await test.step('verify rename change and accept it', async () => {
await editor.expectEditor.toContain('mySketch001 = startSketchOn')
await editor.expectEditor.not.toContain('sketch002 = startSketchOn')
await editor.expectEditor.toContain(
'extrude002 = extrude(mySketch001, length = 50)'
)
await acceptBtn.click()
await expect(successToast).not.toBeVisible()
})
}
)
await acceptBtn.click()
await expect(successToast).not.toBeVisible()
})
})
test('multiple body selections', async ({
context,

View File

@ -483,10 +483,11 @@ extrude001 = extrude(sketch001, length = 50)
}
)
test.fixme(
test(
`Network health indicator only appears in modeling view`,
{ tag: '@electron' },
async ({ context, page }, testInfo) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
await context.folderSetupFn(async (dir) => {
const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true })

View File

@ -188,7 +188,8 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
page.getByRole('button', { name: 'Start Sketch' })
).toBeVisible()
})
test.fixme('Can edit segments by dragging their handles', () => {
test('Can edit segments by dragging their handles', () => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
const doEditSegmentsByDraggingHandle = async (
page: Page,
homePage: HomePageFixture,
@ -1086,107 +1087,108 @@ profile001 = startProfileAt([${roundOff(scale * 69.6)}, ${roundOff(
)
})
// TODO: fix after electron migration is merged
test.fixme(
'empty-scene default-planes act as expected',
async ({ page, homePage }) => {
/**
* Tests the following things
* 1) The the planes are there on load because the scene is empty
* 2) The planes don't changes color when hovered initially
* 3) Putting something in the scene makes the planes hidden
* 4) Removing everything from the scene shows the plans again
* 3) Once "start sketch" is click, the planes do respond to hovers
* 4) Selecting a plan works as expected, i.e. sketch mode
* 5) Reloading the scene with something already in the scene means the planes are hidden
*/
test('empty-scene default-planes act as expected', async ({
page,
homePage,
}) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
/**
* Tests the following things
* 1) The the planes are there on load because the scene is empty
* 2) The planes don't changes color when hovered initially
* 3) Putting something in the scene makes the planes hidden
* 4) Removing everything from the scene shows the plans again
* 3) Once "start sketch" is click, the planes do respond to hovers
* 4) Selecting a plan works as expected, i.e. sketch mode
* 5) Reloading the scene with something already in the scene means the planes are hidden
*/
const u = await getUtils(page)
await homePage.goToModelingScene()
const u = await getUtils(page)
await homePage.goToModelingScene()
await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel()
await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel()
const XYPlanePoint = { x: 774, y: 116 } as const
const unHoveredColor: [number, number, number] = [47, 47, 93]
expect(
await u.getGreatestPixDiff(XYPlanePoint, unHoveredColor)
).toBeLessThan(8)
const XYPlanePoint = { x: 774, y: 116 } as const
const unHoveredColor: [number, number, number] = [47, 47, 93]
expect(
await u.getGreatestPixDiff(XYPlanePoint, unHoveredColor)
).toBeLessThan(8)
await page.mouse.move(XYPlanePoint.x, XYPlanePoint.y)
await page.waitForTimeout(200)
await page.mouse.move(XYPlanePoint.x, XYPlanePoint.y)
await page.waitForTimeout(200)
// color should not change for having been hovered
expect(
await u.getGreatestPixDiff(XYPlanePoint, unHoveredColor)
).toBeLessThan(8)
// color should not change for having been hovered
expect(
await u.getGreatestPixDiff(XYPlanePoint, unHoveredColor)
).toBeLessThan(8)
await u.openAndClearDebugPanel()
await u.openAndClearDebugPanel()
await u.codeLocator.fill(`sketch001 = startSketchOn('XY')
await u.codeLocator.fill(`sketch001 = startSketchOn('XY')
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20])
|> xLine(length = -20)
`)
await u.expectCmdLog('[data-message-type="execution-done"]')
await u.expectCmdLog('[data-message-type="execution-done"]')
const noPlanesColor: [number, number, number] = [30, 30, 30]
expect(
await u.getGreatestPixDiff(XYPlanePoint, noPlanesColor)
).toBeLessThan(3)
const noPlanesColor: [number, number, number] = [30, 30, 30]
expect(
await u.getGreatestPixDiff(XYPlanePoint, noPlanesColor)
).toBeLessThan(3)
await u.clearCommandLogs()
await u.removeCurrentCode()
await u.expectCmdLog('[data-message-type="execution-done"]')
await u.clearCommandLogs()
await u.removeCurrentCode()
await u.expectCmdLog('[data-message-type="execution-done"]')
await expect
.poll(() => u.getGreatestPixDiff(XYPlanePoint, unHoveredColor), {
timeout: 5_000,
})
.toBeLessThan(8)
await expect
.poll(() => u.getGreatestPixDiff(XYPlanePoint, unHoveredColor), {
timeout: 5_000,
})
.toBeLessThan(8)
// click start Sketch
await page.getByRole('button', { name: 'Start Sketch' }).click()
await page.mouse.move(XYPlanePoint.x, XYPlanePoint.y, { steps: 50 })
const hoveredColor: [number, number, number] = [93, 93, 127]
// now that we're expecting the user to select a plan, it does respond to hover
await expect
.poll(() => u.getGreatestPixDiff(XYPlanePoint, hoveredColor))
.toBeLessThan(8)
// click start Sketch
await page.getByRole('button', { name: 'Start Sketch' }).click()
await page.mouse.move(XYPlanePoint.x, XYPlanePoint.y, { steps: 50 })
const hoveredColor: [number, number, number] = [93, 93, 127]
// now that we're expecting the user to select a plan, it does respond to hover
await expect
.poll(() => u.getGreatestPixDiff(XYPlanePoint, hoveredColor))
.toBeLessThan(8)
await page.mouse.click(XYPlanePoint.x, XYPlanePoint.y)
await page.waitForTimeout(600)
await page.mouse.click(XYPlanePoint.x, XYPlanePoint.y)
await page.waitForTimeout(600)
await page.mouse.click(XYPlanePoint.x, XYPlanePoint.y)
await page.waitForTimeout(200)
await page.mouse.click(XYPlanePoint.x + 50, XYPlanePoint.y + 50)
await expect(u.codeLocator).toHaveText(`sketch001 = startSketchOn('XZ')
await page.mouse.click(XYPlanePoint.x, XYPlanePoint.y)
await page.waitForTimeout(200)
await page.mouse.click(XYPlanePoint.x + 50, XYPlanePoint.y + 50)
await expect(u.codeLocator).toHaveText(`sketch001 = startSketchOn('XZ')
|> startProfileAt([11.8, 9.09], %)
|> line(end = [3.39, -3.39])
`)
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`sketch001 = startSketchOn('XZ')
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`sketch001 = startSketchOn('XZ')
|> startProfileAt([11.8, 9.09], %)
|> line(end = [3.39, -3.39])
`
)
})
)
})
await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel()
await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel()
// expect there to be no planes on load since there's something in the scene
expect(
await u.getGreatestPixDiff(XYPlanePoint, noPlanesColor)
).toBeLessThan(3)
}
)
// expect there to be no planes on load since there's something in the scene
expect(
await u.getGreatestPixDiff(XYPlanePoint, noPlanesColor)
).toBeLessThan(3)
})
test('Can attempt to sketch on revolved face', async ({ page, homePage }) => {
const u = await getUtils(page)
@ -1460,10 +1462,11 @@ test.describe(`Sketching with offset planes`, () => {
})
test.describe('multi-profile sketching', () => {
test.fixme(
test(
`test it removes half-finished expressions when changing tools in sketch mode`,
{ tag: ['@skipWin'] },
async ({ context, page, scene, toolbar, editor, homePage, cmdBar }) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
// We seed the scene with a single offset plane
await context.addInitScript(() => {
localStorage.setItem(
@ -2852,13 +2855,18 @@ loft([profile001, profile002])
)
}
)
test.fixme(
'Can enter sketch loft edges offsetPlane and continue sketch',
async ({ scene, toolbar, editor, page, homePage }) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`sketch001 = startSketchOn('XZ')
test('Can enter sketch loft edges offsetPlane and continue sketch', async ({
scene,
toolbar,
editor,
page,
homePage,
}) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`sketch001 = startSketchOn('XZ')
profile001 = startProfileAt([34, 42.66], sketch001)
|> line(end = [102.65, 151.99])
|> line(end = [76, -138.66])
@ -2874,51 +2882,50 @@ profile002 = startProfileAt([39.43, 172.21], sketch002)
loft([profile001, profile002])
`
)
})
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).not.toBeDisabled()
const topProfileEdgeClickCoords = { x: 602, y: 185 } as const
const [topProfileEdgeClick] = scene.makeMouseHelpers(
topProfileEdgeClickCoords.x,
topProfileEdgeClickCoords.y
)
const [sideProfileEdgeClick] = scene.makeMouseHelpers(788, 188)
})
const [rect1Crn1] = scene.makeMouseHelpers(592, 283)
const [rect1Crn2] = scene.makeMouseHelpers(797, 268)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).not.toBeDisabled()
await scene.moveCameraTo(
{ x: 8171, y: -7740, z: 1624 },
{ x: 3302, y: -627, z: 2892 }
)
const topProfileEdgeClickCoords = { x: 602, y: 185 } as const
const [topProfileEdgeClick] = scene.makeMouseHelpers(
topProfileEdgeClickCoords.x,
topProfileEdgeClickCoords.y
)
const [sideProfileEdgeClick] = scene.makeMouseHelpers(788, 188)
await topProfileEdgeClick()
await page.waitForTimeout(300)
await toolbar.editSketch()
await page.waitForTimeout(600)
await sideProfileEdgeClick()
await page.waitForTimeout(300)
await scene.expectPixelColor(TEST_COLORS.BLUE, { x: 788, y: 188 }, 15)
const [rect1Crn1] = scene.makeMouseHelpers(592, 283)
const [rect1Crn2] = scene.makeMouseHelpers(797, 268)
await toolbar.rectangleBtn.click()
await page.waitForTimeout(100)
await rect1Crn1()
await editor.expectEditor.toContain(
`profile003 = startProfileAt([47.76, -17.13], plane001)`
)
await rect1Crn2()
await editor.expectEditor.toContain(
`angledLine([0, 106.42], %, $rectangleSegmentA001)`
)
await page.waitForTimeout(100)
}
)
await scene.moveCameraTo(
{ x: 8171, y: -7740, z: 1624 },
{ x: 3302, y: -627, z: 2892 }
)
await topProfileEdgeClick()
await page.waitForTimeout(300)
await toolbar.editSketch()
await page.waitForTimeout(600)
await sideProfileEdgeClick()
await page.waitForTimeout(300)
await scene.expectPixelColor(TEST_COLORS.BLUE, { x: 788, y: 188 }, 15)
await toolbar.rectangleBtn.click()
await page.waitForTimeout(100)
await rect1Crn1()
await editor.expectEditor.toContain(
`profile003 = startProfileAt([47.76, -17.13], plane001)`
)
await rect1Crn2()
await editor.expectEditor.toContain(
`angledLine([0, 106.42], %, $rectangleSegmentA001)`
)
await page.waitForTimeout(100)
})
})
// Regression test for https://github.com/KittyCAD/modeling-app/issues/4891

View File

@ -36,10 +36,11 @@ test.setTimeout(60_000)
// a snapshot of it feels weird. I'd rather our regular tests fail.
// The primary failure is doExport now relies on the filesystem. We can follow
// up with another PR if we want this back.
test.skip(
test(
'exports of each format should work',
{ tag: ['@snapshot', '@skipWin', '@skipMacos'] },
async ({ page, context, scene, cmdBar, tronApp }) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
if (!tronApp) {
fail()
}
@ -406,9 +407,6 @@ test(
'Draft segments should look right',
{ tag: '@snapshot' },
async ({ page, scene, toolbar }) => {
// FIXME: Skip on macos its being weird.
// test.skip(process.platform === 'darwin', 'Skip on macos')
const u = await getUtils(page)
await page.setViewportSize({ width: 1200, height: 500 })
const PUR = 400 / 37.5 //pixeltoUnitRatio
@ -585,9 +583,6 @@ test(
'Draft circle should look right',
{ tag: '@snapshot' },
async ({ page, context, cmdBar, scene }) => {
// FIXME: Skip on macos its being weird.
// test.skip(process.platform === 'darwin', 'Skip on macos')
const u = await getUtils(page)
await page.setViewportSize({ width: 1200, height: 500 })
const PUR = 400 / 37.5 //pixeltoUnitRatio
@ -952,9 +947,6 @@ test(
)
test.describe('Grid visibility', { tag: '@snapshot' }, () => {
// FIXME: Skip on macos its being weird.
// test.skip(process.platform === 'darwin', 'Skip on macos')
test('Grid turned off to on via command bar', async ({
page,
cmdBar,
@ -1097,7 +1089,8 @@ test.describe('Grid visibility', { tag: '@snapshot' }, () => {
})
})
test.fixme('theme persists', async ({ page, context }) => {
test('theme persists', async ({ page, context }) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
const u = await getUtils(page)
await context.addInitScript(async () => {
localStorage.setItem(

View File

@ -3,11 +3,12 @@ import { commonPoints, getUtils } from './test-utils'
import { EngineCommand } from 'lang/std/artifactGraph'
import { uuidv4 } from 'lib/utils'
test.fixme('Test network and connection issues', () => {
test.describe('Test network and connection issues', () => {
test(
'simulate network down and network little widget',
{ tag: '@skipLocalEngine' },
async ({ page, homePage }) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 })
@ -84,6 +85,7 @@ test.fixme('Test network and connection issues', () => {
'Engine disconnect & reconnect in sketch mode',
{ tag: '@skipLocalEngine' },
async ({ page, homePage, toolbar }) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
const networkToggle = page.getByTestId('network-toggle')
const u = await getUtils(page)

View File

@ -179,169 +179,170 @@ test.describe('Testing Camera Movement', { tag: ['@skipWin'] }, () => {
})
// TODO: fix after electron migration is merged
test.fixme(
'Zoom should be consistent when exiting or entering sketches',
async ({ page, homePage }) => {
// start new sketch pan and zoom before exiting, when exiting the sketch should stay in the same place
// than zoom and pan outside of sketch mode and enter again and it should not change from where it is
// than again for sketching
test('Zoom should be consistent when exiting or entering sketches', async ({
page,
homePage,
}) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
// start new sketch pan and zoom before exiting, when exiting the sketch should stay in the same place
// than zoom and pan outside of sketch mode and enter again and it should not change from where it is
// than again for sketching
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 })
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await u.openDebugPanel()
await homePage.goToModelingScene()
await u.waitForPageLoad()
await u.openDebugPanel()
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).not.toBeDisabled()
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).toBeVisible()
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).not.toBeDisabled()
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).toBeVisible()
// click on "Start Sketch" button
await u.clearCommandLogs()
await page.getByRole('button', { name: 'Start Sketch' }).click()
// click on "Start Sketch" button
await u.clearCommandLogs()
await page.getByRole('button', { name: 'Start Sketch' }).click()
await page.waitForTimeout(100)
// select a plane
await page.mouse.click(700, 325)
let code = `sketch001 = startSketchOn('XY')`
await expect(u.codeLocator).toHaveText(code)
await u.closeDebugPanel()
await page.waitForTimeout(500) // TODO detect animation ending, or disable animation
// move the camera slightly
await page.keyboard.down('Shift')
await page.mouse.move(700, 300)
await page.mouse.down({ button: 'right' })
await page.mouse.move(800, 200)
await page.mouse.up({ button: 'right' })
await page.keyboard.up('Shift')
let y = 350,
x = 948
await u.canvasLocator.click({ position: { x: 783, y } })
code += `\n |> startProfileAt([8.12, -12.98], %)`
// await expect(u.codeLocator).toHaveText(code)
await u.canvasLocator.click({ position: { x, y } })
code += `\n |> line(end = [11.18, 0])`
// await expect(u.codeLocator).toHaveText(code)
await u.canvasLocator.click({ position: { x, y: 275 } })
code += `\n |> line(end = [0, 6.99])`
// await expect(u.codeLocator).toHaveText(code)
// click the line button
await page.getByRole('button', { name: 'line Line', exact: true }).click()
const hoverOverNothing = async () => {
// await u.canvasLocator.hover({position: {x: 700, y: 325}})
await page.mouse.move(700, 325)
await page.waitForTimeout(100)
// select a plane
await page.mouse.click(700, 325)
let code = `sketch001 = startSketchOn('XY')`
await expect(u.codeLocator).toHaveText(code)
await u.closeDebugPanel()
await page.waitForTimeout(500) // TODO detect animation ending, or disable animation
// move the camera slightly
await page.keyboard.down('Shift')
await page.mouse.move(700, 300)
await page.mouse.down({ button: 'right' })
await page.mouse.move(800, 200)
await page.mouse.up({ button: 'right' })
await page.keyboard.up('Shift')
let y = 350,
x = 948
await u.canvasLocator.click({ position: { x: 783, y } })
code += `\n |> startProfileAt([8.12, -12.98], %)`
// await expect(u.codeLocator).toHaveText(code)
await u.canvasLocator.click({ position: { x, y } })
code += `\n |> line(end = [11.18, 0])`
// await expect(u.codeLocator).toHaveText(code)
await u.canvasLocator.click({ position: { x, y: 275 } })
code += `\n |> line(end = [0, 6.99])`
// await expect(u.codeLocator).toHaveText(code)
// click the line button
await page.getByRole('button', { name: 'line Line', exact: true }).click()
const hoverOverNothing = async () => {
// await u.canvasLocator.hover({position: {x: 700, y: 325}})
await page.mouse.move(700, 325)
await page.waitForTimeout(100)
await expect(page.getByTestId('hover-highlight')).not.toBeVisible({
timeout: 10_000,
})
}
await expect(page.getByTestId('hover-highlight')).not.toBeVisible()
await page.waitForTimeout(200)
// hover over horizontal line
await u.canvasLocator.hover({ position: { x: 800, y } })
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await page.waitForTimeout(200)
await hoverOverNothing()
await page.waitForTimeout(200)
// hover over vertical line
await u.canvasLocator.hover({ position: { x, y: 325 } })
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
// click exit sketch
await page.getByRole('button', { name: 'Exit Sketch' }).click()
await page.waitForTimeout(400)
await hoverOverNothing()
await page.waitForTimeout(200)
// hover over horizontal line
await page.mouse.move(858, y, { steps: 5 })
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
// hover over vertical line
await page.mouse.move(x, 325)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
// hover over vertical line
await page.mouse.move(857, y)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
// now click it
await page.mouse.click(857, y)
await expect(
page.getByRole('button', { name: 'Edit Sketch' })
).toBeVisible()
await hoverOverNothing()
await page.getByRole('button', { name: 'Edit Sketch' }).click()
await page.waitForTimeout(400)
x = 975
y = 468
await page.waitForTimeout(100)
await page.mouse.move(x, 419, { steps: 5 })
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
await page.mouse.move(855, y)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
await page.getByRole('button', { name: 'Exit Sketch' }).click()
await page.waitForTimeout(200)
await hoverOverNothing()
await page.waitForTimeout(200)
await page.mouse.move(x, 419)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
await page.mouse.move(855, y)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
await expect(page.getByTestId('hover-highlight')).not.toBeVisible({
timeout: 10_000,
})
}
)
await expect(page.getByTestId('hover-highlight')).not.toBeVisible()
await page.waitForTimeout(200)
// hover over horizontal line
await u.canvasLocator.hover({ position: { x: 800, y } })
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await page.waitForTimeout(200)
await hoverOverNothing()
await page.waitForTimeout(200)
// hover over vertical line
await u.canvasLocator.hover({ position: { x, y: 325 } })
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
// click exit sketch
await page.getByRole('button', { name: 'Exit Sketch' }).click()
await page.waitForTimeout(400)
await hoverOverNothing()
await page.waitForTimeout(200)
// hover over horizontal line
await page.mouse.move(858, y, { steps: 5 })
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
// hover over vertical line
await page.mouse.move(x, 325)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
// hover over vertical line
await page.mouse.move(857, y)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
// now click it
await page.mouse.click(857, y)
await expect(
page.getByRole('button', { name: 'Edit Sketch' })
).toBeVisible()
await hoverOverNothing()
await page.getByRole('button', { name: 'Edit Sketch' }).click()
await page.waitForTimeout(400)
x = 975
y = 468
await page.waitForTimeout(100)
await page.mouse.move(x, 419, { steps: 5 })
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
await page.mouse.move(855, y)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
await page.getByRole('button', { name: 'Exit Sketch' }).click()
await page.waitForTimeout(200)
await hoverOverNothing()
await page.waitForTimeout(200)
await page.mouse.move(x, 419)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
await page.mouse.move(855, y)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
})
test(`Zoom by scroll should not fire while orbiting`, async ({
homePage,

View File

@ -1005,114 +1005,108 @@ part002 = startSketchOn('XZ')
}
})
test.fixme(
'Horizontally constrained line remains selected after applying constraint',
async ({ page, homePage }) => {
test.setTimeout(70_000)
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`sketch001 = startSketchOn('XY')
test('Horizontally constrained line remains selected after applying constraint', async ({
page,
homePage,
}) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
test.setTimeout(70_000)
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`sketch001 = startSketchOn('XY')
|> startProfileAt([-1.05, -1.07], %)
|> line(end = [3.79, 2.68], tag = $seg01)
|> line(end = [3.13, -2.4])`
)
)
})
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await page.getByText('line(end = [3.79, 2.68], tag = $seg01)').click()
await expect(page.getByRole('button', { name: 'Edit Sketch' })).toBeEnabled(
{ timeout: 10_000 }
)
await page.getByRole('button', { name: 'Edit Sketch' }).click()
// Wait for overlays to populate
await page.waitForTimeout(1000)
await page.waitForTimeout(100)
const lineBefore = await u.getSegmentBodyCoords(
`[data-overlay-index="1"]`,
0
)
expect(
await u.getGreatestPixDiff(lineBefore, TEST_COLORS.WHITE)
).toBeLessThan(3)
await page.mouse.move(lineBefore.x, lineBefore.y)
await page.waitForTimeout(50)
await page.mouse.click(lineBefore.x, lineBefore.y)
expect(
await u.getGreatestPixDiff(lineBefore, TEST_COLORS.BLUE)
).toBeLessThan(3)
await page
.getByRole('button', {
name: 'Length: open menu',
})
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 })
.click()
await page.waitForTimeout(500)
await page.getByRole('button', { name: 'Horizontal', exact: true }).click()
await page.waitForTimeout(500)
await homePage.goToModelingScene()
await u.waitForPageLoad()
await pollEditorLinesSelectedLength(page, 1)
let activeLinesContent = await page.locator('.cm-activeLine').all()
await expect(activeLinesContent[0]).toHaveText(`|> xLine(length = 3.13)`)
await page.getByText('line(end = [3.79, 2.68], tag = $seg01)').click()
await expect(
page.getByRole('button', { name: 'Edit Sketch' })
).toBeEnabled({ timeout: 10_000 })
await page.getByRole('button', { name: 'Edit Sketch' }).click()
// Wait for code editor to settle.
await page.waitForTimeout(2000)
// Wait for overlays to populate
await page.waitForTimeout(1000)
// If the overlay-angle is updated the THREE.js scene is in a good state
await expect(
await page.locator('[data-overlay-index="1"]')
).toHaveAttribute('data-overlay-angle', '0')
await page.waitForTimeout(100)
const lineBefore = await u.getSegmentBodyCoords(
`[data-overlay-index="1"]`,
0
)
expect(
await u.getGreatestPixDiff(lineBefore, TEST_COLORS.WHITE)
).toBeLessThan(3)
await page.mouse.move(lineBefore.x, lineBefore.y)
await page.waitForTimeout(50)
await page.mouse.click(lineBefore.x, lineBefore.y)
expect(
await u.getGreatestPixDiff(lineBefore, TEST_COLORS.BLUE)
).toBeLessThan(3)
const lineAfter = await u.getSegmentBodyCoords(
`[data-overlay-index="1"]`,
0
)
await page
.getByRole('button', {
name: 'Length: open menu',
})
.click()
await page.waitForTimeout(500)
await page
.getByRole('button', { name: 'Horizontal', exact: true })
.click()
await page.waitForTimeout(500)
const linebb = await u.getBoundingBox('[data-overlay-index="1"]')
await page.mouse.move(linebb.x, linebb.y, { steps: 25 })
await page.mouse.click(linebb.x, linebb.y)
await pollEditorLinesSelectedLength(page, 1)
let activeLinesContent = await page.locator('.cm-activeLine').all()
await expect(activeLinesContent[0]).toHaveText(`|> xLine(length = 3.13)`)
await expect
.poll(async () => await u.getGreatestPixDiff(lineAfter, TEST_COLORS.BLUE))
.toBeLessThan(3)
// Wait for code editor to settle.
await page.waitForTimeout(2000)
await page.waitForTimeout(500)
// If the overlay-angle is updated the THREE.js scene is in a good state
await expect(
await page.locator('[data-overlay-index="1"]')
).toHaveAttribute('data-overlay-angle', '0')
// await expect(page.getByRole('button', { name: 'length', exact: true })).toBeVisible()
await page.waitForTimeout(200)
// await page.getByRole('button', { name: 'length', exact: true }).click()
await page.getByTestId('constraint-length').click()
const lineAfter = await u.getSegmentBodyCoords(
`[data-overlay-index="1"]`,
0
)
await page.getByTestId('cmd-bar-arg-value').getByRole('textbox').fill('10')
await page
.getByRole('button', {
name: 'arrow right Continue',
})
.click()
const linebb = await u.getBoundingBox('[data-overlay-index="1"]')
await page.mouse.move(linebb.x, linebb.y, { steps: 25 })
await page.mouse.click(linebb.x, linebb.y)
await pollEditorLinesSelectedLength(page, 1)
activeLinesContent = await page.locator('.cm-activeLine').all()
await expect(activeLinesContent[0]).toHaveText(
`|> xLine(length = length001)`
)
await expect
.poll(
async () => await u.getGreatestPixDiff(lineAfter, TEST_COLORS.BLUE)
)
.toBeLessThan(3)
await page.waitForTimeout(500)
// await expect(page.getByRole('button', { name: 'length', exact: true })).toBeVisible()
await page.waitForTimeout(200)
// await page.getByRole('button', { name: 'length', exact: true }).click()
await page.getByTestId('constraint-length').click()
await page
.getByTestId('cmd-bar-arg-value')
.getByRole('textbox')
.fill('10')
await page
.getByRole('button', {
name: 'arrow right Continue',
})
.click()
await pollEditorLinesSelectedLength(page, 1)
activeLinesContent = await page.locator('.cm-activeLine').all()
await expect(activeLinesContent[0]).toHaveText(
`|> xLine(length = length001)`
)
// checking the count of the overlays is a good proxy check that the client sketch scene is in a good state
await expect(page.getByTestId('segment-overlay')).toHaveCount(2)
}
)
// checking the count of the overlays is a good proxy check that the client sketch scene is in a good state
await expect(page.getByTestId('segment-overlay')).toHaveCount(2)
})
})
test.describe('Electron constraint tests', () => {
test(

View File

@ -2,7 +2,8 @@ import { test, expect } from './zoo-test'
import { getUtils } from './test-utils'
test.describe('Test toggling perspective', () => {
test.fixme('via command palette and toggle', async ({ page, homePage }) => {
test('via command palette and toggle', async ({ page, homePage }) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
const u = await getUtils(page)
// Locators and constants

File diff suppressed because it is too large Load Diff

View File

@ -448,15 +448,20 @@ profile003 = startProfileAt([40.16, -120.48], sketch006)
await page.waitForTimeout(200)
await expect(u.codeLocator).not.toContainText(codeToBeDeletedSnippet)
})
test.fixme(
'parent Solid should be select and deletable and uses custom planes to position children',
async ({ page, homePage, scene, cmdBar, editor }) => {
test.setTimeout(90_000)
const u = await getUtils(page)
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`part001 = startSketchOn('XY')
test('parent Solid should be select and deletable and uses custom planes to position children', async ({
page,
homePage,
scene,
cmdBar,
editor,
}) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
test.setTimeout(90_000)
const u = await getUtils(page)
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`part001 = startSketchOn('XY')
yo = startProfileAt([4.83, 12.56], part001)
|> line(end = [15.1, 2.48])
|> line(end = [3.15, -9.85], tag = $seg01)
@ -487,35 +492,34 @@ profile001 = startProfileAt([7.49, 9.96], sketch001)
|> close()
`
)
}, KCL_DEFAULT_LENGTH)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.settled(cmdBar)
const extrudeWall = { x: 575, y: 238 }
// DELETE with selection on face of parent
await page.mouse.click(extrudeWall.x, extrudeWall.y)
await page.waitForTimeout(100)
await expect(page.locator('.cm-activeLine')).toHaveText(
'|> line(end = [-15.17, -4.1])'
)
await u.openAndClearDebugPanel()
await page.keyboard.press('Delete')
await u.expectCmdLog('[data-message-type="execution-done"]', 10_000)
await page.waitForTimeout(200)
}, KCL_DEFAULT_LENGTH)
await page.setBodyDimensions({ width: 1000, height: 500 })
await editor.expectEditor.not.toContain(`yoo = extrude(yo, length = 4)`, {
shouldNormalise: true,
})
await editor.expectEditor.toContain(`startSketchOn({plane={origin`, {
shouldNormalise: true,
})
await editor.snapshot()
}
)
await homePage.goToModelingScene()
await scene.settled(cmdBar)
const extrudeWall = { x: 575, y: 238 }
// DELETE with selection on face of parent
await page.mouse.click(extrudeWall.x, extrudeWall.y)
await page.waitForTimeout(100)
await expect(page.locator('.cm-activeLine')).toHaveText(
'|> line(end = [-15.17, -4.1])'
)
await u.openAndClearDebugPanel()
await page.keyboard.press('Delete')
await u.expectCmdLog('[data-message-type="execution-done"]', 10_000)
await page.waitForTimeout(200)
await editor.expectEditor.not.toContain(`yoo = extrude(yo, length = 4)`, {
shouldNormalise: true,
})
await editor.expectEditor.toContain(`startSketchOn({plane={origin`, {
shouldNormalise: true,
})
await editor.snapshot()
})
test('Hovering over 3d features highlights code, clicking puts the cursor in the right place and sends selection id to engine', async ({
page,
homePage,

View File

@ -55,91 +55,87 @@ test.describe('Testing settings', () => {
})
// The behavior is actually broken. Parent always takes precedence
test.fixme(
'Project settings can be set and override user settings',
async ({ page, homePage }) => {
const u = await getUtils(page)
await test.step(`Setup`, async () => {
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await page
.getByRole('button', { name: 'Start Sketch' })
.waitFor({ state: 'visible' })
})
// Selectors and constants
const paneButtonLocator = page.getByTestId('debug-pane-button')
const headingLocator = page.getByRole('heading', {
name: 'Settings',
exact: true,
})
const inputLocator = page.locator('input[name="app-showDebugPanel"]')
await test.step('Open settings dialog and set "Show debug panel" to on', async () => {
await page.keyboard.press('ControlOrMeta+,')
await expect(headingLocator).toBeVisible()
/** Test to close https://github.com/KittyCAD/modeling-app/issues/2713 */
await test.step(`Confirm that this dialog has a solid background`, async () => {
await expect
.poll(
() => u.getGreatestPixDiff({ x: 600, y: 250 }, [28, 28, 28]),
{
timeout: 1000,
message:
'Checking for solid background, should not see default plane colors',
}
)
.toBeLessThan(15)
})
await page.locator('#showDebugPanel').getByText('OffOn').click()
})
// Close it and open again with keyboard shortcut, while KCL editor is focused
// Put the cursor in the editor
await test.step('Open settings with keyboard shortcut', async () => {
await page.getByTestId('settings-close-button').click()
await page.locator('.cm-content').click()
await page.keyboard.press('ControlOrMeta+,')
await expect(headingLocator).toBeVisible()
})
// Verify the toast appeared
await expect(
page.getByText(`Set show debug panel to "false" for this project`)
).toBeVisible()
await expect(
page.getByText(`Set show debug panel to "false" for this project`)
).not.toBeVisible()
// Check that the debug panel button is gone
await expect(paneButtonLocator).not.toBeVisible()
// Check that the user setting was not changed
await page.getByRole('radio', { name: 'User' }).click()
await expect(inputLocator).toBeChecked()
// Roll back to default of "off"
await await page
.getByText(
'show debug panelRoll back show debug panelRoll back to match'
)
.hover()
test('Project settings can be set and override user settings', async ({
page,
homePage,
}) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
const u = await getUtils(page)
await test.step(`Setup`, async () => {
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await page
.getByRole('button', {
name: 'Roll back show debug panel',
})
.click()
await expect(inputLocator).not.toBeChecked()
.getByRole('button', { name: 'Start Sketch' })
.waitFor({ state: 'visible' })
})
// Check that the project setting did not change
await page.getByRole('radio', { name: 'Project' }).click()
await expect(
page.locator('input[name="app-showDebugPanel"]')
).not.toBeChecked()
}
)
// Selectors and constants
const paneButtonLocator = page.getByTestId('debug-pane-button')
const headingLocator = page.getByRole('heading', {
name: 'Settings',
exact: true,
})
const inputLocator = page.locator('input[name="app-showDebugPanel"]')
await test.step('Open settings dialog and set "Show debug panel" to on', async () => {
await page.keyboard.press('ControlOrMeta+,')
await expect(headingLocator).toBeVisible()
/** Test to close https://github.com/KittyCAD/modeling-app/issues/2713 */
await test.step(`Confirm that this dialog has a solid background`, async () => {
await expect
.poll(() => u.getGreatestPixDiff({ x: 600, y: 250 }, [28, 28, 28]), {
timeout: 1000,
message:
'Checking for solid background, should not see default plane colors',
})
.toBeLessThan(15)
})
await page.locator('#showDebugPanel').getByText('OffOn').click()
})
// Close it and open again with keyboard shortcut, while KCL editor is focused
// Put the cursor in the editor
await test.step('Open settings with keyboard shortcut', async () => {
await page.getByTestId('settings-close-button').click()
await page.locator('.cm-content').click()
await page.keyboard.press('ControlOrMeta+,')
await expect(headingLocator).toBeVisible()
})
// Verify the toast appeared
await expect(
page.getByText(`Set show debug panel to "false" for this project`)
).toBeVisible()
await expect(
page.getByText(`Set show debug panel to "false" for this project`)
).not.toBeVisible()
// Check that the debug panel button is gone
await expect(paneButtonLocator).not.toBeVisible()
// Check that the user setting was not changed
await page.getByRole('radio', { name: 'User' }).click()
await expect(inputLocator).toBeChecked()
// Roll back to default of "off"
await await page
.getByText('show debug panelRoll back show debug panelRoll back to match')
.hover()
await page
.getByRole('button', {
name: 'Roll back show debug panel',
})
.click()
await expect(inputLocator).not.toBeChecked()
// Check that the project setting did not change
await page.getByRole('radio', { name: 'Project' }).click()
await expect(
page.locator('input[name="app-showDebugPanel"]')
).not.toBeChecked()
})
test('Keybindings display the correct hotkey for Command Palette', async ({
page,
@ -175,103 +171,98 @@ test.describe('Testing settings', () => {
await expect(hotkey).toHaveText(text)
})
test.fixme(
'Project and user settings can be reset',
async ({ page, homePage }) => {
const u = await getUtils(page)
await test.step(`Setup`, async () => {
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await page.waitForTimeout(1000)
})
// Selectors and constants
const projectSettingsTab = page.getByRole('radio', { name: 'Project' })
const userSettingsTab = page.getByRole('radio', { name: 'User' })
const resetButton = (level: SettingsLevel) =>
page.getByRole('button', {
name: `Reset ${level}-level settings`,
})
const themeColorSetting = page.locator('#themeColor').getByRole('slider')
const settingValues = {
default: '259',
user: '120',
project: '50',
}
const resetToast = (level: SettingsLevel) =>
page.getByText(`${level}-level settings were reset`)
await test.step(`Open the settings modal`, async () => {
await page.getByRole('link', { name: 'Settings' }).last().click()
await expect(
page.getByRole('heading', { name: 'Settings', exact: true })
).toBeVisible()
})
await test.step('Set up theme color', async () => {
// Verify we're looking at the project-level settings,
// and it's set to default value
await expect(projectSettingsTab).toBeChecked()
await expect(themeColorSetting).toHaveValue(settingValues.default)
// Set project-level value to 50
await themeColorSetting.fill(settingValues.project)
// Set user-level value to 120
await userSettingsTab.click()
await themeColorSetting.fill(settingValues.user)
await projectSettingsTab.click()
})
await test.step('Reset project settings', async () => {
// Click the reset settings button.
await resetButton('project').click()
await expect(resetToast('project')).toBeVisible()
await expect(resetToast('project')).not.toBeVisible()
// Verify it is now set to the inherited user value
await expect(themeColorSetting).toHaveValue(settingValues.user)
await test.step(`Check that the user settings did not change`, async () => {
await userSettingsTab.click()
await expect(themeColorSetting).toHaveValue(settingValues.user)
})
await test.step(`Set project-level again to test the user-level reset`, async () => {
await projectSettingsTab.click()
await themeColorSetting.fill(settingValues.project)
await userSettingsTab.click()
})
})
await test.step('Reset user settings', async () => {
// Click the reset settings button.
await resetButton('user').click()
await expect(resetToast('user')).toBeVisible()
await expect(resetToast('user')).not.toBeVisible()
// Verify it is now set to the default value
await expect(themeColorSetting).toHaveValue(settingValues.default)
await test.step(`Check that the project settings did not change`, async () => {
await projectSettingsTab.click()
await expect(themeColorSetting).toHaveValue(settingValues.project)
})
test('Project and user settings can be reset', async ({ page, homePage }) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
const u = await getUtils(page)
await test.step(`Setup`, async () => {
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await page.waitForTimeout(1000)
})
// Selectors and constants
const projectSettingsTab = page.getByRole('radio', { name: 'Project' })
const userSettingsTab = page.getByRole('radio', { name: 'User' })
const resetButton = (level: SettingsLevel) =>
page.getByRole('button', {
name: `Reset ${level}-level settings`,
})
const themeColorSetting = page.locator('#themeColor').getByRole('slider')
const settingValues = {
default: '259',
user: '120',
project: '50',
}
)
const resetToast = (level: SettingsLevel) =>
page.getByText(`${level}-level settings were reset`)
test.fixme(
await test.step(`Open the settings modal`, async () => {
await page.getByRole('link', { name: 'Settings' }).last().click()
await expect(
page.getByRole('heading', { name: 'Settings', exact: true })
).toBeVisible()
})
await test.step('Set up theme color', async () => {
// Verify we're looking at the project-level settings,
// and it's set to default value
await expect(projectSettingsTab).toBeChecked()
await expect(themeColorSetting).toHaveValue(settingValues.default)
// Set project-level value to 50
await themeColorSetting.fill(settingValues.project)
// Set user-level value to 120
await userSettingsTab.click()
await themeColorSetting.fill(settingValues.user)
await projectSettingsTab.click()
})
await test.step('Reset project settings', async () => {
// Click the reset settings button.
await resetButton('project').click()
await expect(resetToast('project')).toBeVisible()
await expect(resetToast('project')).not.toBeVisible()
// Verify it is now set to the inherited user value
await expect(themeColorSetting).toHaveValue(settingValues.user)
await test.step(`Check that the user settings did not change`, async () => {
await userSettingsTab.click()
await expect(themeColorSetting).toHaveValue(settingValues.user)
})
await test.step(`Set project-level again to test the user-level reset`, async () => {
await projectSettingsTab.click()
await themeColorSetting.fill(settingValues.project)
await userSettingsTab.click()
})
})
await test.step('Reset user settings', async () => {
// Click the reset settings button.
await resetButton('user').click()
await expect(resetToast('user')).toBeVisible()
await expect(resetToast('user')).not.toBeVisible()
// Verify it is now set to the default value
await expect(themeColorSetting).toHaveValue(settingValues.default)
await test.step(`Check that the project settings did not change`, async () => {
await projectSettingsTab.click()
await expect(themeColorSetting).toHaveValue(settingValues.project)
})
})
})
test(
`Project settings override user settings on desktop`,
{ tag: ['@electron', '@skipWin'] },
async ({ context, page }, testInfo) => {
test.skip(
process.platform === 'win32',
'TODO: remove this skip https://github.com/KittyCAD/modeling-app/issues/3557'
)
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
const projectName = 'bracket'
const { dir: projectDirName } = await context.folderSetupFn(
async (dir) => {
@ -407,12 +398,13 @@ test.describe('Testing settings', () => {
)
// It was much easier to test the logo color than the background stream color.
test.fixme(
test(
'user settings reload on external change, on project and modeling view',
{
tag: '@electron',
},
async ({ context, page, tronApp }, testInfo) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
if (!tronApp) {
fail()
}
@ -466,10 +458,11 @@ test.describe('Testing settings', () => {
}
)
test.fixme(
test(
'project settings reload on external change',
{ tag: '@electron' },
async ({ context, page }, testInfo) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
const { dir: projectDirName } = await context.folderSetupFn(
async () => {}
)
@ -982,63 +975,68 @@ fn cube`
/**
* This test assumes that the default value of the "highlight edges" setting is "on".
*/
test.fixme(
`Toggle stream settings multiple times`,
async ({ page, scene, homePage, context, toolbar, cmdBar }, testInfo) => {
await context.folderSetupFn(async (dir) => {
const projectDir = join(dir, 'project-000')
await fsp.mkdir(projectDir, { recursive: true })
await fsp.copyFile(
executorInputPath('cube.kcl'),
join(projectDir, 'main.kcl')
)
})
test(`Toggle stream settings multiple times`, async ({
page,
scene,
homePage,
context,
toolbar,
cmdBar,
}, testInfo) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
await context.folderSetupFn(async (dir) => {
const projectDir = join(dir, 'project-000')
await fsp.mkdir(projectDir, { recursive: true })
await fsp.copyFile(
executorInputPath('cube.kcl'),
join(projectDir, 'main.kcl')
)
})
await test.step(`First snapshot`, async () => {
await homePage.openProject('project-000')
await toolbar.closePane('code')
await expect(toolbar.startSketchBtn).toBeEnabled({ timeout: 20_000 })
await scene.clickNoWhere()
})
await test.step(`First snapshot`, async () => {
await homePage.openProject('project-000')
await toolbar.closePane('code')
await expect(toolbar.startSketchBtn).toBeEnabled({ timeout: 20_000 })
await scene.clickNoWhere()
})
const toast = (value: boolean) =>
page.getByText(
`Set highlight edges to "${String(value)}" as a user default`
)
await test.step(`Toggle highlightEdges off`, async () => {
await cmdBar.openCmdBar()
await cmdBar.chooseCommand('Settings · modeling · highlight edges')
await cmdBar.selectOption({ name: 'off' }).click()
const falseToast = toast(false)
await expect(falseToast).toBeVisible()
await falseToast.waitFor({ state: 'detached' })
})
await expect(scene.streamWrapper).not.toHaveScreenshot(
'toggle-settings-initial.png',
{
maxDiffPixels: 15,
mask: [page.getByTestId('model-state-indicator')],
}
const toast = (value: boolean) =>
page.getByText(
`Set highlight edges to "${String(value)}" as a user default`
)
await test.step(`Toggle highlightEdges on`, async () => {
await cmdBar.openCmdBar()
await cmdBar.chooseCommand('Settings · modeling · highlight edges')
await cmdBar.selectOption({ name: 'on' }).click()
const trueToast = toast(true)
await expect(trueToast).toBeVisible()
await trueToast.waitFor({ state: 'detached' })
})
await test.step(`Toggle highlightEdges off`, async () => {
await cmdBar.openCmdBar()
await cmdBar.chooseCommand('Settings · modeling · highlight edges')
await cmdBar.selectOption({ name: 'off' }).click()
const falseToast = toast(false)
await expect(falseToast).toBeVisible()
await falseToast.waitFor({ state: 'detached' })
})
await expect(scene.streamWrapper).toHaveScreenshot(
'toggle-settings-initial.png',
{
maxDiffPixels: 15,
mask: [page.getByTestId('model-state-indicator')],
}
)
}
)
await expect(scene.streamWrapper).not.toHaveScreenshot(
'toggle-settings-initial.png',
{
maxDiffPixels: 15,
mask: [page.getByTestId('model-state-indicator')],
}
)
await test.step(`Toggle highlightEdges on`, async () => {
await cmdBar.openCmdBar()
await cmdBar.chooseCommand('Settings · modeling · highlight edges')
await cmdBar.selectOption({ name: 'on' }).click()
const trueToast = toast(true)
await expect(trueToast).toBeVisible()
await trueToast.waitFor({ state: 'detached' })
})
await expect(scene.streamWrapper).toHaveScreenshot(
'toggle-settings-initial.png',
{
maxDiffPixels: 15,
mask: [page.getByTestId('model-state-indicator')],
}
)
})
})

View File

@ -431,10 +431,11 @@ test.describe('Text-to-CAD tests', { tag: ['@skipWin'] }, () => {
})
// This will be fine once greg makes prompt at top of file deterministic
test.fixme(
test(
'can do many at once and get many prompts back, and interact with many',
{ tag: ['@skipWin'] },
async ({ page, homePage }) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
// Let this test run longer since we've seen it timeout.
test.setTimeout(180_000)
@ -619,10 +620,11 @@ async function sendPromptFromCommandBar(page: Page, promptStr: string) {
})
}
test.fixme(
test(
'Text-to-CAD functionality',
{ tag: '@electron' },
async ({ context, page }, testInfo) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
const projectName = 'project-000'
const prompt = 'lego 2x4'
const textToCadFileName = 'lego-2x4.kcl'

View File

@ -2,7 +2,8 @@ import { test, expect } from './zoo-test'
import { doExport, getUtils, makeTemplate } from './test-utils'
test.fixme('Units menu', async ({ page, homePage }) => {
test('Units menu', async ({ page, homePage }) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
@ -263,186 +264,187 @@ test('First escape in tool pops you out of tool, second exits sketch mode', asyn
).not.toBeVisible()
})
test.fixme(
'Basic default modeling and sketch hotkeys work',
async ({ page, homePage }) => {
const u = await getUtils(page)
test('Basic default modeling and sketch hotkeys work', async ({
page,
homePage,
}) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
const u = await getUtils(page)
// This test can run long if it takes a little too long to load
// the engine.
test.setTimeout(90000)
// This test has a weird bug on ubuntu
// Funny, it's flaking on Windows too :). I think there is just something
// actually wrong.
test.skip(
process.platform === 'linux',
'weird playwright bug on ubuntu https://github.com/KittyCAD/modeling-app/issues/2444'
)
// Load the app with the code pane open
// This test can run long if it takes a little too long to load
// the engine.
test.setTimeout(90000)
// This test has a weird bug on ubuntu
// Funny, it's flaking on Windows too :). I think there is just something
// actually wrong.
test.skip(
process.platform === 'linux',
'weird playwright bug on ubuntu https://github.com/KittyCAD/modeling-app/issues/2444'
)
// Load the app with the code pane open
await test.step(`Set up test`, async () => {
await page.addInitScript(async () => {
localStorage.setItem(
'store',
JSON.stringify({
state: {
openPanes: ['code'],
},
version: 0,
})
)
})
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel()
})
const codePane = page.locator('.cm-content')
const lineButton = page.getByRole('button', {
name: 'line Line',
exact: true,
})
const arcButton = page.getByRole('button', {
name: 'arc Tangential Arc',
exact: true,
})
const extrudeButton = page.getByRole('button', { name: 'Extrude' })
const commandBarComboBox = page.getByPlaceholder('Search commands')
const exitSketchButton = page.getByRole('button', { name: 'Exit Sketch' })
await test.step(`Type code with modeling hotkeys, shouldn't fire`, async () => {
await codePane.click()
await page.keyboard.type('//')
await page.keyboard.press('s')
await expect(commandBarComboBox).not.toBeVisible()
await page.keyboard.press('e')
await expect(commandBarComboBox).not.toBeVisible()
await expect(codePane).toHaveText('//se')
})
// Blur focus from the code editor, use the s command to sketch
await test.step(`Blur editor focus, enter sketch`, async () => {
/**
* TODO: There is a bug somewhere that causes this test to fail
* if you toggle the codePane closed before your trigger the
* start of the sketch.
* and a separate Safari-only bug that causes the test to fail
* if the pane is open the entire test. The maintainer of CodeMirror
* has pinpointed this to the unusual browser behavior:
* https://discuss.codemirror.net/t/how-to-force-unfocus-of-the-codemirror-element-in-safari/8095/3
*/
await blurCodeEditor()
await page.waitForTimeout(1000)
await page.keyboard.press('s')
await page.waitForTimeout(1000)
await page.mouse.move(800, 300, { steps: 5 })
await page.mouse.click(800, 300)
await page.waitForTimeout(1000)
await expect(lineButton).toHaveAttribute('aria-pressed', 'true', {
timeout: 15_000,
})
})
// Use some sketch hotkeys to create a sketch (l and a for now)
await test.step(`Incomplete sketch with hotkeys`, async () => {
await test.step(`Draw a line`, async () => {
await page.mouse.move(700, 200, { steps: 5 })
await page.mouse.click(700, 200)
await page.mouse.move(800, 250, { steps: 5 })
await page.mouse.click(800, 250)
})
await test.step(`Unequip line tool`, async () => {
await page.keyboard.press('l')
await expect(lineButton).not.toHaveAttribute('aria-pressed', 'true')
})
await test.step(`Draw a tangential arc`, async () => {
await page.keyboard.press('a')
await expect(arcButton).toHaveAttribute('aria-pressed', 'true', {
timeout: 10_000,
await test.step(`Set up test`, async () => {
await page.addInitScript(async () => {
localStorage.setItem(
'store',
JSON.stringify({
state: {
openPanes: ['code'],
},
version: 0,
})
await page.mouse.move(1000, 100, { steps: 5 })
await page.mouse.click(1000, 100)
})
await test.step(`Unequip with escape, equip line tool`, async () => {
await page.keyboard.press('Escape')
await page.keyboard.press('l')
await page.waitForTimeout(50)
await expect(lineButton).toHaveAttribute('aria-pressed', 'true')
})
)
})
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel()
})
await test.step(`Type code with sketch hotkeys, shouldn't fire`, async () => {
// Since there's code now, we have to get to the end of the line
await page.locator('.cm-line').last().click()
await page.keyboard.down('ControlOrMeta')
await page.keyboard.press('ArrowRight')
await page.keyboard.up('ControlOrMeta')
const codePane = page.locator('.cm-content')
const lineButton = page.getByRole('button', {
name: 'line Line',
exact: true,
})
const arcButton = page.getByRole('button', {
name: 'arc Tangential Arc',
exact: true,
})
const extrudeButton = page.getByRole('button', { name: 'Extrude' })
const commandBarComboBox = page.getByPlaceholder('Search commands')
const exitSketchButton = page.getByRole('button', { name: 'Exit Sketch' })
await page.keyboard.press('Enter')
await page.keyboard.type('//')
await page.keyboard.press('l')
await expect(lineButton).toHaveAttribute('aria-pressed', 'true')
await page.keyboard.press('a')
await expect(lineButton).toHaveAttribute('aria-pressed', 'true')
await expect(codePane).toContainText('//la')
await page.keyboard.press('Backspace')
await page.keyboard.press('Backspace')
await page.keyboard.press('Backspace')
await page.keyboard.press('Backspace')
await test.step(`Type code with modeling hotkeys, shouldn't fire`, async () => {
await codePane.click()
await page.keyboard.type('//')
await page.keyboard.press('s')
await expect(commandBarComboBox).not.toBeVisible()
await page.keyboard.press('e')
await expect(commandBarComboBox).not.toBeVisible()
await expect(codePane).toHaveText('//se')
})
// Blur focus from the code editor, use the s command to sketch
await test.step(`Blur editor focus, enter sketch`, async () => {
/**
* TODO: There is a bug somewhere that causes this test to fail
* if you toggle the codePane closed before your trigger the
* start of the sketch.
* and a separate Safari-only bug that causes the test to fail
* if the pane is open the entire test. The maintainer of CodeMirror
* has pinpointed this to the unusual browser behavior:
* https://discuss.codemirror.net/t/how-to-force-unfocus-of-the-codemirror-element-in-safari/8095/3
*/
await blurCodeEditor()
await page.waitForTimeout(1000)
await page.keyboard.press('s')
await page.waitForTimeout(1000)
await page.mouse.move(800, 300, { steps: 5 })
await page.mouse.click(800, 300)
await page.waitForTimeout(1000)
await expect(lineButton).toHaveAttribute('aria-pressed', 'true', {
timeout: 15_000,
})
})
await test.step(`Close profile and exit sketch`, async () => {
await blurCodeEditor()
// Use some sketch hotkeys to create a sketch (l and a for now)
await test.step(`Incomplete sketch with hotkeys`, async () => {
await test.step(`Draw a line`, async () => {
await page.mouse.move(700, 200, { steps: 5 })
await page.mouse.click(700, 200)
// On close it will unequip the line tool.
await expect(lineButton).toHaveAttribute('aria-pressed', 'false')
await expect(exitSketchButton).toBeEnabled()
await page.keyboard.press('Escape')
await expect(
page.getByRole('button', { name: 'Exit Sketch' })
).not.toBeVisible()
await page.mouse.move(800, 250, { steps: 5 })
await page.mouse.click(800, 250)
})
// Extrude with e
await test.step(`Extrude the sketch`, async () => {
await page.mouse.click(750, 150)
await blurCodeEditor()
await expect(extrudeButton).toBeEnabled()
await page.keyboard.press('e')
await page.waitForTimeout(500)
await page.mouse.move(800, 200, { steps: 5 })
await page.mouse.click(800, 200)
await expect(page.getByRole('button', { name: 'Continue' })).toBeVisible({
timeout: 20_000,
await test.step(`Unequip line tool`, async () => {
await page.keyboard.press('l')
await expect(lineButton).not.toHaveAttribute('aria-pressed', 'true')
})
await test.step(`Draw a tangential arc`, async () => {
await page.keyboard.press('a')
await expect(arcButton).toHaveAttribute('aria-pressed', 'true', {
timeout: 10_000,
})
await page.getByRole('button', { name: 'Continue' }).click()
await expect(
page.getByRole('button', { name: 'Submit command' })
).toBeVisible()
await page.getByRole('button', { name: 'Submit command' }).click()
await expect(page.locator('.cm-content')).toContainText('extrude(')
await page.mouse.move(1000, 100, { steps: 5 })
await page.mouse.click(1000, 100)
})
// await codePaneButton.click()
// await expect(u.codeLocator).not.toBeVisible()
/**
* work-around: to stop `keyboard.press()` from typing in the editor even when it should be blurred
*/
async function blurCodeEditor() {
await page.getByRole('button', { name: 'Commands' }).click()
await page.waitForTimeout(100)
await test.step(`Unequip with escape, equip line tool`, async () => {
await page.keyboard.press('Escape')
await page.waitForTimeout(100)
}
await page.keyboard.press('l')
await page.waitForTimeout(50)
await expect(lineButton).toHaveAttribute('aria-pressed', 'true')
})
})
await test.step(`Type code with sketch hotkeys, shouldn't fire`, async () => {
// Since there's code now, we have to get to the end of the line
await page.locator('.cm-line').last().click()
await page.keyboard.down('ControlOrMeta')
await page.keyboard.press('ArrowRight')
await page.keyboard.up('ControlOrMeta')
await page.keyboard.press('Enter')
await page.keyboard.type('//')
await page.keyboard.press('l')
await expect(lineButton).toHaveAttribute('aria-pressed', 'true')
await page.keyboard.press('a')
await expect(lineButton).toHaveAttribute('aria-pressed', 'true')
await expect(codePane).toContainText('//la')
await page.keyboard.press('Backspace')
await page.keyboard.press('Backspace')
await page.keyboard.press('Backspace')
await page.keyboard.press('Backspace')
})
await test.step(`Close profile and exit sketch`, async () => {
await blurCodeEditor()
await page.mouse.move(700, 200, { steps: 5 })
await page.mouse.click(700, 200)
// On close it will unequip the line tool.
await expect(lineButton).toHaveAttribute('aria-pressed', 'false')
await expect(exitSketchButton).toBeEnabled()
await page.keyboard.press('Escape')
await expect(
page.getByRole('button', { name: 'Exit Sketch' })
).not.toBeVisible()
})
// Extrude with e
await test.step(`Extrude the sketch`, async () => {
await page.mouse.click(750, 150)
await blurCodeEditor()
await expect(extrudeButton).toBeEnabled()
await page.keyboard.press('e')
await page.waitForTimeout(500)
await page.mouse.move(800, 200, { steps: 5 })
await page.mouse.click(800, 200)
await expect(page.getByRole('button', { name: 'Continue' })).toBeVisible({
timeout: 20_000,
})
await page.getByRole('button', { name: 'Continue' }).click()
await expect(
page.getByRole('button', { name: 'Submit command' })
).toBeVisible()
await page.getByRole('button', { name: 'Submit command' }).click()
await expect(page.locator('.cm-content')).toContainText('extrude(')
})
// await codePaneButton.click()
// await expect(u.codeLocator).not.toBeVisible()
/**
* work-around: to stop `keyboard.press()` from typing in the editor even when it should be blurred
*/
async function blurCodeEditor() {
await page.getByRole('button', { name: 'Commands' }).click()
await page.waitForTimeout(100)
await page.keyboard.press('Escape')
await page.waitForTimeout(100)
}
)
})
test('Delete key does not navigate back', async ({ page, homePage }) => {
await page.setBodyDimensions({ width: 1200, height: 500 })