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

View File

@ -340,14 +340,22 @@ jobs:
if: needs.conditions.outputs.should-run == 'true' if: needs.conditions.outputs.should-run == 'true'
run: yarn tronb:vite:dev run: yarn tronb:vite:dev
- name: Install good sed - name: Install vector
if: startsWith(matrix.os, 'macos') if: contains(matrix.os, 'ubuntu')
shell: bash shell: bash
run: | run: |
brew install gnu-sed curl --proto '=https' --tlsv1.2 -sSfL https://sh.vector.dev > /tmp/vector.sh
echo "/opt/homebrew/opt/gnu-sed/libexec/gnubin" >> $GITHUB_PATH chmod +x /tmp/vector.sh
/tmp/vector.sh -y -no-modify-path
# TODO: Add back axiom logs 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 - uses: actions/download-artifact@v4
if: ${{ needs.conditions.outputs.should-run == 'true' && !cancelled() && (success() || failure()) }} 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.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']) await doBasicSketch(page, homePage, ['code'])
}) })

View File

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

View File

@ -47,7 +47,8 @@ test.describe('Command bar tests', { tag: ['@skipWin'] }, () => {
}) })
// TODO: fix this test after the electron migration // 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 () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',

View File

@ -635,14 +635,16 @@ test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible() await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
}) })
test.fixme( test('error with 2 source ranges gets 2 diagnostics', async ({
'error with 2 source ranges gets 2 diagnostics', page,
async ({ page, homePage }) => { homePage,
const u = await getUtils(page) }) => {
await page.addInitScript(async () => { test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
localStorage.setItem( const u = await getUtils(page)
'persistCode', await page.addInitScript(async () => {
`length = .750 localStorage.setItem(
'persistCode',
`length = .750
width = 0.500 width = 0.500
height = 0.500 height = 0.500
dia = 4 dia = 4
@ -657,53 +659,52 @@ test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
return squareHoleSketch return squareHoleSketch
} }
` `
) )
}) })
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await u.waitForPageLoad() await u.waitForPageLoad()
await page.waitForTimeout(1000) await page.waitForTimeout(1000)
await u.openDebugPanel() await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]') await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel() await u.closeDebugPanel()
// check no error to begin with // check no error to begin with
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible() await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
// Click on the bottom of the code editor to add a new line // Click on the bottom of the code editor to add a new line
await u.codeLocator.click() 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('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.press('Enter')
await page.keyboard.type(`extrusion = startSketchOn('XY') await page.keyboard.type(`extrusion = startSketchOn('XY')
|> circle(center: [0, 0], radius: dia/2) |> circle(center: [0, 0], radius: dia/2)
|> hole(squareHole(length, width, height), %) |> hole(squareHole(length, width, height), %)
|> extrude(length = height)`) |> extrude(length = height)`)
// error in gutter // error in gutter
await expect(page.locator('.cm-lint-marker-error').first()).toBeVisible() await expect(page.locator('.cm-lint-marker-error').first()).toBeVisible()
await page.hover('.cm-lint-marker-error:first-child') await page.hover('.cm-lint-marker-error:first-child')
await expect( await expect(
page.getByText('Expected 2 arguments, got 3').first() page.getByText('Expected 2 arguments, got 3').first()
).toBeVisible() ).toBeVisible()
// Make sure there are two diagnostics // Make sure there are two diagnostics
await expect(page.locator('.cm-lint-marker-error')).toHaveCount(2) await expect(page.locator('.cm-lint-marker-error')).toHaveCount(2)
} })
)
test('if your kcl gets an error from the engine it is inlined', async ({ test('if your kcl gets an error from the engine it is inlined', async ({
context, context,
page, 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`, `Can use the import stdlib function on a local OBJ file`,
{ tag: '@electron' }, { tag: '@electron' },
async ({ page, context }, testInfo) => { async ({ page, context }, testInfo) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
await context.folderSetupFn(async (dir) => { await context.folderSetupFn(async (dir) => {
const bracketDir = join(dir, 'cube') const bracketDir = join(dir, 'cube')
await fsp.mkdir(bracketDir, { recursive: true }) 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', 'loading small file, then large, then back to small',
{ {
tag: '@electron', tag: '@electron',
}, },
async ({ page }, testInfo) => { async ({ page }, testInfo) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
const { const {
panesOpen, panesOpen,
pasteCodeInEditor, 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 // (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 // 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. // low impact of an avatar not showing I'm changing this to fixme.
test.fixme( test('Avatar text updates depending on image load success', async ({
'Avatar text updates depending on image load success', context,
async ({ context, page, homePage, tronApp }) => { page,
if (!tronApp) { homePage,
fail() tronApp,
} }) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
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 }) => {
if (!tronApp) { if (!tronApp) {
fail() fail()
} }
await tronApp.cleanProjectDir({ await tronApp.cleanProjectDir({
app: { app: {
onboarding_status: 'dismissed', onboarding_status: '',
}, },
}) })
await context.folderSetupFn(async (dir) => { // Override beforeEach test setup
const routerTemplateDir = join(dir, 'router-template-slate') await context.addInitScript(
await fsp.mkdir(routerTemplateDir, { recursive: true }) async ({ settingsKey, settings }) => {
await fsp.copyFile( localStorage.setItem(settingsKey, settings)
executorInputPath('router-template-slate.kcl'), },
join(routerTemplateDir, 'main.kcl') {
) settingsKey: TEST_SETTINGS_KEY,
}) settings: settingsToToml({
settings: TEST_SETTINGS_ONBOARDING_USER_MENU,
}),
}
)
// Our constants await page.setBodyDimensions({ width: 1200, height: 500 })
const u = await getUtils(page) await homePage.goToModelingScene()
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 // Test that the text in this step is correct
.getByTestId('project-sidebar-toggle') const avatarLocator = page.getByTestId('user-sidebar-toggle').locator('img')
.filter({ hasText: 'Tutorial Project 00' }) const onboardingOverlayLocator = page
const tutorialModalText = page.getByText('Welcome to Modeling App!') .getByTestId('onboarding-content')
const tutorialDismissButton = page.getByRole('button', { name: 'Dismiss' }) .locator('div')
const userMenuButton = page.getByTestId('user-sidebar-toggle') .nth(1)
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 () => { // Expect the avatar to be visible and for the text to reference it
await expect( await expect(avatarLocator).toBeVisible()
page.getByRole('heading', { name: 'Your Projects' }) await expect(onboardingOverlayLocator).toBeVisible()
).toBeVisible() await expect(onboardingOverlayLocator).toContainText('your avatar')
await expect(projectCard).toBeVisible()
await projectCard.click()
await u.waitForPageLoad()
})
await test.step('Restart the onboarding from help menu', async () => { // This is to force the avatar to 404.
await helpMenuButton.click() // For our test image (only triggers locally. on CI, it's Kurt's /
await restartOnboardingButton.click() // gravatar image )
await page.route('/cat.jpg', async (route) => {
await nextButton.hover() await route.fulfill({
await nextButton.click() status: 404,
}) contentType: 'text/plain',
body: 'Not Found!',
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()
}) })
// 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( test(`Shift-click to select and deselect sketch segments`, async ({
`Shift-click to select and deselect sketch segments`, page,
async ({ page, homePage, scene, editor }) => { homePage,
// Locators scene,
const firstPointLocation = { x: 200, y: 100 } editor,
const secondPointLocation = { x: 800, y: 100 } }) => {
const thirdPointLocation = { x: 800, y: 400 } test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
const fristSegmentLocation = { x: 750, y: 100 } // Locators
const secondSegmentLocation = { x: 800, y: 150 } const firstPointLocation = { x: 200, y: 100 }
const planeLocation = { x: 700, y: 200 } 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 // Click helpers
const [clickFirstPoint] = scene.makeMouseHelpers( const [clickFirstPoint] = scene.makeMouseHelpers(
firstPointLocation.x, firstPointLocation.x,
firstPointLocation.y firstPointLocation.y
) )
const [clickSecondPoint] = scene.makeMouseHelpers( const [clickSecondPoint] = scene.makeMouseHelpers(
secondPointLocation.x, secondPointLocation.x,
secondPointLocation.y secondPointLocation.y
) )
const [clickThirdPoint] = scene.makeMouseHelpers( const [clickThirdPoint] = scene.makeMouseHelpers(
thirdPointLocation.x, thirdPointLocation.x,
thirdPointLocation.y thirdPointLocation.y
) )
const [clickFirstSegment] = scene.makeMouseHelpers( const [clickFirstSegment] = scene.makeMouseHelpers(
fristSegmentLocation.x, fristSegmentLocation.x,
fristSegmentLocation.y fristSegmentLocation.y
) )
const [clickSecondSegment] = scene.makeMouseHelpers( const [clickSecondSegment] = scene.makeMouseHelpers(
secondSegmentLocation.x, secondSegmentLocation.x,
secondSegmentLocation.y secondSegmentLocation.y
) )
const [clickPlane] = scene.makeMouseHelpers( const [clickPlane] = scene.makeMouseHelpers(
planeLocation.x, planeLocation.x,
planeLocation.y planeLocation.y
) )
// Colors // Colors
const edgeColorWhite: [number, number, number] = [220, 220, 220] const edgeColorWhite: [number, number, number] = [220, 220, 220]
const edgeColorBlue: [number, number, number] = [20, 20, 200] const edgeColorBlue: [number, number, number] = [20, 20, 200]
const backgroundColor: [number, number, number] = [30, 30, 30] const backgroundColor: [number, number, number] = [30, 30, 30]
const tolerance = 40 const tolerance = 40
const timeout = 150 const timeout = 150
// Setup // Setup
await test.step(`Initial test setup`, async () => { await test.step(`Initial test setup`, async () => {
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene() 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( await scene.expectPixelColor(
backgroundColor, edgeColorBlue,
secondPointLocation, fristSegmentLocation,
tolerance
)
await scene.expectPixelColor(
edgeColorWhite,
secondSegmentLocation,
tolerance tolerance
) )
}) })
await test.step('Select the second segment (Shift-click)', async () => {
await test.step('Select and deselect a single sketch segment', async () => { await page.keyboard.down('Shift')
await test.step('Get into sketch mode', async () => { await page.waitForTimeout(timeout)
await editor.closePane() await clickSecondSegment()
await page.waitForTimeout(timeout) await page.waitForTimeout(timeout)
await page.getByRole('button', { name: 'Start Sketch' }).click() await page.keyboard.up('Shift')
await page.waitForTimeout(timeout) await scene.expectPixelColor(
await clickPlane() edgeColorBlue,
await page.waitForTimeout(1000) fristSegmentLocation,
}) tolerance
await test.step('Draw sketch', async () => { )
await clickFirstPoint() await scene.expectPixelColor(
await page.waitForTimeout(timeout) edgeColorBlue,
await clickSecondPoint() secondSegmentLocation,
await page.waitForTimeout(timeout) tolerance
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('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 ({ test(`Offset plane point-and-click`, async ({
context, context,

View File

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

View File

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

View File

@ -483,10 +483,11 @@ extrude001 = extrude(sketch001, length = 50)
} }
) )
test.fixme( test(
`Network health indicator only appears in modeling view`, `Network health indicator only appears in modeling view`,
{ tag: '@electron' }, { tag: '@electron' },
async ({ context, page }, testInfo) => { async ({ context, page }, testInfo) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
await context.folderSetupFn(async (dir) => { await context.folderSetupFn(async (dir) => {
const bracketDir = path.join(dir, 'bracket') const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true }) 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' }) page.getByRole('button', { name: 'Start Sketch' })
).toBeVisible() ).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 ( const doEditSegmentsByDraggingHandle = async (
page: Page, page: Page,
homePage: HomePageFixture, homePage: HomePageFixture,
@ -1086,107 +1087,108 @@ profile001 = startProfileAt([${roundOff(scale * 69.6)}, ${roundOff(
) )
}) })
// TODO: fix after electron migration is merged // TODO: fix after electron migration is merged
test.fixme( test('empty-scene default-planes act as expected', async ({
'empty-scene default-planes act as expected', page,
async ({ page, homePage }) => { homePage,
/** }) => {
* Tests the following things test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
* 1) The the planes are there on load because the scene is empty /**
* 2) The planes don't changes color when hovered initially * Tests the following things
* 3) Putting something in the scene makes the planes hidden * 1) The the planes are there on load because the scene is empty
* 4) Removing everything from the scene shows the plans again * 2) The planes don't changes color when hovered initially
* 3) Once "start sketch" is click, the planes do respond to hovers * 3) Putting something in the scene makes the planes hidden
* 4) Selecting a plan works as expected, i.e. sketch mode * 4) Removing everything from the scene shows the plans again
* 5) Reloading the scene with something already in the scene means the planes are hidden * 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) const u = await getUtils(page)
await homePage.goToModelingScene() await homePage.goToModelingScene()
await u.openDebugPanel() await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]') await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel() await u.closeDebugPanel()
const XYPlanePoint = { x: 774, y: 116 } as const const XYPlanePoint = { x: 774, y: 116 } as const
const unHoveredColor: [number, number, number] = [47, 47, 93] const unHoveredColor: [number, number, number] = [47, 47, 93]
expect( expect(
await u.getGreatestPixDiff(XYPlanePoint, unHoveredColor) await u.getGreatestPixDiff(XYPlanePoint, unHoveredColor)
).toBeLessThan(8) ).toBeLessThan(8)
await page.mouse.move(XYPlanePoint.x, XYPlanePoint.y) await page.mouse.move(XYPlanePoint.x, XYPlanePoint.y)
await page.waitForTimeout(200) await page.waitForTimeout(200)
// color should not change for having been hovered // color should not change for having been hovered
expect( expect(
await u.getGreatestPixDiff(XYPlanePoint, unHoveredColor) await u.getGreatestPixDiff(XYPlanePoint, unHoveredColor)
).toBeLessThan(8) ).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], %) |> startProfileAt([-10, -10], %)
|> line(end = [20, 0]) |> line(end = [20, 0])
|> line(end = [0, 20]) |> line(end = [0, 20])
|> xLine(length = -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] const noPlanesColor: [number, number, number] = [30, 30, 30]
expect( expect(
await u.getGreatestPixDiff(XYPlanePoint, noPlanesColor) await u.getGreatestPixDiff(XYPlanePoint, noPlanesColor)
).toBeLessThan(3) ).toBeLessThan(3)
await u.clearCommandLogs() await u.clearCommandLogs()
await u.removeCurrentCode() await u.removeCurrentCode()
await u.expectCmdLog('[data-message-type="execution-done"]') await u.expectCmdLog('[data-message-type="execution-done"]')
await expect await expect
.poll(() => u.getGreatestPixDiff(XYPlanePoint, unHoveredColor), { .poll(() => u.getGreatestPixDiff(XYPlanePoint, unHoveredColor), {
timeout: 5_000, timeout: 5_000,
}) })
.toBeLessThan(8) .toBeLessThan(8)
// click start Sketch // click start Sketch
await page.getByRole('button', { name: 'Start Sketch' }).click() await page.getByRole('button', { name: 'Start Sketch' }).click()
await page.mouse.move(XYPlanePoint.x, XYPlanePoint.y, { steps: 50 }) await page.mouse.move(XYPlanePoint.x, XYPlanePoint.y, { steps: 50 })
const hoveredColor: [number, number, number] = [93, 93, 127] const hoveredColor: [number, number, number] = [93, 93, 127]
// now that we're expecting the user to select a plan, it does respond to hover // now that we're expecting the user to select a plan, it does respond to hover
await expect await expect
.poll(() => u.getGreatestPixDiff(XYPlanePoint, hoveredColor)) .poll(() => u.getGreatestPixDiff(XYPlanePoint, hoveredColor))
.toBeLessThan(8) .toBeLessThan(8)
await page.mouse.click(XYPlanePoint.x, XYPlanePoint.y) await page.mouse.click(XYPlanePoint.x, XYPlanePoint.y)
await page.waitForTimeout(600) await page.waitForTimeout(600)
await page.mouse.click(XYPlanePoint.x, XYPlanePoint.y) await page.mouse.click(XYPlanePoint.x, XYPlanePoint.y)
await page.waitForTimeout(200) await page.waitForTimeout(200)
await page.mouse.click(XYPlanePoint.x + 50, XYPlanePoint.y + 50) await page.mouse.click(XYPlanePoint.x + 50, XYPlanePoint.y + 50)
await expect(u.codeLocator).toHaveText(`sketch001 = startSketchOn('XZ') await expect(u.codeLocator).toHaveText(`sketch001 = startSketchOn('XZ')
|> startProfileAt([11.8, 9.09], %) |> startProfileAt([11.8, 9.09], %)
|> line(end = [3.39, -3.39]) |> line(end = [3.39, -3.39])
`) `)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`sketch001 = startSketchOn('XZ') `sketch001 = startSketchOn('XZ')
|> startProfileAt([11.8, 9.09], %) |> startProfileAt([11.8, 9.09], %)
|> line(end = [3.39, -3.39]) |> line(end = [3.39, -3.39])
` `
) )
}) })
await u.openDebugPanel() await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]') await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel() await u.closeDebugPanel()
// expect there to be no planes on load since there's something in the scene // expect there to be no planes on load since there's something in the scene
expect( expect(
await u.getGreatestPixDiff(XYPlanePoint, noPlanesColor) await u.getGreatestPixDiff(XYPlanePoint, noPlanesColor)
).toBeLessThan(3) ).toBeLessThan(3)
} })
)
test('Can attempt to sketch on revolved face', async ({ page, homePage }) => { test('Can attempt to sketch on revolved face', async ({ page, homePage }) => {
const u = await getUtils(page) const u = await getUtils(page)
@ -1460,10 +1462,11 @@ test.describe(`Sketching with offset planes`, () => {
}) })
test.describe('multi-profile sketching', () => { test.describe('multi-profile sketching', () => {
test.fixme( test(
`test it removes half-finished expressions when changing tools in sketch mode`, `test it removes half-finished expressions when changing tools in sketch mode`,
{ tag: ['@skipWin'] }, { tag: ['@skipWin'] },
async ({ context, page, scene, toolbar, editor, homePage, cmdBar }) => { 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 // We seed the scene with a single offset plane
await context.addInitScript(() => { await context.addInitScript(() => {
localStorage.setItem( localStorage.setItem(
@ -2852,13 +2855,18 @@ loft([profile001, profile002])
) )
} }
) )
test.fixme( test('Can enter sketch loft edges offsetPlane and continue sketch', async ({
'Can enter sketch loft edges offsetPlane and continue sketch', scene,
async ({ scene, toolbar, editor, page, homePage }) => { toolbar,
await page.addInitScript(async () => { editor,
localStorage.setItem( page,
'persistCode', homePage,
`sketch001 = startSketchOn('XZ') }) => {
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) profile001 = startProfileAt([34, 42.66], sketch001)
|> line(end = [102.65, 151.99]) |> line(end = [102.65, 151.99])
|> line(end = [76, -138.66]) |> line(end = [76, -138.66])
@ -2874,51 +2882,50 @@ profile002 = startProfileAt([39.43, 172.21], sketch002)
loft([profile001, profile002]) 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) await page.setBodyDimensions({ width: 1000, height: 500 })
const [rect1Crn2] = scene.makeMouseHelpers(797, 268) await homePage.goToModelingScene()
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).not.toBeDisabled()
await scene.moveCameraTo( const topProfileEdgeClickCoords = { x: 602, y: 185 } as const
{ x: 8171, y: -7740, z: 1624 }, const [topProfileEdgeClick] = scene.makeMouseHelpers(
{ x: 3302, y: -627, z: 2892 } topProfileEdgeClickCoords.x,
) topProfileEdgeClickCoords.y
)
const [sideProfileEdgeClick] = scene.makeMouseHelpers(788, 188)
await topProfileEdgeClick() const [rect1Crn1] = scene.makeMouseHelpers(592, 283)
await page.waitForTimeout(300) const [rect1Crn2] = scene.makeMouseHelpers(797, 268)
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 scene.moveCameraTo(
await page.waitForTimeout(100) { x: 8171, y: -7740, z: 1624 },
await rect1Crn1() { x: 3302, y: -627, z: 2892 }
await editor.expectEditor.toContain( )
`profile003 = startProfileAt([47.76, -17.13], plane001)`
) await topProfileEdgeClick()
await rect1Crn2() await page.waitForTimeout(300)
await editor.expectEditor.toContain( await toolbar.editSketch()
`angledLine([0, 106.42], %, $rectangleSegmentA001)` await page.waitForTimeout(600)
) await sideProfileEdgeClick()
await page.waitForTimeout(100) 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 // 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. // 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 // The primary failure is doExport now relies on the filesystem. We can follow
// up with another PR if we want this back. // up with another PR if we want this back.
test.skip( test(
'exports of each format should work', 'exports of each format should work',
{ tag: ['@snapshot', '@skipWin', '@skipMacos'] }, { tag: ['@snapshot', '@skipWin', '@skipMacos'] },
async ({ page, context, scene, cmdBar, tronApp }) => { async ({ page, context, scene, cmdBar, tronApp }) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
if (!tronApp) { if (!tronApp) {
fail() fail()
} }
@ -406,9 +407,6 @@ test(
'Draft segments should look right', 'Draft segments should look right',
{ tag: '@snapshot' }, { tag: '@snapshot' },
async ({ page, scene, toolbar }) => { async ({ page, scene, toolbar }) => {
// FIXME: Skip on macos its being weird.
// test.skip(process.platform === 'darwin', 'Skip on macos')
const u = await getUtils(page) const u = await getUtils(page)
await page.setViewportSize({ width: 1200, height: 500 }) await page.setViewportSize({ width: 1200, height: 500 })
const PUR = 400 / 37.5 //pixeltoUnitRatio const PUR = 400 / 37.5 //pixeltoUnitRatio
@ -585,9 +583,6 @@ test(
'Draft circle should look right', 'Draft circle should look right',
{ tag: '@snapshot' }, { tag: '@snapshot' },
async ({ page, context, cmdBar, scene }) => { 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) const u = await getUtils(page)
await page.setViewportSize({ width: 1200, height: 500 }) await page.setViewportSize({ width: 1200, height: 500 })
const PUR = 400 / 37.5 //pixeltoUnitRatio const PUR = 400 / 37.5 //pixeltoUnitRatio
@ -952,9 +947,6 @@ test(
) )
test.describe('Grid visibility', { tag: '@snapshot' }, () => { 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 ({ test('Grid turned off to on via command bar', async ({
page, page,
cmdBar, 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) const u = await getUtils(page)
await context.addInitScript(async () => { await context.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(

View File

@ -3,11 +3,12 @@ import { commonPoints, getUtils } from './test-utils'
import { EngineCommand } from 'lang/std/artifactGraph' import { EngineCommand } from 'lang/std/artifactGraph'
import { uuidv4 } from 'lib/utils' import { uuidv4 } from 'lib/utils'
test.fixme('Test network and connection issues', () => { test.describe('Test network and connection issues', () => {
test( test(
'simulate network down and network little widget', 'simulate network down and network little widget',
{ tag: '@skipLocalEngine' }, { tag: '@skipLocalEngine' },
async ({ page, homePage }) => { async ({ page, homePage }) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
const u = await getUtils(page) const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
@ -84,6 +85,7 @@ test.fixme('Test network and connection issues', () => {
'Engine disconnect & reconnect in sketch mode', 'Engine disconnect & reconnect in sketch mode',
{ tag: '@skipLocalEngine' }, { tag: '@skipLocalEngine' },
async ({ page, homePage, toolbar }) => { async ({ page, homePage, toolbar }) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
const networkToggle = page.getByTestId('network-toggle') const networkToggle = page.getByTestId('network-toggle')
const u = await getUtils(page) 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 // TODO: fix after electron migration is merged
test.fixme( test('Zoom should be consistent when exiting or entering sketches', async ({
'Zoom should be consistent when exiting or entering sketches', page,
async ({ page, homePage }) => { 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 test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
// than again for sketching // 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) const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await u.waitForPageLoad() await u.waitForPageLoad()
await u.openDebugPanel() await u.openDebugPanel()
await expect( await expect(
page.getByRole('button', { name: 'Start Sketch' }) page.getByRole('button', { name: 'Start Sketch' })
).not.toBeDisabled() ).not.toBeDisabled()
await expect( await expect(
page.getByRole('button', { name: 'Start Sketch' }) page.getByRole('button', { name: 'Start Sketch' })
).toBeVisible() ).toBeVisible()
// click on "Start Sketch" button // click on "Start Sketch" button
await u.clearCommandLogs() await u.clearCommandLogs()
await page.getByRole('button', { name: 'Start Sketch' }).click() 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) await page.waitForTimeout(100)
await expect(page.getByTestId('hover-highlight')).not.toBeVisible({
// 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({
timeout: 10_000, 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 ({ test(`Zoom by scroll should not fire while orbiting`, async ({
homePage, homePage,

View File

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

View File

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

View File

@ -55,91 +55,87 @@ test.describe('Testing settings', () => {
}) })
// The behavior is actually broken. Parent always takes precedence // The behavior is actually broken. Parent always takes precedence
test.fixme( test('Project settings can be set and override user settings', async ({
'Project settings can be set and override user settings', page,
async ({ page, homePage }) => { homePage,
const u = await getUtils(page) }) => {
await test.step(`Setup`, async () => { test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
await page.setBodyDimensions({ width: 1200, height: 500 }) const u = await getUtils(page)
await homePage.goToModelingScene() await test.step(`Setup`, async () => {
await page await page.setBodyDimensions({ width: 1200, height: 500 })
.getByRole('button', { name: 'Start Sketch' }) await homePage.goToModelingScene()
.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()
await page await page
.getByRole('button', { .getByRole('button', { name: 'Start Sketch' })
name: 'Roll back show debug panel', .waitFor({ state: 'visible' })
}) })
.click()
await expect(inputLocator).not.toBeChecked()
// Check that the project setting did not change // Selectors and constants
await page.getByRole('radio', { name: 'Project' }).click() const paneButtonLocator = page.getByTestId('debug-pane-button')
await expect( const headingLocator = page.getByRole('heading', {
page.locator('input[name="app-showDebugPanel"]') name: 'Settings',
).not.toBeChecked() 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 ({ test('Keybindings display the correct hotkey for Command Palette', async ({
page, page,
@ -175,103 +171,98 @@ test.describe('Testing settings', () => {
await expect(hotkey).toHaveText(text) await expect(hotkey).toHaveText(text)
}) })
test.fixme( test('Project and user settings can be reset', async ({ page, homePage }) => {
'Project and user settings can be reset', test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
async ({ page, homePage }) => { const u = await getUtils(page)
const u = await getUtils(page) await test.step(`Setup`, async () => {
await test.step(`Setup`, async () => { await page.setBodyDimensions({ width: 1200, height: 500 })
await page.setBodyDimensions({ width: 1200, height: 500 }) await homePage.goToModelingScene()
await homePage.goToModelingScene() await u.waitForPageLoad()
await u.waitForPageLoad() await page.waitForTimeout(1000)
await page.waitForTimeout(1000) })
})
// Selectors and constants
// Selectors and constants const projectSettingsTab = page.getByRole('radio', { name: 'Project' })
const projectSettingsTab = page.getByRole('radio', { name: 'Project' }) const userSettingsTab = page.getByRole('radio', { name: 'User' })
const userSettingsTab = page.getByRole('radio', { name: 'User' }) const resetButton = (level: SettingsLevel) =>
const resetButton = (level: SettingsLevel) => page.getByRole('button', {
page.getByRole('button', { name: `Reset ${level}-level settings`,
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)
})
}) })
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`, `Project settings override user settings on desktop`,
{ tag: ['@electron', '@skipWin'] }, { tag: ['@electron', '@skipWin'] },
async ({ context, page }, testInfo) => { async ({ context, page }, testInfo) => {
test.skip( test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
process.platform === 'win32',
'TODO: remove this skip https://github.com/KittyCAD/modeling-app/issues/3557'
)
const projectName = 'bracket' const projectName = 'bracket'
const { dir: projectDirName } = await context.folderSetupFn( const { dir: projectDirName } = await context.folderSetupFn(
async (dir) => { async (dir) => {
@ -407,12 +398,13 @@ test.describe('Testing settings', () => {
) )
// It was much easier to test the logo color than the background stream color. // 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', 'user settings reload on external change, on project and modeling view',
{ {
tag: '@electron', tag: '@electron',
}, },
async ({ context, page, tronApp }, testInfo) => { async ({ context, page, tronApp }, testInfo) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
if (!tronApp) { if (!tronApp) {
fail() fail()
} }
@ -466,10 +458,11 @@ test.describe('Testing settings', () => {
} }
) )
test.fixme( test(
'project settings reload on external change', 'project settings reload on external change',
{ tag: '@electron' }, { tag: '@electron' },
async ({ context, page }, testInfo) => { async ({ context, page }, testInfo) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
const { dir: projectDirName } = await context.folderSetupFn( const { dir: projectDirName } = await context.folderSetupFn(
async () => {} async () => {}
) )
@ -982,63 +975,68 @@ fn cube`
/** /**
* This test assumes that the default value of the "highlight edges" setting is "on". * This test assumes that the default value of the "highlight edges" setting is "on".
*/ */
test.fixme( test(`Toggle stream settings multiple times`, async ({
`Toggle stream settings multiple times`, page,
async ({ page, scene, homePage, context, toolbar, cmdBar }, testInfo) => { scene,
await context.folderSetupFn(async (dir) => { homePage,
const projectDir = join(dir, 'project-000') context,
await fsp.mkdir(projectDir, { recursive: true }) toolbar,
await fsp.copyFile( cmdBar,
executorInputPath('cube.kcl'), }, testInfo) => {
join(projectDir, 'main.kcl') 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 test.step(`First snapshot`, async () => {
await homePage.openProject('project-000') await homePage.openProject('project-000')
await toolbar.closePane('code') await toolbar.closePane('code')
await expect(toolbar.startSketchBtn).toBeEnabled({ timeout: 20_000 }) await expect(toolbar.startSketchBtn).toBeEnabled({ timeout: 20_000 })
await scene.clickNoWhere() await scene.clickNoWhere()
}) })
const toast = (value: boolean) => const toast = (value: boolean) =>
page.getByText( page.getByText(
`Set highlight edges to "${String(value)}" as a user default` `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')],
}
) )
await test.step(`Toggle highlightEdges on`, async () => { await test.step(`Toggle highlightEdges off`, async () => {
await cmdBar.openCmdBar() await cmdBar.openCmdBar()
await cmdBar.chooseCommand('Settings · modeling · highlight edges') await cmdBar.chooseCommand('Settings · modeling · highlight edges')
await cmdBar.selectOption({ name: 'on' }).click() await cmdBar.selectOption({ name: 'off' }).click()
const trueToast = toast(true) const falseToast = toast(false)
await expect(trueToast).toBeVisible() await expect(falseToast).toBeVisible()
await trueToast.waitFor({ state: 'detached' }) await falseToast.waitFor({ state: 'detached' })
}) })
await expect(scene.streamWrapper).toHaveScreenshot( await expect(scene.streamWrapper).not.toHaveScreenshot(
'toggle-settings-initial.png', 'toggle-settings-initial.png',
{ {
maxDiffPixels: 15, maxDiffPixels: 15,
mask: [page.getByTestId('model-state-indicator')], 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 // 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', 'can do many at once and get many prompts back, and interact with many',
{ tag: ['@skipWin'] }, { tag: ['@skipWin'] },
async ({ page, homePage }) => { async ({ page, homePage }) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
// Let this test run longer since we've seen it timeout. // Let this test run longer since we've seen it timeout.
test.setTimeout(180_000) test.setTimeout(180_000)
@ -619,10 +620,11 @@ async function sendPromptFromCommandBar(page: Page, promptStr: string) {
}) })
} }
test.fixme( test(
'Text-to-CAD functionality', 'Text-to-CAD functionality',
{ tag: '@electron' }, { tag: '@electron' },
async ({ context, page }, testInfo) => { async ({ context, page }, testInfo) => {
test.fixme(process.env.GITHUB_HEAD_REF !== 'all-e2e')
const projectName = 'project-000' const projectName = 'project-000'
const prompt = 'lego 2x4' const prompt = 'lego 2x4'
const textToCadFileName = 'lego-2x4.kcl' const textToCadFileName = 'lego-2x4.kcl'

View File

@ -2,7 +2,8 @@ import { test, expect } from './zoo-test'
import { doExport, getUtils, makeTemplate } from './test-utils' 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 page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
@ -263,186 +264,187 @@ test('First escape in tool pops you out of tool, second exits sketch mode', asyn
).not.toBeVisible() ).not.toBeVisible()
}) })
test.fixme( test('Basic default modeling and sketch hotkeys work', async ({
'Basic default modeling and sketch hotkeys work', page,
async ({ page, homePage }) => { homePage,
const u = await getUtils(page) }) => {
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 // This test can run long if it takes a little too long to load
// the engine. // the engine.
test.setTimeout(90000) test.setTimeout(90000)
// This test has a weird bug on ubuntu // This test has a weird bug on ubuntu
// Funny, it's flaking on Windows too :). I think there is just something // Funny, it's flaking on Windows too :). I think there is just something
// actually wrong. // actually wrong.
test.skip( test.skip(
process.platform === 'linux', process.platform === 'linux',
'weird playwright bug on ubuntu https://github.com/KittyCAD/modeling-app/issues/2444' 'weird playwright bug on ubuntu https://github.com/KittyCAD/modeling-app/issues/2444'
) )
// Load the app with the code pane open // Load the app with the code pane open
await test.step(`Set up test`, async () => { await test.step(`Set up test`, async () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'store', 'store',
JSON.stringify({ JSON.stringify({
state: { state: {
openPanes: ['code'], openPanes: ['code'],
}, },
version: 0, 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 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 () => { const codePane = page.locator('.cm-content')
// Since there's code now, we have to get to the end of the line const lineButton = page.getByRole('button', {
await page.locator('.cm-line').last().click() name: 'line Line',
await page.keyboard.down('ControlOrMeta') exact: true,
await page.keyboard.press('ArrowRight') })
await page.keyboard.up('ControlOrMeta') 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 test.step(`Type code with modeling hotkeys, shouldn't fire`, async () => {
await page.keyboard.type('//') await codePane.click()
await page.keyboard.press('l') await page.keyboard.type('//')
await expect(lineButton).toHaveAttribute('aria-pressed', 'true') await page.keyboard.press('s')
await page.keyboard.press('a') await expect(commandBarComboBox).not.toBeVisible()
await expect(lineButton).toHaveAttribute('aria-pressed', 'true') await page.keyboard.press('e')
await expect(codePane).toContainText('//la') await expect(commandBarComboBox).not.toBeVisible()
await page.keyboard.press('Backspace') await expect(codePane).toHaveText('//se')
await page.keyboard.press('Backspace') })
await page.keyboard.press('Backspace')
await page.keyboard.press('Backspace') // 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 () => { // Use some sketch hotkeys to create a sketch (l and a for now)
await blurCodeEditor() 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.move(700, 200, { steps: 5 })
await page.mouse.click(700, 200) await page.mouse.click(700, 200)
// On close it will unequip the line tool. await page.mouse.move(800, 250, { steps: 5 })
await expect(lineButton).toHaveAttribute('aria-pressed', 'false') await page.mouse.click(800, 250)
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(`Unequip line tool`, async () => {
await test.step(`Extrude the sketch`, async () => { await page.keyboard.press('l')
await page.mouse.click(750, 150) await expect(lineButton).not.toHaveAttribute('aria-pressed', 'true')
await blurCodeEditor() })
await expect(extrudeButton).toBeEnabled()
await page.keyboard.press('e') await test.step(`Draw a tangential arc`, async () => {
await page.waitForTimeout(500) await page.keyboard.press('a')
await page.mouse.move(800, 200, { steps: 5 }) await expect(arcButton).toHaveAttribute('aria-pressed', 'true', {
await page.mouse.click(800, 200) timeout: 10_000,
await expect(page.getByRole('button', { name: 'Continue' })).toBeVisible({
timeout: 20_000,
}) })
await page.getByRole('button', { name: 'Continue' }).click() await page.mouse.move(1000, 100, { steps: 5 })
await expect( await page.mouse.click(1000, 100)
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 test.step(`Unequip with escape, equip line tool`, async () => {
// 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.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 }) => { test('Delete key does not navigate back', async ({ page, homePage }) => {
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })