Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

selections e2e test #1136

Merged
merged 6 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 119 additions & 11 deletions e2e/playwright/flow-tests.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ test('Basic sketch', async ({ page }) => {
const u = getUtils(page)
await page.setViewportSize({ width: 1200, height: 500 })
const PUR = 400 / 37.5 //pixeltoUnitRatio
await page.goto('localhost:3000')
await page.goto('/')
await u.waitForAuthSkipAppStart()
await u.openDebugPanel()
await u.waitForDefaultPlanesVisibilityChange()
Expand Down Expand Up @@ -134,7 +134,7 @@ test('Basic sketch', async ({ page }) => {
test('if you write invalid kcl you get inlined errors', async ({ page }) => {
const u = getUtils(page)
await page.setViewportSize({ width: 1000, height: 500 })
await page.goto('localhost:3000')
await page.goto('/')

await u.waitForAuthSkipAppStart()

Expand All @@ -148,6 +148,11 @@ test('if you write invalid kcl you get inlined errors', async ({ page }) => {
*/
await page.click('.cm-content')
await page.keyboard.type('# error')

// press arrows to clear autocomplete
await page.keyboard.press('ArrowLeft')
await page.keyboard.press('ArrowRight')

await page.keyboard.press('Enter')
await page.keyboard.type('const topAng = 30')
await page.keyboard.press('Enter')
Expand Down Expand Up @@ -186,7 +191,7 @@ test('executes on load', async ({ page, context }) => {
)
})
await page.setViewportSize({ width: 1000, height: 500 })
await page.goto('localhost:3000')
await page.goto('/')
await u.waitForAuthSkipAppStart()

// expand variables section
Expand All @@ -211,7 +216,7 @@ test('re-executes', async ({ page, context }) => {
localStorage.setItem('persistCode', `const myVar = 5`)
})
await page.setViewportSize({ width: 1000, height: 500 })
await page.goto('localhost:3000')
await page.goto('/')
await u.waitForAuthSkipAppStart()

await page.getByText('Variables').click()
Expand All @@ -237,7 +242,7 @@ test('Can create sketches on all planes and their back sides', async ({
const u = getUtils(page)
const PUR = 400 / 37.5 //pixeltoUnitRatio
await page.setViewportSize({ width: 1200, height: 500 })
await page.goto('localhost:3000')
await page.goto('/')
await u.waitForAuthSkipAppStart()
await u.openDebugPanel()
await u.waitForDefaultPlanesVisibilityChange()
Expand Down Expand Up @@ -354,7 +359,7 @@ test('Auto complete works', async ({ page }) => {
const u = getUtils(page)
// const PUR = 400 / 37.5 //pixeltoUnitRatio
await page.setViewportSize({ width: 1200, height: 500 })
await page.goto('localhost:3000')
await page.goto('/')
await u.waitForAuthSkipAppStart()
await u.waitForDefaultPlanesVisibilityChange()

Expand Down Expand Up @@ -410,18 +415,18 @@ test('Onboarding redirects and code updating', async ({ page, context }) => {
})

await page.setViewportSize({ width: 1200, height: 500 })
await page.goto('localhost:3000')
await page.goto('/')
await u.waitForAuthSkipAppStart()

// Test that the redirect happened
await expect(page.url()).toBe(
`http://localhost:3000/file/new/onboarding/export`
await expect(page.url().split(':3000').slice(-1)[0]).toBe(
`/file/new/onboarding/export`
)

// Test that you come back to this page when you refresh
await page.reload()
await expect(page.url()).toBe(
`http://localhost:3000/file/new/onboarding/export`
await expect(page.url().split(':3000').slice(-1)[0]).toBe(
`/file/new/onboarding/export`
)

// Test that the onboarding pane loaded
Expand All @@ -436,3 +441,106 @@ test('Onboarding redirects and code updating', async ({ page, context }) => {
await page.locator('[data-testid="onboarding-next"]').click()
await expect(page.locator('.cm-content')).toHaveText(/.+/)
})

test('Selections work on fresh and edited sketch', async ({ page }) => {
// tests mapping works on fresh sketch and edited sketch
// tests using hovers which is the same as selections, because if
// source ranges are wrong, hovers won't work
const u = getUtils(page)
const PUR = 400 / 37.5 //pixeltoUnitRatio
await page.setViewportSize({ width: 1200, height: 500 })
await page.goto('/')
await u.waitForAuthSkipAppStart()
await u.openDebugPanel()
await u.waitForDefaultPlanesVisibilityChange()

await u.clearCommandLogs()
await page.getByRole('button', { name: 'Start Sketch' }).click()
await u.waitForDefaultPlanesVisibilityChange()

// select a plane
await u.doAndWaitForCmd(() => page.mouse.click(700, 200), 'edit_mode_enter')
await u.waitForCmdReceive('set_tool')

await u.doAndWaitForCmd(
() => page.getByRole('button', { name: 'Line' }).click(),
'set_tool'
)

const startXPx = 600
await u.doAndWaitForCmd(
() => page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10),
'mouse_click',
false
)

await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10)

const startAt = '[9.94, -13.41]'
const tenish = '10.03'
await expect(page.locator('.cm-content'))
.toHaveText(`const part001 = startSketchOn('-XZ')
|> startProfileAt(${startAt}, %)
|> line([${tenish}, 0], %)`)

await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 20)
await expect(page.locator('.cm-content'))
.toHaveText(`const part001 = startSketchOn('-XZ')
|> startProfileAt(${startAt}, %)
|> line([${tenish}, 0], %)
|> line([0, ${tenish}], %)`)
await page.mouse.click(startXPx, 500 - PUR * 20)
await expect(page.locator('.cm-content'))
.toHaveText(`const part001 = startSketchOn('-XZ')
|> startProfileAt(${startAt}, %)
|> line([${tenish}, 0], %)
|> line([0, ${tenish}], %)
|> line([-19.97, 0], %)`)

// deselect line tool
await u.doAndWaitForCmd(
() => page.getByRole('button', { name: 'Line' }).click(),
'set_tool'
)

await u.closeDebugPanel()
const hoverSequency = async () => {
await expect(page.getByTestId('hover-highlight')).not.toBeVisible()

await page.mouse.move(startXPx + PUR * 15, 500 - PUR * 10)

await expect(page.getByTestId('hover-highlight')).toBeVisible()
// bg-yellow-200 is more brittle than hover-highlight, but is closer to the user experience
// and will be an easy fix if it breaks because we change the colour
await expect(page.locator('.bg-yellow-200')).toBeVisible()

// check mousing off, than mousing onto another line
await page.mouse.move(startXPx + PUR * 10, 500 - PUR * 15) // mouse off
await expect(page.getByTestId('hover-highlight')).not.toBeVisible()
await page.mouse.move(startXPx + PUR * 10, 500 - PUR * 20) // mouse onto another line
await expect(page.getByTestId('hover-highlight')).toBeVisible()
}
await hoverSequency()

// hovering in fresh sketch worked, lets try exiting and re-entering
await u.doAndWaitForCmd(
() => page.getByRole('button', { name: 'Exit Sketch' }).click(),
'edit_mode_exit'
)

// select a line
await u.doAndWaitForCmd(
() => page.mouse.click(startXPx + PUR * 10, 500 - PUR * 20),
'select_with_point'
)

// enter sketch again
await u.doAndWaitForCmd(
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
'edit_mode_enter',
false
)

// hover again and check it works
await hoverSequency()
})
2 changes: 1 addition & 1 deletion e2e/playwright/snapshot-tests.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ test.setTimeout(60000)
test('change camera, show planes', async ({ page, context }) => {
const u = getUtils(page)
await page.setViewportSize({ width: 1200, height: 500 })
await page.goto('localhost:3000')
await page.goto('/')
await u.waitForAuthSkipAppStart()
await u.openAndClearDebugPanel()

Expand Down
2 changes: 0 additions & 2 deletions e2e/playwright/test-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import { expect, Page } from '@playwright/test'
import { EngineCommand } from '../../src/lang/std/engineConnection'

async function waitForPageLoad(page: Page) {
// wait for 'Loading KittyCAD Modeling App...' spinner
await page.getByTestId('initial-load').waitFor()
// wait for 'Loading stream...' spinner
await page.getByTestId('loading-stream').waitFor()
// wait for all spinners to be gone
Expand Down
2 changes: 1 addition & 1 deletion playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default defineConfig({
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
// baseURL: 'http://127.0.0.1:3000',
baseURL: 'http://localhost:3000',

/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
Expand Down
2 changes: 1 addition & 1 deletion src/components/EngineCommands.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const EngineCommands = () => {
const stringer = JSON.stringify(command)
if (containsFilter && !stringer.includes(containsFilter)) return null
return (
<pre className="text-xs">
<pre className="text-xs" key={index}>
<code
key={index}
data-message-type={command.type}
Expand Down
5 changes: 4 additions & 1 deletion src/editor/highlightextension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,7 @@ export const lineHighlightField = StateField.define({
provide: (f) => EditorView.decorations.from(f),
})

const matchDeco = Decoration.mark({ class: 'bg-yellow-200' })
const matchDeco = Decoration.mark({
class: 'bg-yellow-200',
attributes: { 'data-testid': 'hover-highlight' },
})
10 changes: 5 additions & 5 deletions src/lang/std/engineConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ type ClientMetrics = Models['ClientMetrics_type']
// EngineConnection encapsulates the connection(s) to the Engine
// for the EngineCommandManager; namely, the underlying WebSocket
// and WebRTC connections.
export class EngineConnection {
class EngineConnection {
websocket?: WebSocket
pc?: RTCPeerConnection
unreliableDataChannel?: RTCDataChannel
Expand Down Expand Up @@ -610,10 +610,9 @@ export type CommandLog =
data: null
}

type CommandLogTypes = Extract<CommandLog, { type: string }>['type']

export class EngineCommandManager {
artifactMap: ArtifactMap = {}
lastArtifactMap: ArtifactMap = {}
outSequence = 1
inSequence = 1
engineConnection?: EngineConnection
Expand Down Expand Up @@ -810,17 +809,17 @@ export class EngineCommandManager {
return
}
const modelingResponse = message.data.modeling_response
const command = this.artifactMap[id]
this.addCommandLog({
type: 'receive-reliable',
data: message,
id,
cmd_type: this.artifactMap[id]?.commandType,
cmd_type: command?.commandType || this.lastArtifactMap[id]?.commandType,
})
Object.values(this.subscriptions[modelingResponse.type] || {}).forEach(
(callback) => callback(modelingResponse)
)

const command = this.artifactMap[id]
if (command && command.type === 'pending') {
const resolve = command.resolve
this.artifactMap[id] = {
Expand Down Expand Up @@ -884,6 +883,7 @@ export class EngineCommandManager {
this.engineConnection?.tearDown()
}
startNewSession() {
this.lastArtifactMap = this.artifactMap
this.artifactMap = {}
}
subscribeTo<T extends ModelTypes>({
Expand Down
3 changes: 1 addition & 2 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@
"jsx": "react-jsx"
},
"include": [
"src",
"e2e"
"src"
],
"references": [{ "path": "./tsconfig.node.json" }]
}