2024-05-24 20:54:42 +10:00
import { test , expect , Page } from '@playwright/test'
2024-06-04 08:32:24 -04:00
import {
makeTemplate ,
getUtils ,
getMovementUtils ,
wiggleMove ,
doExport ,
2024-06-04 14:36:34 -04:00
metaModifier ,
2024-06-22 04:49:31 -04:00
TEST_COLORS ,
2024-06-04 08:32:24 -04:00
} from './test-utils'
2023-11-24 08:59:24 +11:00
import waitOn from 'wait-on'
2024-06-03 15:37:23 +10:00
import { XOR , roundOff , uuidv4 } from 'lib/utils'
2024-04-02 10:29:34 -04:00
import { SaveSettingsPayload } from 'lib/settings/settingsTypes'
2024-04-11 13:37:49 -04:00
import { secrets } from './secrets'
import {
TEST_SETTINGS ,
TEST_SETTINGS_KEY ,
TEST_SETTINGS_CORRUPTED ,
2024-04-26 13:20:03 -04:00
TEST_SETTINGS_ONBOARDING_EXPORT ,
TEST_SETTINGS_ONBOARDING_START ,
2024-06-06 19:56:46 -04:00
TEST_CODE_GIZMO ,
2024-06-20 14:06:11 -04:00
TEST_SETTINGS_ONBOARDING_USER_MENU ,
2024-06-20 21:39:01 -04:00
TEST_SETTINGS_ONBOARDING_PARAMETRIC_MODELING ,
2024-04-11 13:37:49 -04:00
} from './storageStates'
2024-04-16 21:36:19 -07:00
import * as TOML from '@iarna/toml'
2024-05-24 20:54:42 +10:00
import { LineInputsType } from 'lang/std/sketchcombos'
2024-05-09 15:04:33 +10:00
import { Coords2d } from 'lang/std/sketch'
2024-05-17 10:29:04 -04:00
import { KCL_DEFAULT_LENGTH } from 'lib/constants'
2024-05-23 22:02:25 +02:00
import { EngineCommand } from 'lang/std/engineConnection'
2024-06-20 21:39:01 -04:00
import { onboardingPaths } from 'routes/Onboarding/paths'
import { bracket } from 'lib/exampleKcl'
2023-11-24 08:59:24 +11:00
2024-07-02 17:16:27 +10:00
const PERSIST_MODELING_CONTEXT = 'persistModelingContext'
2023-11-24 08:59:24 +11:00
/ *
debug helper : unfortunately we do rely on exact coord mouse clicks in a few places
just from the nature of the stream , running the test with debugger and pasting the below
into the console can be useful to get coords
document . addEventListener ( 'mousemove' , ( e ) = >
console . log ( ` await page.mouse.click( ${ e . clientX } , ${ e . clientY } ) ` )
)
* /
2024-06-04 08:32:24 -04:00
const deg = ( Math . PI * 2 ) / 360
2024-02-26 19:53:44 +11:00
const commonPoints = {
2024-06-18 16:08:41 +10:00
startAt : '[7.19, -9.7]' ,
num1 : 7.25 ,
num2 : 14.44 ,
2024-03-22 10:23:04 +11:00
// num1: 9.64,
// num2: 19.19,
2024-02-26 19:53:44 +11:00
}
2024-07-07 13:10:52 -04:00
test . afterEach ( async ( { context , page } , testInfo ) = > {
if ( testInfo . status === 'skipped' ) return
if ( testInfo . status === 'failed' ) return
const u = await getUtils ( page )
// Kill the network so shutdown happens properly
await u . emulateNetworkConditions ( {
offline : true ,
// values of 0 remove any active throttling. crbug.com/456324#c9
latency : 0 ,
downloadThroughput : - 1 ,
uploadThroughput : - 1 ,
} )
// It seems it's best to give the browser about 3s to close things
// It's not super reliable but we have no real other choice for now
await page . waitForTimeout ( 3000 )
} )
2024-06-04 08:32:24 -04:00
2023-11-24 08:59:24 +11:00
test . beforeEach ( async ( { context , page } ) = > {
// wait for Vite preview server to be up
await waitOn ( {
resources : [ 'tcp:3000' ] ,
timeout : 5000 ,
} )
2024-04-02 10:29:34 -04:00
2024-04-11 13:37:49 -04:00
await context . addInitScript (
async ( { token , settingsKey , settings } ) = > {
localStorage . setItem ( 'TOKEN_PERSIST_KEY' , token )
localStorage . setItem ( 'persistCode' , ` ` )
localStorage . setItem ( settingsKey , settings )
2024-05-24 21:59:51 +10:00
localStorage . setItem ( 'playwright' , 'true' )
2024-04-11 13:37:49 -04:00
} ,
{
token : secrets.token ,
settingsKey : TEST_SETTINGS_KEY ,
settings : TOML.stringify ( { settings : TEST_SETTINGS } ) ,
}
)
2023-11-24 08:59:24 +11:00
// kill animations, speeds up tests and reduced flakiness
await page . emulateMedia ( { reducedMotion : 'reduce' } )
} )
2024-07-07 13:10:52 -04:00
test . setTimeout ( 120000 )
2023-11-24 08:59:24 +11:00
2024-06-22 02:21:13 -07:00
async function doBasicSketch ( page : Page , openPanes : string [ ] ) {
2024-05-23 02:20:40 -07:00
const u = await getUtils ( page )
2023-11-24 08:59:24 +11:00
await page . setViewportSize ( { width : 1200 , height : 500 } )
const PUR = 400 / 37.5 //pixeltoUnitRatio
2024-06-29 18:10:07 -07:00
2023-11-24 08:59:24 +11:00
await u . waitForAuthSkipAppStart ( )
await u . openDebugPanel ( )
2024-06-22 02:21:13 -07:00
// If we have the code pane open, we should see the code.
if ( openPanes . includes ( 'code' ) ) {
await expect ( u . codeLocator ) . toHaveText ( ` ` )
} else {
// Ensure we don't see the code.
await expect ( u . codeLocator ) . not . toBeVisible ( )
}
2024-02-26 21:02:33 +11:00
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . not . toBeDisabled ( )
2023-11-24 08:59:24 +11:00
await expect ( page . getByRole ( 'button' , { name : 'Start Sketch' } ) ) . toBeVisible ( )
// click on "Start Sketch" button
await u . clearCommandLogs ( )
2024-03-02 11:25:50 +11:00
await page . getByRole ( 'button' , { name : 'Start Sketch' } ) . click ( )
await page . waitForTimeout ( 100 )
2023-11-24 08:59:24 +11:00
// select a plane
2024-02-11 12:59:00 +11:00
await page . mouse . click ( 700 , 200 )
2023-11-24 08:59:24 +11:00
2024-06-22 02:21:13 -07:00
if ( openPanes . includes ( 'code' ) ) {
await expect ( u . codeLocator ) . toHaveText (
` const sketch001 = startSketchOn('XZ') `
)
}
2024-03-22 10:23:04 +11:00
await u . closeDebugPanel ( )
2023-11-24 08:59:24 +11:00
2024-06-22 02:21:13 -07:00
await page . waitForTimeout ( 1000 ) // TODO detect animation ending, or disable animation
2024-02-11 12:59:00 +11:00
2023-11-24 08:59:24 +11:00
const startXPx = 600
2024-02-11 12:59:00 +11:00
await page . mouse . click ( startXPx + PUR * 10 , 500 - PUR * 10 )
2024-06-22 02:21:13 -07:00
if ( openPanes . includes ( 'code' ) ) {
await expect ( u . codeLocator )
. toHaveText ( ` const sketch001 = startSketchOn('XZ')
2024-02-26 19:53:44 +11:00
| > startProfileAt ( $ { commonPoints . startAt } , % ) ` )
2024-06-22 02:21:13 -07:00
}
await page . waitForTimeout ( 500 )
2023-11-24 08:59:24 +11:00
await page . mouse . click ( startXPx + PUR * 20 , 500 - PUR * 10 )
2024-06-22 02:21:13 -07:00
await page . waitForTimeout ( 500 )
2023-11-24 08:59:24 +11:00
2024-06-22 02:21:13 -07:00
if ( openPanes . includes ( 'code' ) ) {
await expect ( u . codeLocator )
. toHaveText ( ` const sketch001 = startSketchOn('XZ')
2024-02-26 19:53:44 +11:00
| > startProfileAt ( $ { commonPoints . startAt } , % )
| > line ( [ $ { commonPoints . num1 } , 0 ] , % ) ` )
2024-06-22 02:21:13 -07:00
}
await page . waitForTimeout ( 500 )
2023-11-24 08:59:24 +11:00
await page . mouse . click ( startXPx + PUR * 20 , 500 - PUR * 20 )
2024-06-22 02:21:13 -07:00
if ( openPanes . includes ( 'code' ) ) {
await expect ( u . codeLocator )
. toHaveText ( ` const sketch001 = startSketchOn('XZ')
2024-02-26 19:53:44 +11:00
| > startProfileAt ( $ { commonPoints . startAt } , % )
| > line ( [ $ { commonPoints . num1 } , 0 ] , % )
2024-06-18 16:08:41 +10:00
| > line ( [ 0 , $ { commonPoints . num1 + 0.01 } ] , % ) ` )
2024-06-22 02:21:13 -07:00
}
await page . waitForTimeout ( 500 )
2023-11-24 08:59:24 +11:00
await page . mouse . click ( startXPx , 500 - PUR * 20 )
2024-06-22 02:21:13 -07:00
if ( openPanes . includes ( 'code' ) ) {
await expect ( u . codeLocator )
. toHaveText ( ` const sketch001 = startSketchOn('XZ')
2024-02-26 19:53:44 +11:00
| > startProfileAt ( $ { commonPoints . startAt } , % )
| > line ( [ $ { commonPoints . num1 } , 0 ] , % )
2024-06-18 16:08:41 +10:00
| > line ( [ 0 , $ { commonPoints . num1 + 0.01 } ] , % )
2024-02-26 19:53:44 +11:00
| > line ( [ - $ { commonPoints . num2 } , 0 ] , % ) ` )
2024-06-22 02:21:13 -07:00
}
2023-11-24 08:59:24 +11:00
// deselect line tool
2024-02-11 12:59:00 +11:00
await page . getByRole ( 'button' , { name : 'Line' } ) . click ( )
2024-06-22 02:21:13 -07:00
await page . waitForTimeout ( 500 )
2023-11-24 08:59:24 +11:00
2024-06-05 10:36:12 +10:00
const line1 = await u . getSegmentBodyCoords ( ` [data-overlay-index=" ${ 0 } "] ` , 0 )
2024-06-22 02:21:13 -07:00
if ( openPanes . includes ( 'code' ) ) {
expect ( await u . getGreatestPixDiff ( line1 , TEST_COLORS . WHITE ) ) . toBeLessThan ( 3 )
await expect (
await u . getGreatestPixDiff ( line1 , [ 249 , 249 , 249 ] )
) . toBeLessThan ( 3 )
}
2023-11-24 08:59:24 +11:00
// click between first two clicks to get center of the line
2024-02-11 12:59:00 +11:00
await page . mouse . click ( startXPx + PUR * 15 , 500 - PUR * 10 )
await page . waitForTimeout ( 100 )
2024-06-22 02:21:13 -07:00
if ( openPanes . includes ( 'code' ) ) {
expect ( await u . getGreatestPixDiff ( line1 , TEST_COLORS . BLUE ) ) . toBeLessThan ( 3 )
await expect ( await u . getGreatestPixDiff ( line1 , [ 0 , 0 , 255 ] ) ) . toBeLessThan ( 3 )
}
2023-11-24 08:59:24 +11:00
// hold down shift
await page . keyboard . down ( 'Shift' )
// click between the latest two clicks to get center of the line
await page . mouse . click ( startXPx + PUR * 10 , 500 - PUR * 20 )
// selected two lines therefore there should be two cursors
2024-06-22 02:21:13 -07:00
if ( openPanes . includes ( 'code' ) ) {
await expect ( page . locator ( '.cm-cursor' ) ) . toHaveCount ( 2 )
}
2023-11-24 08:59:24 +11:00
2024-06-24 11:37:48 -04:00
await page . getByRole ( 'button' , { name : 'Constraints' } ) . click ( )
2023-11-24 08:59:24 +11:00
await page . getByRole ( 'button' , { name : 'Equal Length' } ) . click ( )
2024-06-22 02:21:13 -07:00
// Open the code pane.
await u . openKclCodePanel ( )
2024-06-05 14:43:12 +02:00
await expect ( u . codeLocator ) . toHaveText ( ` const sketch001 = startSketchOn('XZ')
2024-02-26 19:53:44 +11:00
| > startProfileAt ( $ { commonPoints . startAt } , % )
2024-06-24 22:39:04 -07:00
| > line ( [ $ { commonPoints . num1 } , 0 ] , % , $seg01 )
2024-06-18 16:08:41 +10:00
| > line ( [ 0 , $ { commonPoints . num1 + 0.01 } ] , % )
2024-06-24 22:39:04 -07:00
| > angledLine ( [ 180 , segLen ( seg01 , % ) ] , % ) ` )
2024-06-22 02:21:13 -07:00
}
test . describe ( 'Basic sketch' , ( ) = > {
test ( 'code pane open at start' , async ( { page } ) = > {
await doBasicSketch ( page , [ 'code' ] )
} )
test ( 'code pane closed at start' , async ( { page } ) = > {
// Load the app with the code panes
2024-07-02 17:16:27 +10:00
await page . addInitScript ( async ( persistModelingContext ) = > {
2024-06-22 02:21:13 -07:00
localStorage . setItem (
2024-07-02 17:16:27 +10:00
persistModelingContext ,
JSON . stringify ( { openPanes : [ ] } )
2024-06-22 02:21:13 -07:00
)
2024-07-02 17:16:27 +10:00
} , PERSIST_MODELING_CONTEXT )
2024-06-22 02:21:13 -07:00
await doBasicSketch ( page , [ ] )
} )
2023-11-24 08:59:24 +11:00
} )
2024-06-18 16:08:41 +10:00
test . describe ( 'Testing Camera Movement' , ( ) = > {
test ( 'Can moving camera' , async ( { page , context } ) = > {
test . skip ( process . platform === 'darwin' , 'Can moving camera' )
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-06-18 16:08:41 +10:00
await u . waitForAuthSkipAppStart ( )
await u . openAndClearDebugPanel ( )
await u . closeKclCodePanel ( )
const camPos : [ number , number , number ] = [ 0 , 85 , 85 ]
const bakeInRetries = async (
mouseActions : any ,
xyz : [ number , number , number ] ,
cnt = 0
) = > {
// hack that we're implemented our own retry instead of using retries built into playwright.
// however each of these camera drags can be flaky, because of udp
// and so putting them together means only one needs to fail to make this test extra flaky.
// this way we can retry within the test
// We could break them out into separate tests, but the longest past of the test is waiting
// for the stream to start, so it can be good to bundle related things together.
const camCommand : EngineCommand = {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_look_at' ,
center : { x : 0 , y : 0 , z : 0 } ,
vantage : { x : camPos [ 0 ] , y : camPos [ 1 ] , z : camPos [ 2 ] } ,
up : { x : 0 , y : 0 , z : 1 } ,
} ,
}
const updateCamCommand : EngineCommand = {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_get_settings' ,
} ,
}
await u . sendCustomCmd ( camCommand )
await page . waitForTimeout ( 100 )
await u . sendCustomCmd ( updateCamCommand )
await page . waitForTimeout ( 100 )
// rotate
await u . closeDebugPanel ( )
await page . getByRole ( 'button' , { name : 'Start Sketch' } ) . click ( )
await page . waitForTimeout ( 100 )
// const yo = page.getByTestId('cam-x-position').inputValue()
await u . doAndWaitForImageDiff ( async ( ) = > {
await mouseActions ( )
await u . openAndClearDebugPanel ( )
await u . closeDebugPanel ( )
await page . waitForTimeout ( 100 )
} , 300 )
await u . openAndClearDebugPanel ( )
await page . getByTestId ( 'cam-x-position' ) . isVisible ( )
const vals = await Promise . all ( [
page . getByTestId ( 'cam-x-position' ) . inputValue ( ) ,
page . getByTestId ( 'cam-y-position' ) . inputValue ( ) ,
page . getByTestId ( 'cam-z-position' ) . inputValue ( ) ,
] )
const xError = Math . abs ( Number ( vals [ 0 ] ) + xyz [ 0 ] )
const yError = Math . abs ( Number ( vals [ 1 ] ) + xyz [ 1 ] )
const zError = Math . abs ( Number ( vals [ 2 ] ) + xyz [ 2 ] )
let shouldRetry = false
if ( xError > 5 || yError > 5 || zError > 5 ) {
if ( cnt > 2 ) {
console . log ( 'xVal' , vals [ 0 ] , 'xError' , xError )
console . log ( 'yVal' , vals [ 1 ] , 'yError' , yError )
console . log ( 'zVal' , vals [ 2 ] , 'zError' , zError )
throw new Error ( 'Camera position not as expected' )
}
shouldRetry = true
}
await page . getByRole ( 'button' , { name : 'Exit Sketch' } ) . click ( )
await page . waitForTimeout ( 100 )
if ( shouldRetry ) await bakeInRetries ( mouseActions , xyz , cnt + 1 )
}
await bakeInRetries ( async ( ) = > {
await page . mouse . move ( 700 , 200 )
await page . mouse . down ( { button : 'right' } )
await page . mouse . move ( 600 , 303 )
await page . mouse . up ( { button : 'right' } )
} , [ 4 , - 10.5 , - 120 ] )
await bakeInRetries ( async ( ) = > {
await page . keyboard . down ( 'Shift' )
await page . mouse . move ( 600 , 200 )
await page . mouse . down ( { button : 'right' } )
await page . mouse . move ( 700 , 200 , { steps : 2 } )
await page . mouse . up ( { button : 'right' } )
await page . keyboard . up ( 'Shift' )
} , [ - 19 , - 85 , - 85 ] )
2024-03-04 10:36:54 +11:00
2024-05-23 22:02:25 +02:00
const camCommand : EngineCommand = {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_look_at' ,
center : { x : 0 , y : 0 , z : 0 } ,
vantage : { x : camPos [ 0 ] , y : camPos [ 1 ] , z : camPos [ 2 ] } ,
up : { x : 0 , y : 0 , z : 1 } ,
} ,
}
const updateCamCommand : EngineCommand = {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_get_settings' ,
} ,
}
await u . sendCustomCmd ( camCommand )
await page . waitForTimeout ( 100 )
await u . sendCustomCmd ( updateCamCommand )
2024-03-04 10:36:54 +11:00
await page . waitForTimeout ( 100 )
2024-06-18 16:08:41 +10:00
await u . clearCommandLogs ( )
2024-03-04 10:36:54 +11:00
await u . closeDebugPanel ( )
2024-06-18 16:08:41 +10:00
2024-03-04 10:36:54 +11:00
await page . getByRole ( 'button' , { name : 'Start Sketch' } ) . click ( )
2024-06-18 16:08:41 +10:00
await page . waitForTimeout ( 200 )
2024-03-04 10:36:54 +11:00
2024-06-18 16:08:41 +10:00
// zoom
2024-03-04 10:36:54 +11:00
await u . doAndWaitForImageDiff ( async ( ) = > {
2024-06-18 16:08:41 +10:00
await page . keyboard . down ( 'Control' )
await page . mouse . move ( 700 , 400 )
await page . mouse . down ( { button : 'right' } )
await page . mouse . move ( 700 , 300 )
await page . mouse . up ( { button : 'right' } )
await page . keyboard . up ( 'Control' )
2024-03-04 10:36:54 +11:00
2024-06-18 16:08:41 +10:00
await u . openDebugPanel ( )
await page . waitForTimeout ( 300 )
await u . clearCommandLogs ( )
2024-03-04 10:36:54 +11:00
await u . closeDebugPanel ( )
} , 300 )
2024-06-18 16:08:41 +10:00
// zoom with scroll
2024-03-04 10:36:54 +11:00
await u . openAndClearDebugPanel ( )
2024-06-18 16:08:41 +10:00
// TODO, it appears we don't get the cam setting back from the engine when the interaction is zoom into `backInRetries` once the information is sent back on zoom
// await expect(Math.abs(Number(await page.getByTestId('cam-x-position').inputValue()) + 12)).toBeLessThan(1.5)
// await expect(Math.abs(Number(await page.getByTestId('cam-y-position').inputValue()) - 85)).toBeLessThan(1.5)
// await expect(Math.abs(Number(await page.getByTestId('cam-z-position').inputValue()) - 85)).toBeLessThan(1.5)
2024-03-04 10:36:54 +11:00
await page . getByRole ( 'button' , { name : 'Exit Sketch' } ) . click ( )
2024-06-18 16:08:41 +10:00
await bakeInRetries ( async ( ) = > {
await page . mouse . move ( 700 , 400 )
await page . mouse . wheel ( 0 , - 100 )
2024-07-03 01:50:40 +10:00
} , [ 0 , - 85 , - 85 ] )
2024-06-18 16:08:41 +10:00
} )
test ( 'Zoom should be consistent when exiting or entering sketches' , async ( {
page ,
} ) = > {
// start new sketch pan and zoom before exiting, when exiting the sketch should stay in the same place
// than zoom and pan outside of sketch mode and enter again and it should not change from where it is
// than again for sketching
test . skip ( process . platform !== 'darwin' , 'Zoom should be consistent' )
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-06-18 16:08:41 +10:00
await u . waitForAuthSkipAppStart ( )
await u . openDebugPanel ( )
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . not . toBeDisabled ( )
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . toBeVisible ( )
// click on "Start Sketch" button
await u . clearCommandLogs ( )
await page . getByRole ( 'button' , { name : 'Start Sketch' } ) . click ( )
2024-03-04 10:36:54 +11:00
await page . waitForTimeout ( 100 )
2024-06-18 16:08:41 +10:00
// select a plane
await page . mouse . click ( 700 , 325 )
let code = ` const 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
2024-03-04 10:36:54 +11:00
await page . keyboard . down ( 'Shift' )
2024-06-18 16:08:41 +10:00
await page . mouse . move ( 700 , 300 )
2024-03-04 10:36:54 +11:00
await page . mouse . down ( { button : 'right' } )
2024-06-18 16:08:41 +10:00
await page . mouse . move ( 800 , 200 )
2024-03-04 10:36:54 +11:00
await page . mouse . up ( { button : 'right' } )
await page . keyboard . up ( 'Shift' )
2024-05-23 22:02:25 +02:00
2024-06-18 16:08:41 +10:00
let y = 350 ,
x = 948
2024-03-04 10:36:54 +11:00
2024-06-18 16:08:41 +10:00
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([11.18, 0], %) `
// await expect(u.codeLocator).toHaveText(code)
await u . canvasLocator . click ( { position : { x , y : 275 } } )
code += ` \ n |> line([0, 6.99], %) `
// await expect(u.codeLocator).toHaveText(code)
2024-03-04 10:36:54 +11:00
2024-06-18 16:08:41 +10:00
// click the line button
await page . getByRole ( 'button' , { name : 'Line' } ) . click ( )
2024-03-04 10:36:54 +11:00
2024-06-18 16:08:41 +10:00
const hoverOverNothing = async ( ) = > {
// await u.canvasLocator.hover({position: {x: 700, y: 325}})
await page . mouse . move ( 700 , 325 )
await page . waitForTimeout ( 100 )
2024-07-02 17:16:27 +10:00
await expect ( page . getByTestId ( 'hover-highlight' ) ) . not . toBeVisible ( {
timeout : 10_000 ,
} )
2024-06-18 16:08:41 +10:00
}
2024-03-04 10:36:54 +11:00
2024-06-18 16:08:41 +10:00
await expect ( page . getByTestId ( 'hover-highlight' ) ) . not . toBeVisible ( )
2024-03-04 10:36:54 +11:00
2024-06-18 16:08:41 +10:00
await page . waitForTimeout ( 100 )
// hover over horizontal line
await u . canvasLocator . hover ( { position : { x : 800 , y } } )
2024-07-02 17:16:27 +10:00
await expect ( page . getByTestId ( 'hover-highlight' ) . first ( ) ) . toBeVisible ( {
timeout : 10_000 ,
} )
await page . waitForTimeout ( 200 )
2024-03-04 10:36:54 +11:00
2024-06-18 16:08:41 +10:00
await hoverOverNothing ( )
2024-07-02 17:16:27 +10:00
await page . waitForTimeout ( 200 )
2024-06-18 16:08:41 +10:00
// hover over vertical line
await u . canvasLocator . hover ( { position : { x , y : 325 } } )
2024-07-02 17:16:27 +10:00
await expect ( page . getByTestId ( 'hover-highlight' ) . first ( ) ) . toBeVisible ( {
timeout : 10_000 ,
} )
2024-03-04 10:36:54 +11:00
2024-06-18 16:08:41 +10:00
await hoverOverNothing ( )
// click exit sketch
await page . getByRole ( 'button' , { name : 'Exit Sketch' } ) . click ( )
await page . waitForTimeout ( 400 )
await hoverOverNothing ( )
2024-07-02 17:16:27 +10:00
await page . waitForTimeout ( 200 )
2024-06-18 16:08:41 +10:00
// hover over horizontal line
await page . mouse . move ( 858 , y , { steps : 5 } )
2024-07-02 17:16:27 +10:00
await expect ( page . getByTestId ( 'hover-highlight' ) . first ( ) ) . toBeVisible ( {
timeout : 10_000 ,
} )
2024-06-18 16:08:41 +10:00
await hoverOverNothing ( )
// hover over vertical line
await page . mouse . move ( x , 325 )
2024-07-02 17:16:27 +10:00
await expect ( page . getByTestId ( 'hover-highlight' ) . first ( ) ) . toBeVisible ( {
timeout : 10_000 ,
} )
2024-06-18 16:08:41 +10:00
await hoverOverNothing ( )
// hover over vertical line
await page . mouse . move ( 857 , y )
2024-07-02 17:16:27 +10:00
await expect ( page . getByTestId ( 'hover-highlight' ) . first ( ) ) . toBeVisible ( {
timeout : 10_000 ,
} )
2024-06-18 16:08:41 +10:00
// now click it
await page . mouse . click ( 857 , y )
await expect (
page . getByRole ( 'button' , { name : 'Edit Sketch' } )
) . toBeVisible ( )
await page . getByRole ( 'button' , { name : 'Edit Sketch' } ) . click ( )
await page . waitForTimeout ( 400 )
await hoverOverNothing ( )
x = 975
y = 468
await page . waitForTimeout ( 100 )
await page . mouse . move ( x , 419 , { steps : 5 } )
2024-07-02 17:16:27 +10:00
await expect ( page . getByTestId ( 'hover-highlight' ) . first ( ) ) . toBeVisible ( {
timeout : 10_000 ,
} )
2024-06-18 16:08:41 +10:00
await hoverOverNothing ( )
2024-03-04 10:36:54 +11:00
2024-06-18 16:08:41 +10:00
await page . mouse . move ( 855 , y )
2024-07-02 17:16:27 +10:00
await expect ( page . getByTestId ( 'hover-highlight' ) . first ( ) ) . toBeVisible ( {
timeout : 10_000 ,
} )
2024-06-18 16:08:41 +10:00
await hoverOverNothing ( )
await page . getByRole ( 'button' , { name : 'Exit Sketch' } ) . click ( )
2024-07-02 17:16:27 +10:00
await page . waitForTimeout ( 200 )
2024-06-18 16:08:41 +10:00
await hoverOverNothing ( )
2024-07-02 17:16:27 +10:00
await page . waitForTimeout ( 200 )
2024-06-18 16:08:41 +10:00
await page . mouse . move ( x , 419 )
2024-07-02 17:16:27 +10:00
await expect ( page . getByTestId ( 'hover-highlight' ) . first ( ) ) . toBeVisible ( {
timeout : 10_000 ,
} )
2024-06-18 16:08:41 +10:00
await hoverOverNothing ( )
await page . mouse . move ( 855 , y )
2024-07-02 17:16:27 +10:00
await expect ( page . getByTestId ( 'hover-highlight' ) . first ( ) ) . toBeVisible ( {
timeout : 10_000 ,
} )
2024-06-18 16:08:41 +10:00
} )
2024-03-04 10:36:54 +11:00
} )
2024-07-03 14:34:45 +10:00
test . describe ( 'Editor tests' , ( ) = > {
test ( 'if you click the format button it formats your code' , async ( {
page ,
} ) = > {
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1000 , height : 500 } )
2024-05-10 15:30:40 -07:00
2024-07-03 14:34:45 +10:00
await u . waitForAuthSkipAppStart ( )
2024-05-10 15:30:40 -07:00
2024-07-03 14:34:45 +10:00
// check no error to begin with
await expect ( page . locator ( '.cm-lint-marker-error' ) ) . not . toBeVisible ( )
2024-05-10 15:30:40 -07:00
2024-07-03 14:34:45 +10:00
await u . codeLocator . click ( )
await page . keyboard . type ( ` const sketch001 = startSketchOn('XY')
2024-05-10 15:30:40 -07:00
| > startProfileAt ( [ - 10 , - 10 ] , % )
| > line ( [ 20 , 0 ] , % )
| > line ( [ 0 , 20 ] , % )
| > line ( [ - 20 , 0 ] , % )
| > close ( % ) ` )
2024-07-03 14:34:45 +10:00
await page . locator ( '#code-pane button:first-child' ) . click ( )
await page . locator ( 'button:has-text("Format code")' ) . click ( )
2024-06-30 17:14:39 -07:00
2024-07-03 14:34:45 +10:00
await expect ( page . locator ( '.cm-content' ) )
. toHaveText ( ` const sketch001 = startSketchOn('XY')
| > startProfileAt ( [ - 10 , - 10 ] , % )
| > line ( [ 20 , 0 ] , % )
| > line ( [ 0 , 20 ] , % )
| > line ( [ - 20 , 0 ] , % )
| > close ( % ) ` )
2024-06-30 17:14:39 -07:00
} )
2024-07-03 14:34:45 +10:00
test ( 'fold gutters work' , async ( { page } ) = > {
const u = await getUtils ( page )
2024-06-30 17:14:39 -07:00
2024-07-03 14:34:45 +10:00
const fullCode = ` const sketch001 = startSketchOn('XY')
| > startProfileAt ( [ - 10 , - 10 ] , % )
| > line ( [ 20 , 0 ] , % )
| > line ( [ 0 , 20 ] , % )
| > line ( [ - 20 , 0 ] , % )
| > close ( % ) `
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const sketch001 = startSketchOn('XY')
| > startProfileAt ( [ - 10 , - 10 ] , % )
| > line ( [ 20 , 0 ] , % )
| > line ( [ 0 , 20 ] , % )
| > line ( [ - 20 , 0 ] , % )
| > close ( % ) `
)
} )
await page . setViewportSize ( { width : 1000 , height : 500 } )
2024-06-30 17:14:39 -07:00
2024-07-03 14:34:45 +10:00
await u . waitForAuthSkipAppStart ( )
2024-06-29 18:10:07 -07:00
2024-07-03 14:34:45 +10:00
// TODO: Jess needs to fix this but you have to mod the code to get them to show
// up, its an annoying codemirror thing.
await page . locator ( '.cm-content' ) . click ( )
2024-07-03 21:28:51 -07:00
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' )
2024-07-03 14:34:45 +10:00
await page . keyboard . press ( 'Enter' )
2024-06-22 15:50:16 -07:00
2024-07-03 14:34:45 +10:00
const foldGutterFoldLine = page . locator ( '[title="Fold line"]' )
const foldGutterUnfoldLine = page . locator ( '[title="Unfold line"]' )
2024-06-22 15:50:16 -07:00
2024-07-03 14:34:45 +10:00
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( fullCode )
2024-06-22 15:50:16 -07:00
2024-07-03 14:34:45 +10:00
// check no error to begin with
await expect ( page . locator ( '.cm-lint-marker-error' ) ) . not . toBeVisible ( )
2024-06-22 15:50:16 -07:00
2024-07-03 14:34:45 +10:00
// Make sure we have a fold gutter
await expect ( foldGutterFoldLine ) . toBeVisible ( )
await expect ( foldGutterUnfoldLine ) . not . toBeVisible ( )
2024-06-22 15:50:16 -07:00
2024-07-03 14:34:45 +10:00
// Collapse the code
await foldGutterFoldLine . click ( )
2024-06-22 15:50:16 -07:00
2024-07-03 14:34:45 +10:00
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
` const sketch001 = startSketchOn('XY')… `
2024-05-10 16:51:54 -07:00
)
2024-07-03 14:34:45 +10:00
await expect ( page . locator ( '.cm-content' ) ) . not . toHaveText ( fullCode )
await expect ( foldGutterFoldLine ) . not . toBeVisible ( )
await expect ( foldGutterUnfoldLine . nth ( 1 ) ) . toBeVisible ( )
2024-05-10 15:30:40 -07:00
2024-07-03 14:34:45 +10:00
// Expand the code
await foldGutterUnfoldLine . nth ( 1 ) . click ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( fullCode )
2024-05-10 15:30:40 -07:00
2024-07-03 14:34:45 +10:00
// Delete all the code.
await page . locator ( '.cm-content' ) . click ( )
// Select all
await page . keyboard . press ( 'Control+A' )
await page . keyboard . press ( 'Backspace' )
await page . keyboard . press ( 'Meta+A' )
await page . keyboard . press ( 'Backspace' )
2024-05-10 15:30:40 -07:00
2024-07-03 14:34:45 +10:00
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( ` ` )
await expect ( page . locator ( '.cm-content' ) ) . not . toHaveText ( fullCode )
2024-05-10 15:30:40 -07:00
2024-07-03 14:34:45 +10:00
await expect ( foldGutterUnfoldLine ) . not . toBeVisible ( )
await expect ( foldGutterFoldLine ) . not . toBeVisible ( )
} )
2024-05-10 15:30:40 -07:00
2024-07-03 14:34:45 +10:00
test ( 'hover over functions shows function description' , async ( { page } ) = > {
const u = await getUtils ( page )
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const sketch001 = startSketchOn('XY')
2024-05-10 15:30:40 -07:00
| > startProfileAt ( [ - 10 , - 10 ] , % )
| > line ( [ 20 , 0 ] , % )
| > line ( [ 0 , 20 ] , % )
| > line ( [ - 20 , 0 ] , % )
2024-07-03 14:34:45 +10:00
| > close ( % ) `
)
} )
await page . setViewportSize ( { width : 1000 , height : 500 } )
2024-05-10 15:30:40 -07:00
2024-07-03 14:34:45 +10:00
await u . waitForAuthSkipAppStart ( )
2024-05-20 14:59:59 -04:00
2024-07-03 14:34:45 +10:00
// check no error to begin with
await expect ( page . locator ( '.cm-lint-marker-error' ) ) . not . toBeVisible ( )
2024-05-20 14:59:59 -04:00
2024-07-03 14:34:45 +10:00
await u . openDebugPanel ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await u . closeDebugPanel ( )
2024-06-11 17:05:25 -07:00
2024-07-03 14:34:45 +10:00
// focus the editor
await u . codeLocator . click ( )
2024-06-11 17:05:25 -07:00
2024-07-03 14:34:45 +10:00
// Hover over the startSketchOn function
await page . getByText ( 'startSketchOn' ) . hover ( )
await expect ( page . locator ( '.hover-tooltip' ) ) . toBeVisible ( )
await expect (
page . getByText ( 'Start a sketch on a specific plane or face' )
) . toBeVisible ( )
2024-06-11 17:05:25 -07:00
2024-07-03 14:34:45 +10:00
// Hover over the line function
await page . getByText ( 'line' ) . first ( ) . hover ( )
await expect ( page . locator ( '.hover-tooltip' ) ) . toBeVisible ( )
await expect ( page . getByText ( 'Draw a line' ) ) . toBeVisible ( )
} )
2024-06-11 17:05:25 -07:00
2024-07-03 14:34:45 +10:00
test ( 'if you use the format keyboard binding it formats your code' , async ( {
page ,
} ) = > {
const u = await getUtils ( page )
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const sketch001 = startSketchOn('XY')
| > startProfileAt ( [ - 10 , - 10 ] , % )
| > line ( [ 20 , 0 ] , % )
| > line ( [ 0 , 20 ] , % )
| > line ( [ - 20 , 0 ] , % )
| > close ( % ) `
)
localStorage . setItem ( 'disableAxis' , 'true' )
} )
await page . setViewportSize ( { width : 1000 , height : 500 } )
2024-06-11 17:05:25 -07:00
2024-07-03 14:34:45 +10:00
await u . waitForAuthSkipAppStart ( )
2024-06-11 17:05:25 -07:00
2024-07-03 14:34:45 +10:00
// check no error to begin with
await expect ( page . locator ( '.cm-lint-marker-error' ) ) . not . toBeVisible ( )
2024-06-11 17:05:25 -07:00
2024-07-03 14:34:45 +10:00
await u . openDebugPanel ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await u . closeDebugPanel ( )
2024-06-11 17:05:25 -07:00
2024-07-03 14:34:45 +10:00
// focus the editor
await u . codeLocator . click ( )
2024-06-11 17:05:25 -07:00
2024-07-03 14:34:45 +10:00
// Hit alt+shift+f to format the code
await page . keyboard . press ( 'Alt+Shift+KeyF' )
2024-06-19 16:15:22 -04:00
2024-07-03 14:34:45 +10:00
await expect ( page . locator ( '.cm-content' ) )
. toHaveText ( ` const sketch001 = startSketchOn('XY')
| > startProfileAt ( [ - 10 , - 10 ] , % )
| > line ( [ 20 , 0 ] , % )
| > line ( [ 0 , 20 ] , % )
| > line ( [ - 20 , 0 ] , % )
| > close ( % ) ` )
} )
2024-06-19 16:15:22 -04:00
2024-07-03 14:34:45 +10:00
test ( 'if you write kcl with lint errors you get lints' , async ( { page } ) = > {
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1000 , height : 500 } )
2024-06-19 16:15:22 -04:00
2024-07-03 14:34:45 +10:00
await u . waitForAuthSkipAppStart ( )
2024-06-19 16:15:22 -04:00
2024-07-03 14:34:45 +10:00
// check no error to begin with
await expect ( page . locator ( '.cm-lint-marker-info' ) ) . not . toBeVisible ( )
2024-06-19 16:15:22 -04:00
2024-07-03 14:34:45 +10:00
await u . codeLocator . click ( )
await page . keyboard . type ( 'const my_snake_case_var = 5' )
await page . keyboard . press ( 'Enter' )
await page . keyboard . type ( 'const myCamelCaseVar = 5' )
await page . keyboard . press ( 'Enter' )
2024-06-19 16:15:22 -04:00
2024-07-03 14:34:45 +10:00
// press arrows to clear autocomplete
await page . keyboard . press ( 'ArrowLeft' )
await page . keyboard . press ( 'ArrowRight' )
2024-06-19 16:15:22 -04:00
2024-07-03 14:34:45 +10:00
// error in guter
2024-07-03 19:28:46 -07:00
await expect ( page . locator ( '.cm-lint-marker-info' ) . first ( ) ) . toBeVisible ( )
2024-06-19 16:15:22 -04:00
2024-07-03 14:34:45 +10:00
// error text on hover
await page . hover ( '.cm-lint-marker-info' )
await expect (
2024-07-03 19:28:46 -07:00
page . getByText ( 'Identifiers must be lowerCamelCase' ) . first ( )
2024-07-03 14:34:45 +10:00
) . toBeVisible ( )
2023-11-24 08:59:24 +11:00
2024-07-03 14:34:45 +10:00
// select the line that's causing the error and delete it
await page . getByText ( 'const my_snake_case_var = 5' ) . click ( )
await page . keyboard . press ( 'End' )
await page . keyboard . down ( 'Shift' )
await page . keyboard . press ( 'Home' )
await page . keyboard . up ( 'Shift' )
await page . keyboard . press ( 'Backspace' )
2023-11-24 08:59:24 +11:00
2024-07-03 14:34:45 +10:00
// wait for .cm-lint-marker-info not to be visible
await expect ( page . locator ( '.cm-lint-marker-info' ) ) . not . toBeVisible ( )
} )
2023-11-24 08:59:24 +11:00
2024-07-03 14:34:45 +10:00
test ( 'if you fixup kcl errors you clear lints' , async ( { page } ) = > {
const u = await getUtils ( page )
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( [ 3.29 , 7.86 ] , % )
| > line ( [ 2.48 , 2.44 ] , % )
| > line ( [ 2.66 , 1.17 ] , % )
| > close ( % )
`
)
} )
2023-11-28 21:23:20 +11:00
2024-07-03 14:34:45 +10:00
await page . setViewportSize ( { width : 1000 , height : 500 } )
2023-11-28 21:23:20 +11:00
2024-07-03 14:34:45 +10:00
await u . waitForAuthSkipAppStart ( )
2023-11-24 08:59:24 +11:00
2024-07-03 14:34:45 +10:00
// check no error to begin with
await expect ( page . locator ( '.cm-lint-marker-error' ) ) . not . toBeVisible ( )
2023-11-24 08:59:24 +11:00
2024-07-03 14:34:45 +10:00
await u . codeLocator . click ( )
2023-11-24 08:59:24 +11:00
2024-07-03 14:34:45 +10:00
await page . getByText ( ' |> line([2.48, 2.44], %)' ) . click ( )
2023-11-24 08:59:24 +11:00
2024-07-03 14:34:45 +10:00
await expect (
page . locator ( '.cm-lint-marker-error' ) . first ( )
) . not . toBeVisible ( )
await page . keyboard . press ( 'End' )
await page . keyboard . press ( 'Backspace' )
2023-12-05 06:34:23 +11:00
2024-07-03 14:34:45 +10:00
await expect ( page . locator ( '.cm-lint-marker-error' ) . first ( ) ) . toBeVisible ( )
await page . keyboard . type ( ')' )
await expect (
page . locator ( '.cm-lint-marker-error' ) . first ( )
) . not . toBeVisible ( )
} )
2023-12-05 06:34:23 +11:00
2024-07-03 14:34:45 +10:00
test ( 'if you write invalid kcl you get inlined errors' , async ( { page } ) = > {
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1000 , height : 500 } )
2023-12-05 06:34:23 +11:00
2024-07-03 14:34:45 +10:00
await u . waitForAuthSkipAppStart ( )
2023-12-05 06:34:23 +11:00
2024-07-03 14:34:45 +10:00
// check no error to begin with
await expect ( page . locator ( '.cm-lint-marker-error' ) ) . not . toBeVisible ( )
2023-12-05 06:34:23 +11:00
2024-07-03 14:34:45 +10:00
/ * a d d t h e f o l l o w i n g c o d e t o t h e e d i t o r ( $ e r r o r i s n o t a v a l i d l i n e )
$ error
const topAng = 30
const bottomAng = 25
* /
await u . codeLocator . click ( )
await page . keyboard . type ( '$ error' )
2023-11-24 08:59:24 +11:00
2024-07-03 14:34:45 +10:00
// press arrows to clear autocomplete
await page . keyboard . press ( 'ArrowLeft' )
await page . keyboard . press ( 'ArrowRight' )
2024-06-29 18:10:07 -07:00
2024-07-03 14:34:45 +10:00
await page . keyboard . press ( 'Enter' )
await page . keyboard . type ( 'const topAng = 30' )
await page . keyboard . press ( 'Enter' )
await page . keyboard . type ( 'const bottomAng = 25' )
await page . keyboard . press ( 'Enter' )
2024-05-21 00:49:57 -07:00
2024-07-03 14:34:45 +10:00
// error in guter
await expect ( page . locator ( '.cm-lint-marker-error' ) ) . toBeVisible ( )
2024-05-21 00:49:57 -07:00
2024-07-03 14:34:45 +10:00
// error text on hover
await page . hover ( '.cm-lint-marker-error' )
await expect ( page . getByText ( 'Unexpected token' ) . first ( ) ) . toBeVisible ( )
2024-05-21 00:49:57 -07:00
2024-07-03 14:34:45 +10:00
// select the line that's causing the error and delete it
await page . getByText ( '$ error' ) . click ( )
await page . keyboard . press ( 'End' )
await page . keyboard . down ( 'Shift' )
await page . keyboard . press ( 'Home' )
await page . keyboard . up ( 'Shift' )
await page . keyboard . press ( 'Backspace' )
2024-04-17 09:11:35 -07:00
2024-07-03 14:34:45 +10:00
// wait for .cm-lint-marker-error not to be visible
await expect ( page . locator ( '.cm-lint-marker-error' ) ) . not . toBeVisible ( )
2024-04-17 09:11:35 -07:00
2024-07-03 14:34:45 +10:00
// let's check we get an error when defining the same variable twice
await page . getByText ( 'const bottomAng = 25' ) . click ( )
await page . keyboard . press ( 'Enter' )
await page . keyboard . type ( "// Let's define the same thing twice" )
await page . keyboard . press ( 'Enter' )
await page . keyboard . type ( 'const topAng = 42' )
await page . keyboard . press ( 'ArrowLeft' )
2024-04-17 09:11:35 -07:00
2024-07-03 14:34:45 +10:00
await expect ( page . locator ( '.cm-lint-marker-error' ) ) . toBeVisible ( )
2024-07-03 19:28:46 -07:00
await expect (
page . locator ( '.cm-lintRange.cm-lintRange-error' ) . first ( )
) . toBeVisible ( )
2024-04-17 09:11:35 -07:00
2024-07-03 14:34:45 +10:00
await page . locator ( '.cm-lintRange.cm-lintRange-error' ) . hover ( )
2024-07-03 19:28:46 -07:00
await expect ( page . locator ( '.cm-diagnosticText' ) . first ( ) ) . toBeVisible ( )
await expect (
page . getByText ( 'Cannot redefine `topAng`' ) . first ( )
) . toBeVisible ( )
2024-04-17 09:11:35 -07:00
2024-07-03 19:28:46 -07:00
const secondTopAng = page . getByText ( 'topAng' ) . first ( )
2024-07-03 14:34:45 +10:00
await secondTopAng ? . dblclick ( )
await page . keyboard . type ( 'otherAng' )
2024-04-17 09:11:35 -07:00
2024-07-03 14:34:45 +10:00
await expect ( page . locator ( '.cm-lint-marker-error' ) ) . not . toBeVisible ( )
2023-11-24 08:59:24 +11:00
} )
2024-06-29 18:10:07 -07:00
2024-07-03 14:34:45 +10:00
test ( 'error with 2 source ranges gets 2 diagnostics' , async ( { page } ) = > {
const u = await getUtils ( page )
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const length = .750
const width = 0.500
const height = 0.500
const dia = 4
fn squareHole = ( l , w ) = > {
const squareHoleSketch = startSketchOn ( 'XY' )
| > startProfileAt ( [ - width / 2 , - length / 2 ] , % )
| > lineTo ( [ width / 2 , - length / 2 ] , % )
| > lineTo ( [ width / 2 , length / 2 ] , % )
| > lineTo ( [ - width / 2 , length / 2 ] , % )
| > close ( % )
return squareHoleSketch
}
`
)
} )
await page . setViewportSize ( { width : 1000 , height : 500 } )
2023-11-24 08:59:24 +11:00
2024-07-03 14:34:45 +10:00
await u . waitForAuthSkipAppStart ( )
2023-11-24 08:59:24 +11:00
2024-07-03 14:34:45 +10:00
await u . openDebugPanel ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await u . closeDebugPanel ( )
2024-06-29 18:10:07 -07:00
2024-07-03 14:34:45 +10:00
// check no error to begin with
await expect ( page . locator ( '.cm-lint-marker-error' ) ) . not . toBeVisible ( )
2023-11-24 08:59:24 +11:00
2024-07-03 14:34:45 +10:00
// Click on the bottom of the code editor to add a new line
await u . codeLocator . click ( )
await page . keyboard . press ( 'ArrowDown' )
await page . keyboard . press ( 'ArrowDown' )
await page . keyboard . press ( 'ArrowDown' )
await page . keyboard . press ( 'ArrowDown' )
await page . keyboard . press ( 'ArrowDown' )
await page . keyboard . press ( 'ArrowDown' )
await page . keyboard . press ( 'ArrowDown' )
await page . keyboard . press ( 'ArrowDown' )
await page . keyboard . press ( 'ArrowDown' )
await page . keyboard . press ( 'ArrowDown' )
await page . keyboard . press ( 'ArrowDown' )
await page . keyboard . press ( 'ArrowDown' )
await page . keyboard . press ( 'ArrowDown' )
await page . keyboard . press ( 'Enter' )
await page . keyboard . type ( ` const extrusion = startSketchOn('XY')
| > circle ( [ 0 , 0 ] , dia / 2 , % )
| > hole ( squareHole ( length , width , height ) , % )
| > extrude ( height , % ) ` )
// error in gutter
await expect ( page . locator ( '.cm-lint-marker-error' ) . first ( ) ) . toBeVisible ( )
await page . hover ( '.cm-lint-marker-error:first-child' )
2024-07-03 19:28:46 -07:00
await expect (
page . getByText ( 'Expected 2 arguments, got 3' ) . first ( )
) . toBeVisible ( )
2024-07-03 14:34:45 +10:00
// Make sure there are two diagnostics
await expect ( page . locator ( '.cm-lint-marker-error' ) ) . toHaveCount ( 2 )
} )
test ( 'if your kcl gets an error from the engine it is inlined' , async ( {
page ,
} ) = > {
const u = await getUtils ( page )
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const box = startSketchOn('XY')
| > startProfileAt ( [ 0 , 0 ] , % )
| > line ( [ 0 , 10 ] , % )
| > line ( [ 10 , 0 ] , % )
| > line ( [ 0 , - 10 ] , % , 'revolveAxis' )
| > close ( % )
| > extrude ( 10 , % )
const sketch001 = startSketchOn ( box , "revolveAxis" )
| > startProfileAt ( [ 5 , 10 ] , % )
| > line ( [ 0 , - 10 ] , % )
| > line ( [ 2 , 0 ] , % )
| > line ( [ 0 , - 10 ] , % )
| > close ( % )
| > revolve ( {
axis : getEdge ( 'revolveAxis' , box ) ,
angle : 90
} , % )
`
)
} )
2023-11-24 08:59:24 +11:00
2024-07-03 14:34:45 +10:00
await page . setViewportSize ( { width : 1000 , height : 500 } )
2023-11-24 08:59:24 +11:00
2024-07-05 05:42:54 +10:00
await page . goto ( '/' )
await u . waitForPageLoad ( )
2024-04-18 15:16:08 -07:00
2024-07-03 14:34:45 +10:00
await expect ( page . locator ( '.cm-lint-marker-error' ) ) . toBeVisible ( )
2024-04-18 15:16:08 -07:00
2024-07-03 14:34:45 +10:00
// error text on hover
await page . hover ( '.cm-lint-marker-error' )
2024-07-05 05:42:54 +10:00
const searchText =
'sketch profile must lie entirely on one side of the revolution axis'
await expect ( page . getByText ( searchText ) . first ( ) ) . toBeVisible ( )
2023-11-24 08:59:24 +11:00
} )
2024-07-03 14:34:45 +10:00
test . describe ( 'Autocomplete works' , ( ) = > {
test ( 'with enter/click to accept the completion' , async ( { page } ) = > {
const u = await getUtils ( page )
// const PUR = 400 / 37.5 //pixeltoUnitRatio
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-04-18 15:16:08 -07:00
2024-07-03 14:34:45 +10:00
await u . waitForAuthSkipAppStart ( )
2024-04-18 15:16:08 -07:00
2024-07-03 14:34:45 +10:00
// this test might be brittle as we add and remove functions
// but should also be easy to update.
// tests clicking on an option, selection the first option
// and arrowing down to an option
await u . codeLocator . click ( )
await page . keyboard . type ( 'const sketch001 = start' )
// expect there to be six auto complete options
await expect ( page . locator ( '.cm-completionLabel' ) ) . toHaveCount ( 6 )
// this makes sure we can accept a completion with click
await page . getByText ( 'startSketchOn' ) . click ( )
await page . keyboard . type ( "'XZ'" )
await page . keyboard . press ( 'Tab' )
await page . keyboard . press ( 'Enter' )
await page . keyboard . type ( ' |> startProfi' )
// expect there be a single auto complete option that we can just hit enter on
await expect ( page . locator ( '.cm-completionLabel' ) ) . toBeVisible ( )
await page . waitForTimeout ( 100 )
await page . keyboard . press ( 'Enter' ) // accepting the auto complete, not a new line
2024-04-18 15:16:08 -07:00
2024-07-03 14:34:45 +10:00
await page . keyboard . press ( 'Tab' )
await page . waitForTimeout ( 100 )
await page . keyboard . type ( '12' )
await page . waitForTimeout ( 100 )
await page . keyboard . press ( 'Tab' )
await page . waitForTimeout ( 100 )
await page . keyboard . press ( 'Tab' )
await page . waitForTimeout ( 100 )
await page . keyboard . press ( 'Tab' )
await page . waitForTimeout ( 100 )
await page . keyboard . press ( 'Enter' )
await page . waitForTimeout ( 100 )
await page . keyboard . type ( ' |> lin' )
2024-04-18 15:16:08 -07:00
2024-07-03 14:34:45 +10:00
await expect ( page . locator ( '.cm-tooltip-autocomplete' ) ) . toBeVisible ( )
await page . waitForTimeout ( 100 )
// press arrow down twice then enter to accept xLine
await page . keyboard . press ( 'ArrowDown' )
await page . keyboard . press ( 'ArrowDown' )
await page . keyboard . press ( 'Enter' )
// finish line with comment
await page . keyboard . type ( '5' )
await page . waitForTimeout ( 100 )
await page . keyboard . press ( 'Tab' )
await page . waitForTimeout ( 100 )
await page . keyboard . press ( 'Tab' )
2023-11-24 08:59:24 +11:00
2024-07-03 14:34:45 +10:00
await page . keyboard . type ( ' // ' )
// Since we need to parse the ast to know we are in a comment we gotta hang tight.
await page . waitForTimeout ( 700 )
await page . keyboard . type ( 'lin ' )
await page . waitForTimeout ( 200 )
// there shouldn't be any auto complete options for 'lin' in the comment
await expect ( page . locator ( '.cm-completionLabel' ) ) . not . toBeVisible ( )
2024-06-21 15:06:01 -07:00
2024-07-03 14:34:45 +10:00
await expect ( page . locator ( '.cm-content' ) )
. toHaveText ( ` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( [ 3.14 , 12 ] , % )
| > xLine ( 5 , % ) // lin`)
} )
2024-06-29 18:10:07 -07:00
2024-07-03 14:34:45 +10:00
test ( 'with tab to accept the completion' , async ( { page } ) = > {
const u = await getUtils ( page )
// const PUR = 400 / 37.5 //pixeltoUnitRatio
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-21 15:06:01 -07:00
2024-07-03 14:34:45 +10:00
await u . waitForAuthSkipAppStart ( )
2024-06-21 15:06:01 -07:00
2024-07-03 14:34:45 +10:00
// this test might be brittle as we add and remove functions
// but should also be easy to update.
// tests clicking on an option, selection the first option
// and arrowing down to an option
2024-06-21 15:06:01 -07:00
2024-07-03 14:34:45 +10:00
await u . codeLocator . click ( )
await page . keyboard . type ( 'const sketch001 = startSketchO' )
await page . waitForTimeout ( 100 )
2024-06-21 15:06:01 -07:00
2024-07-03 14:34:45 +10:00
// Make sure just hitting tab will take the only one left
await expect ( page . locator ( '.cm-completionLabel' ) ) . toHaveCount ( 1 )
await page . waitForTimeout ( 500 )
await page . keyboard . press ( 'ArrowDown' )
await page . keyboard . press ( 'Tab' )
await page . waitForTimeout ( 500 )
await page . keyboard . type ( "'XZ'" )
await page . keyboard . press ( 'Tab' )
await page . keyboard . press ( 'Enter' )
await page . keyboard . type ( ' |> startProfi' )
// expect there be a single auto complete option that we can just hit enter on
await expect ( page . locator ( '.cm-completionLabel' ) ) . toBeVisible ( )
await page . waitForTimeout ( 100 )
await page . keyboard . press ( 'Tab' ) // accepting the auto complete, not a new line
2024-06-30 18:26:16 -07:00
2024-07-03 14:34:45 +10:00
await page . keyboard . press ( 'Tab' )
await page . keyboard . type ( '12' )
await page . waitForTimeout ( 100 )
await page . keyboard . press ( 'Tab' )
await page . waitForTimeout ( 100 )
await page . keyboard . press ( 'Tab' )
await page . waitForTimeout ( 100 )
await page . keyboard . press ( 'Tab' )
await page . waitForTimeout ( 100 )
await page . keyboard . press ( 'Enter' )
await page . waitForTimeout ( 100 )
await page . keyboard . type ( ' |> lin' )
2024-06-30 18:26:16 -07:00
2024-07-03 14:34:45 +10:00
await expect ( page . locator ( '.cm-tooltip-autocomplete' ) ) . toBeVisible ( )
await page . waitForTimeout ( 100 )
// press arrow down twice then tab to accept xLine
await page . keyboard . press ( 'ArrowDown' )
await page . keyboard . press ( 'ArrowDown' )
await page . keyboard . press ( 'Tab' )
// finish line with comment
await page . keyboard . type ( '5' )
await page . waitForTimeout ( 100 )
await page . keyboard . press ( 'Tab' )
await page . waitForTimeout ( 100 )
await page . keyboard . press ( 'Tab' )
2024-06-30 18:26:16 -07:00
2024-07-03 14:34:45 +10:00
await page . keyboard . type ( ' // ' )
// Since we need to parse the ast to know we are in a comment we gotta hang tight.
await page . waitForTimeout ( 700 )
await page . keyboard . type ( 'lin ' )
await page . waitForTimeout ( 200 )
// there shouldn't be any auto complete options for 'lin' in the comment
await expect ( page . locator ( '.cm-completionLabel' ) ) . not . toBeVisible ( )
2024-06-30 18:26:16 -07:00
2024-07-03 14:34:45 +10:00
await expect ( page . locator ( '.cm-content' ) )
. toHaveText ( ` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( [ 3.14 , 12 ] , % )
| > xLine ( 5 , % ) // lin`)
} )
} )
test ( 'Can undo a click and point extrude with ctrl+z' , async ( { page } ) = > {
2024-06-30 18:26:16 -07:00
const u = await getUtils ( page )
2024-07-03 14:34:45 +10:00
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( [ 4.61 , - 14.01 ] , % )
| > line ( [ 12.73 , - 0.09 ] , % )
| > tangentialArcTo ( [ 24.95 , - 5.38 ] , % )
| > close ( % ) `
)
} )
2024-06-30 18:26:16 -07:00
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
2024-07-03 14:34:45 +10:00
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . not . toBeDisabled ( )
2024-06-30 18:26:16 -07:00
2024-07-03 14:34:45 +10:00
await page . waitForTimeout ( 100 )
await u . openAndClearDebugPanel ( )
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_look_at' ,
vantage : { x : 0 , y : - 1250 , z : 580 } ,
center : { x : 0 , y : 0 , z : 0 } ,
up : { x : 0 , y : 0 , z : 1 } ,
} ,
} )
await page . waitForTimeout ( 100 )
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_get_settings' ,
} ,
} )
await page . waitForTimeout ( 100 )
2024-06-30 18:26:16 -07:00
2024-07-03 14:34:45 +10:00
const startPX = [ 665 , 458 ]
2024-06-30 18:26:16 -07:00
2024-07-03 14:34:45 +10:00
const dragPX = 40
await page . getByText ( 'startProfileAt([4.61, -14.01], %)' ) . click ( )
await expect ( page . getByRole ( 'button' , { name : 'Extrude' } ) ) . toBeVisible ( )
await page . getByRole ( 'button' , { name : 'Extrude' } ) . click ( )
await expect ( page . getByTestId ( 'command-bar' ) ) . toBeVisible ( )
await page . waitForTimeout ( 100 )
2024-06-30 18:26:16 -07:00
await page . keyboard . press ( 'Enter' )
2024-07-03 14:34:45 +10:00
await page . waitForTimeout ( 100 )
await expect ( page . getByText ( 'Confirm Extrude' ) ) . toBeVisible ( )
2024-06-30 18:26:16 -07:00
await page . keyboard . press ( 'Enter' )
2024-07-03 14:34:45 +10:00
await page . waitForTimeout ( 100 )
2024-06-30 18:26:16 -07:00
2024-07-03 14:34:45 +10:00
// expect the code to have changed
2024-06-30 18:26:16 -07:00
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
2024-07-03 14:34:45 +10:00
` const sketch001 = startSketchOn('XZ') |> startProfileAt([4.61, -14.01], %) |> line([12.73, -0.09], %) |> tangentialArcTo([24.95, -5.38], %) |> close(%)const extrude001 = extrude(5, sketch001) `
2024-07-01 21:05:31 -07:00
)
2024-07-03 14:34:45 +10:00
// Now hit undo
await page . keyboard . down ( 'Control' )
await page . keyboard . press ( 'KeyZ' )
await page . keyboard . up ( 'Control' )
await page . waitForTimeout ( 100 )
await expect ( page . locator ( '.cm-content' ) )
. toHaveText ( ` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( [ 4.61 , - 14.01 ] , % )
| > line ( [ 12.73 , - 0.09 ] , % )
| > tangentialArcTo ( [ 24.95 , - 5.38 ] , % )
| > close ( % ) ` )
2024-07-01 21:05:31 -07:00
} )
2024-07-03 14:34:45 +10:00
test ( 'Can undo a sketch modification with ctrl+z' , async ( { page } ) = > {
2024-07-01 21:05:31 -07:00
const u = await getUtils ( page )
2024-07-03 14:34:45 +10:00
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( [ 4.61 , - 14.01 ] , % )
| > line ( [ 12.73 , - 0.09 ] , % )
| > tangentialArcTo ( [ 24.95 , - 5.38 ] , % )
| > close ( % )
| > extrude ( 5 , % ) `
)
} )
2024-07-01 21:05:31 -07:00
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
2024-07-03 14:34:45 +10:00
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . not . toBeDisabled ( )
2024-07-01 21:05:31 -07:00
2024-07-03 14:34:45 +10:00
await page . waitForTimeout ( 100 )
await u . openAndClearDebugPanel ( )
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_look_at' ,
vantage : { x : 0 , y : - 1250 , z : 580 } ,
center : { x : 0 , y : 0 , z : 0 } ,
up : { x : 0 , y : 0 , z : 1 } ,
} ,
} )
await page . waitForTimeout ( 100 )
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_get_settings' ,
} ,
} )
await page . waitForTimeout ( 100 )
2024-07-01 21:05:31 -07:00
2024-07-03 14:34:45 +10:00
const startPX = [ 665 , 458 ]
2024-07-01 21:05:31 -07:00
2024-07-03 14:34:45 +10:00
const dragPX = 40
await page . getByText ( 'startProfileAt([4.61, -14.01], %)' ) . click ( )
await expect (
page . getByRole ( 'button' , { name : 'Edit Sketch' } )
) . toBeVisible ( )
await page . getByRole ( 'button' , { name : 'Edit Sketch' } ) . click ( )
await page . waitForTimeout ( 400 )
let prevContent = await page . locator ( '.cm-content' ) . innerText ( )
await expect ( page . getByTestId ( 'segment-overlay' ) ) . toHaveCount ( 2 )
// drag startProfieAt handle
await page . dragAndDrop ( '#stream' , '#stream' , {
sourcePosition : { x : startPX [ 0 ] , y : startPX [ 1 ] } ,
targetPosition : { x : startPX [ 0 ] + dragPX , y : startPX [ 1 ] + dragPX } ,
} )
await page . waitForTimeout ( 100 )
await expect ( page . locator ( '.cm-content' ) ) . not . toHaveText ( prevContent )
prevContent = await page . locator ( '.cm-content' ) . innerText ( )
// drag line handle
// we wait so it saves the code
await page . waitForTimeout ( 800 )
const lineEnd = await u . getBoundingBox ( '[data-overlay-index="0"]' )
await page . waitForTimeout ( 100 )
await page . dragAndDrop ( '#stream' , '#stream' , {
sourcePosition : { x : lineEnd.x - 5 , y : lineEnd.y } ,
targetPosition : { x : lineEnd.x + dragPX , y : lineEnd.y + dragPX } ,
} )
await expect ( page . locator ( '.cm-content' ) ) . not . toHaveText ( prevContent )
prevContent = await page . locator ( '.cm-content' ) . innerText ( )
// we wait so it saves the code
await page . waitForTimeout ( 800 )
// drag tangentialArcTo handle
const tangentEnd = await u . getBoundingBox ( '[data-overlay-index="1"]' )
await page . dragAndDrop ( '#stream' , '#stream' , {
sourcePosition : { x : tangentEnd.x , y : tangentEnd.y - 5 } ,
targetPosition : {
x : tangentEnd.x + dragPX ,
y : tangentEnd.y + dragPX ,
} ,
} )
await page . waitForTimeout ( 100 )
await expect ( page . locator ( '.cm-content' ) ) . not . toHaveText ( prevContent )
// expect the code to have changed
await expect ( page . locator ( '.cm-content' ) )
. toHaveText ( ` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( [ 7.12 , - 16.82 ] , % )
| > line ( [ 15.4 , - 2.74 ] , % )
| > tangentialArcTo ( [ 24.95 , - 5.38 ] , % )
| > line ( [ 2.65 , - 2.69 ] , % )
| > close ( % )
| > extrude ( 5 , % ) ` )
// Hit undo
await page . keyboard . down ( 'Control' )
await page . keyboard . press ( 'KeyZ' )
await page . keyboard . up ( 'Control' )
await expect ( page . locator ( '.cm-content' ) )
. toHaveText ( ` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( [ 7.12 , - 16.82 ] , % )
| > line ( [ 15.4 , - 2.74 ] , % )
| > tangentialArcTo ( [ 24.95 , - 5.38 ] , % )
| > close ( % )
| > extrude ( 5 , % ) ` )
// Hit undo again.
await page . keyboard . down ( 'Control' )
await page . keyboard . press ( 'KeyZ' )
await page . keyboard . up ( 'Control' )
await expect ( page . locator ( '.cm-content' ) )
. toHaveText ( ` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( [ 7.12 , - 16.82 ] , % )
| > line ( [ 12.73 , - 0.09 ] , % )
| > tangentialArcTo ( [ 24.95 , - 5.38 ] , % )
| > close ( % )
| > extrude ( 5 , % ) ` )
// Hit undo again.
await page . keyboard . down ( 'Control' )
await page . keyboard . press ( 'KeyZ' )
await page . keyboard . up ( 'Control' )
await page . waitForTimeout ( 100 )
await expect ( page . locator ( '.cm-content' ) )
. toHaveText ( ` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( [ 4.61 , - 14.01 ] , % )
| > line ( [ 12.73 , - 0.09 ] , % )
| > tangentialArcTo ( [ 24.95 , - 5.38 ] , % )
| > close ( % )
| > extrude ( 5 , % ) ` )
} )
} )
test . describe ( 'Can create sketches on all planes and their back sides' , ( ) = > {
const sketchOnPlaneAndBackSideTest = async (
page : any ,
plane : string ,
clickCoords : { x : number ; y : number }
) = > {
const u = await getUtils ( page )
const PUR = 400 / 37.5 //pixeltoUnitRatio
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
await u . openDebugPanel ( )
const coord =
plane === '-XY' || plane === '-YZ' || plane === 'XZ' ? - 100 : 100
const camCommand : EngineCommand = {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_look_at' ,
center : { x : 0 , y : 0 , z : 0 } ,
vantage : { x : coord , y : coord , z : coord } ,
up : { x : 0 , y : 0 , z : 1 } ,
} ,
}
const updateCamCommand : EngineCommand = {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_get_settings' ,
} ,
}
const code = ` const sketch001 = startSketchOn(' ${ plane } ')
| > startProfileAt ( [ 0.9 , - 1.22 ] , % ) `
await u . openDebugPanel ( )
await u . clearCommandLogs ( )
await page . getByRole ( 'button' , { name : 'Start Sketch' } ) . click ( )
await u . sendCustomCmd ( camCommand )
await page . waitForTimeout ( 100 )
await u . sendCustomCmd ( updateCamCommand )
await u . closeDebugPanel ( )
await page . mouse . click ( clickCoords . x , clickCoords . y )
await page . waitForTimeout ( 300 ) // wait for animation
await expect ( page . getByRole ( 'button' , { name : 'Line' } ) ) . toBeVisible ( )
// draw a line
const startXPx = 600
await u . closeDebugPanel ( )
await page . mouse . click ( startXPx + PUR * 10 , 500 - PUR * 10 )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( code )
await page . getByRole ( 'button' , { name : 'Line' } ) . click ( )
await u . openAndClearDebugPanel ( )
await page . getByRole ( 'button' , { name : 'Exit Sketch' } ) . click ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await u . clearCommandLogs ( )
await u . removeCurrentCode ( )
}
test ( 'XY' , async ( { page } ) = > {
await sketchOnPlaneAndBackSideTest (
page ,
'XY' ,
{ x : 600 , y : 388 } // red plane
// { x: 600, y: 400 }, // red plane // clicks grid helper and that causes problems, should fix so that these coords work too.
)
} )
test ( 'YZ' , async ( { page } ) = > {
await sketchOnPlaneAndBackSideTest ( page , 'YZ' , { x : 700 , y : 250 } ) // green plane
} )
test ( 'XZ' , async ( { page } ) = > {
await sketchOnPlaneAndBackSideTest ( page , '-XZ' , { x : 700 , y : 80 } ) // blue plane
} )
test ( '-XY' , async ( { page } ) = > {
await sketchOnPlaneAndBackSideTest ( page , '-XY' , { x : 600 , y : 118 } ) // back of red plane
} )
test ( '-YZ' , async ( { page } ) = > {
await sketchOnPlaneAndBackSideTest ( page , '-YZ' , { x : 700 , y : 219 } ) // back of green plane
} )
test ( '-XZ' , async ( { page } ) = > {
await sketchOnPlaneAndBackSideTest ( page , 'XZ' , { x : 700 , y : 427 } ) // back of blue plane
} )
} )
test . describe ( 'Copilot ghost text' , ( ) = > {
test ( 'completes code in empty file' , async ( { page } ) = > {
const u = await getUtils ( page )
// const PUR = 400 / 37.5 //pixeltoUnitRatio
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
await u . codeLocator . click ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( ` ` )
await expect ( page . locator ( '.cm-ghostText' ) ) . not . toBeVisible ( )
await page . waitForTimeout ( 500 )
await page . keyboard . press ( 'Enter' )
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . toBeVisible ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
` fn cube = (pos, scale) => { const sg = startSketchOn('XY') |> startProfileAt(pos, %) |> line([0, scale], %) |> line([scale, 0], %) |> line([0, -scale], %) return sg}const part001 = cube([0,0], 20) |> close(%) |> extrude(20, %) `
)
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . toHaveText (
` fn cube = (pos, scale) => { `
)
// We should be able to hit Tab to accept the completion.
await page . keyboard . press ( 'Tab' )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
` fn cube = (pos, scale) => { const sg = startSketchOn('XY') |> startProfileAt(pos, %) |> line([0, scale], %) |> line([scale, 0], %) |> line([0, -scale], %) return sg}const part001 = cube([0,0], 20) |> close(%) |> extrude(20, %) `
)
// Hit enter a few times.
await page . keyboard . press ( 'Enter' )
await page . keyboard . press ( 'Enter' )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
` fn cube = (pos, scale) => { const sg = startSketchOn('XY') |> startProfileAt(pos, %) |> line([0, scale], %) |> line([scale, 0], %) |> line([0, -scale], %) return sg}const part001 = cube([0,0], 20) |> close(%) |> extrude(20, %) `
)
await expect ( page . locator ( '.cm-ghostText' ) ) . not . toBeVisible ( )
} )
test ( 'copilot disabled in sketch mode no select plane' , async ( { page } ) = > {
const u = await getUtils ( page )
// const PUR = 400 / 37.5 //pixeltoUnitRatio
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
await u . codeLocator . click ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( ` ` )
// Click sketch mode.
await page . getByRole ( 'button' , { name : 'Start Sketch' } ) . click ( )
await u . codeLocator . click ( )
await expect ( page . locator ( '.cm-ghostText' ) ) . not . toBeVisible ( )
2024-07-01 21:05:31 -07:00
await page . waitForTimeout ( 500 )
await page . keyboard . press ( 'Enter' )
await page . waitForTimeout ( 500 )
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . not . toBeVisible ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( ` ` )
// Exit sketch mode.
await page . getByRole ( 'button' , { name : 'Exit Sketch' } ) . click ( )
await page . waitForTimeout ( 500 )
await u . codeLocator . click ( )
await expect ( page . locator ( '.cm-ghostText' ) ) . not . toBeVisible ( )
await page . waitForTimeout ( 500 )
await page . keyboard . press ( 'Enter' )
await page . waitForTimeout ( 500 )
await page . keyboard . press ( 'Enter' )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
` fn cube = (pos, scale) => { const sg = startSketchOn('XY') |> startProfileAt(pos, %) |> line([0, scale], %) |> line([scale, 0], %) |> line([0, -scale], %) return sg}const part001 = cube([0,0], 20) |> close(%) |> extrude(20, %) `
)
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . toHaveText (
` fn cube = (pos, scale) => { `
)
// We should be able to hit Tab to accept the completion.
await page . keyboard . press ( 'Tab' )
await expect ( page . locator ( '.cm-content' ) ) . toContainText (
` fn cube = (pos, scale) => { const sg = startSketchOn('XY') |> startProfileAt(pos, %) |> line([0, scale], %) |> line([scale, 0], %) |> line([0, -scale], %) return sg}const part001 = cube([0,0], 20) |> close(%) |> extrude(20, %) `
)
} )
test ( 'copilot disabled in sketch mode after selecting plane' , async ( {
page ,
} ) = > {
const u = await getUtils ( page )
// const PUR = 400 / 37.5 //pixeltoUnitRatio
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
await u . codeLocator . click ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( ` ` )
// Click sketch mode.
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . not . toBeDisabled ( )
await page . getByRole ( 'button' , { name : 'Start Sketch' } ) . click ( )
// select a plane
await page . mouse . click ( 700 , 200 )
await page . waitForTimeout ( 700 ) // wait for animation
await u . codeLocator . click ( )
await expect ( page . locator ( '.cm-ghostText' ) ) . not . toBeVisible ( )
await page . waitForTimeout ( 500 )
await page . keyboard . press ( 'Enter' )
await page . waitForTimeout ( 500 )
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . not . toBeVisible ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
` const sketch001 = startSketchOn('XZ') `
)
// Escape to exit the tool.
await u . openDebugPanel ( )
await u . closeDebugPanel ( )
await page . keyboard . press ( 'Escape' )
await page . waitForTimeout ( 500 )
await u . codeLocator . click ( )
await expect ( page . locator ( '.cm-ghostText' ) ) . not . toBeVisible ( )
await page . waitForTimeout ( 500 )
await page . keyboard . press ( 'Enter' )
await page . waitForTimeout ( 500 )
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . not . toBeVisible ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
` const sketch001 = startSketchOn('XZ') `
)
// Escape again to exit sketch mode.
await u . openDebugPanel ( )
await u . closeDebugPanel ( )
await page . keyboard . press ( 'Escape' )
await page . waitForTimeout ( 500 )
await u . codeLocator . click ( )
await expect ( page . locator ( '.cm-ghostText' ) ) . not . toBeVisible ( )
await page . waitForTimeout ( 500 )
await page . keyboard . press ( 'Enter' )
await page . waitForTimeout ( 500 )
await page . keyboard . press ( 'Enter' )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
` const sketch001 = startSketchOn('XZ')fn cube = (pos, scale) => { const sg = startSketchOn('XY') |> startProfileAt(pos, %) |> line([0, scale], %) |> line([scale, 0], %) |> line([0, -scale], %) return sg}const part001 = cube([0,0], 20) |> close(%) |> extrude(20, %) `
)
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . toHaveText (
` fn cube = (pos, scale) => { `
)
// We should be able to hit Tab to accept the completion.
await page . keyboard . press ( 'Tab' )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
` const sketch001 = startSketchOn('XZ')fn cube = (pos, scale) => { const sg = startSketchOn('XY') |> startProfileAt(pos, %) |> line([0, scale], %) |> line([scale, 0], %) |> line([0, -scale], %) return sg}const part001 = cube([0,0], 20) |> close(%) |> extrude(20, %) `
)
// Hit enter a few times.
await page . keyboard . press ( 'Enter' )
await page . keyboard . press ( 'Enter' )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
` const sketch001 = startSketchOn('XZ')fn cube = (pos, scale) => { const sg = startSketchOn('XY') |> startProfileAt(pos, %) |> line([0, scale], %) |> line([scale, 0], %) |> line([0, -scale], %) return sg}const part001 = cube([0,0], 20) |> close(%) |> extrude(20, %) `
2024-06-30 18:26:16 -07:00
)
await expect ( page . locator ( '.cm-ghostText' ) ) . not . toBeVisible ( )
} )
2024-06-30 19:37:17 -07:00
test ( 'ArrowUp in code rejects the suggestion' , async ( { page } ) = > {
2024-06-30 18:26:16 -07:00
const u = await getUtils ( page )
// const PUR = 400 / 37.5 //pixeltoUnitRatio
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
await u . codeLocator . click ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( ` ` )
await expect ( page . locator ( '.cm-ghostText' ) ) . not . toBeVisible ( )
await page . waitForTimeout ( 500 )
await page . keyboard . press ( 'Enter' )
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . toBeVisible ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
` fn cube = (pos, scale) => { const sg = startSketchOn('XY') |> startProfileAt(pos, %) |> line([0, scale], %) |> line([scale, 0], %) |> line([0, -scale], %) return sg}const part001 = cube([0,0], 20) |> close(%) |> extrude(20, %) `
)
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . toHaveText (
` fn cube = (pos, scale) => { `
)
// Going elsewhere in the code should hide the ghost text.
await page . keyboard . press ( 'ArrowUp' )
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . not . toBeVisible ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( ` ` )
} )
2024-06-30 19:37:17 -07:00
test ( 'ArrowDown in code rejects the suggestion' , async ( { page } ) = > {
const u = await getUtils ( page )
// const PUR = 400 / 37.5 //pixeltoUnitRatio
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
await u . codeLocator . click ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( ` ` )
await expect ( page . locator ( '.cm-ghostText' ) ) . not . toBeVisible ( )
await page . waitForTimeout ( 500 )
await page . keyboard . press ( 'Enter' )
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . toBeVisible ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
` fn cube = (pos, scale) => { const sg = startSketchOn('XY') |> startProfileAt(pos, %) |> line([0, scale], %) |> line([scale, 0], %) |> line([0, -scale], %) return sg}const part001 = cube([0,0], 20) |> close(%) |> extrude(20, %) `
)
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . toHaveText (
` fn cube = (pos, scale) => { `
)
// Going elsewhere in the code should hide the ghost text.
await page . keyboard . press ( 'ArrowDown' )
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . not . toBeVisible ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( ` ` )
} )
test ( 'ArrowLeft in code rejects the suggestion' , async ( { page } ) = > {
const u = await getUtils ( page )
// const PUR = 400 / 37.5 //pixeltoUnitRatio
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
await u . codeLocator . click ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( ` ` )
await expect ( page . locator ( '.cm-ghostText' ) ) . not . toBeVisible ( )
await page . waitForTimeout ( 500 )
await page . keyboard . press ( 'Enter' )
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . toBeVisible ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
` fn cube = (pos, scale) => { const sg = startSketchOn('XY') |> startProfileAt(pos, %) |> line([0, scale], %) |> line([scale, 0], %) |> line([0, -scale], %) return sg}const part001 = cube([0,0], 20) |> close(%) |> extrude(20, %) `
)
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . toHaveText (
` fn cube = (pos, scale) => { `
)
// Going elsewhere in the code should hide the ghost text.
await page . keyboard . press ( 'ArrowLeft' )
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . not . toBeVisible ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( ` ` )
} )
test ( 'ArrowRight in code rejects the suggestion' , async ( { page } ) = > {
const u = await getUtils ( page )
// const PUR = 400 / 37.5 //pixeltoUnitRatio
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
await u . codeLocator . click ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( ` ` )
await expect ( page . locator ( '.cm-ghostText' ) ) . not . toBeVisible ( )
await page . waitForTimeout ( 500 )
await page . keyboard . press ( 'Enter' )
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . toBeVisible ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
` fn cube = (pos, scale) => { const sg = startSketchOn('XY') |> startProfileAt(pos, %) |> line([0, scale], %) |> line([scale, 0], %) |> line([0, -scale], %) return sg}const part001 = cube([0,0], 20) |> close(%) |> extrude(20, %) `
)
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . toHaveText (
` fn cube = (pos, scale) => { `
)
// Going elsewhere in the code should hide the ghost text.
await page . keyboard . press ( 'ArrowRight' )
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . not . toBeVisible ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( ` ` )
} )
test ( 'Enter in code scoots it down' , async ( { page } ) = > {
const u = await getUtils ( page )
// const PUR = 400 / 37.5 //pixeltoUnitRatio
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
await u . codeLocator . click ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( ` ` )
await expect ( page . locator ( '.cm-ghostText' ) ) . not . toBeVisible ( )
await page . waitForTimeout ( 500 )
await page . keyboard . press ( 'Enter' )
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . toBeVisible ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
` fn cube = (pos, scale) => { const sg = startSketchOn('XY') |> startProfileAt(pos, %) |> line([0, scale], %) |> line([scale, 0], %) |> line([0, -scale], %) return sg}const part001 = cube([0,0], 20) |> close(%) |> extrude(20, %) `
)
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . toHaveText (
` fn cube = (pos, scale) => { `
)
// Going elsewhere in the code should hide the ghost text.
await page . keyboard . press ( 'Enter' )
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . toBeVisible ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
` fn cube = (pos, scale) => { const sg = startSketchOn('XY') |> startProfileAt(pos, %) |> line([0, scale], %) |> line([scale, 0], %) |> line([0, -scale], %) return sg}const part001 = cube([0,0], 20) |> close(%) |> extrude(20, %) `
)
} )
2024-07-02 10:08:02 -07:00
test ( 'Ctrl+shift+z in code rejects the suggestion' , async ( { page } ) = > {
const u = await getUtils ( page )
// const PUR = 400 / 37.5 //pixeltoUnitRatio
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
const CtrlKey = process . platform === 'darwin' ? 'Meta' : 'Control'
await u . codeLocator . click ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( ` ` )
await expect ( page . locator ( '.cm-ghostText' ) ) . not . toBeVisible ( )
await page . waitForTimeout ( 500 )
await page . keyboard . press ( 'Enter' )
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . toBeVisible ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
` fn cube = (pos, scale) => { const sg = startSketchOn('XY') |> startProfileAt(pos, %) |> line([0, scale], %) |> line([scale, 0], %) |> line([0, -scale], %) return sg}const part001 = cube([0,0], 20) |> close(%) |> extrude(20, %) `
)
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . toHaveText (
` fn cube = (pos, scale) => { `
)
// Going elsewhere in the code should hide the ghost text.
await page . keyboard . down ( CtrlKey )
await page . keyboard . down ( 'Shift' )
await page . keyboard . press ( 'KeyZ' )
await page . keyboard . up ( CtrlKey )
await page . keyboard . up ( 'Shift' )
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . not . toBeVisible ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( ` ` )
} )
test ( 'Ctrl+z in code rejects the suggestion and undos the last code' , async ( {
page ,
} ) = > {
const u = await getUtils ( page )
// const PUR = 400 / 37.5 //pixeltoUnitRatio
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
const CtrlKey = process . platform === 'darwin' ? 'Meta' : 'Control'
await page . waitForTimeout ( 800 )
await u . codeLocator . click ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( ` ` )
await page . keyboard . type ( '{thing: "blah"}' , { delay : 0 } )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( ` {thing: "blah"} ` )
// We wanna make sure the code saves.
await page . waitForTimeout ( 800 )
// Ctrl+z
await page . keyboard . down ( CtrlKey )
await page . keyboard . press ( 'KeyZ' )
await page . keyboard . up ( CtrlKey )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( ` ` )
// Ctrl+shift+z
await page . keyboard . down ( CtrlKey )
await page . keyboard . down ( 'Shift' )
await page . keyboard . press ( 'KeyZ' )
await page . keyboard . up ( CtrlKey )
await page . keyboard . up ( 'Shift' )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( ` {thing: "blah"} ` )
// We wanna make sure the code saves.
await page . waitForTimeout ( 800 )
await page . waitForTimeout ( 500 )
await page . keyboard . press ( 'Enter' )
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . toBeVisible ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
` {thing: "blah"}fn cube = (pos, scale) => { const sg = startSketchOn('XY') |> startProfileAt(pos, %) |> line([0, scale], %) |> line([scale, 0], %) |> line([0, -scale], %) return sg}const part001 = cube([0,0], 20) |> close(%) |> extrude(20, %) `
)
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . toHaveText (
` fn cube = (pos, scale) => { `
)
// Once for the enter.
await page . keyboard . down ( CtrlKey )
await page . keyboard . press ( 'KeyZ' )
await page . keyboard . up ( CtrlKey )
// Once for the text.
await page . keyboard . down ( CtrlKey )
await page . keyboard . press ( 'KeyZ' )
await page . keyboard . up ( CtrlKey )
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . not . toBeVisible ( )
2024-07-03 19:28:46 -07:00
// TODO when we make codemirror a widget, we can test this.
//await expect(page.locator('.cm-content')).toHaveText(``)
2024-07-02 10:08:02 -07:00
} )
2024-06-30 18:26:16 -07:00
test ( 'delete in code rejects the suggestion' , async ( { page } ) = > {
const u = await getUtils ( page )
// const PUR = 400 / 37.5 //pixeltoUnitRatio
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
await u . codeLocator . click ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( ` ` )
await expect ( page . locator ( '.cm-ghostText' ) ) . not . toBeVisible ( )
await page . waitForTimeout ( 500 )
await page . keyboard . press ( 'Enter' )
await page . keyboard . press ( 'Enter' )
await page . keyboard . press ( 'Enter' )
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . toBeVisible ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
` fn cube = (pos, scale) => { const sg = startSketchOn('XY') |> startProfileAt(pos, %) |> line([0, scale], %) |> line([scale, 0], %) |> line([0, -scale], %) return sg}const part001 = cube([0,0], 20) |> close(%) |> extrude(20, %) `
)
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . toHaveText (
` fn cube = (pos, scale) => { `
)
// Going elsewhere in the code should hide the ghost text.
await page . keyboard . press ( 'Delete' )
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . not . toBeVisible ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( ` ` )
} )
test ( 'backspace in code rejects the suggestion' , async ( { page } ) = > {
const u = await getUtils ( page )
// const PUR = 400 / 37.5 //pixeltoUnitRatio
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
await u . codeLocator . click ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( ` ` )
await expect ( page . locator ( '.cm-ghostText' ) ) . not . toBeVisible ( )
await page . waitForTimeout ( 500 )
await page . keyboard . press ( 'Enter' )
await page . keyboard . press ( 'Enter' )
await page . keyboard . press ( 'Enter' )
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . toBeVisible ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
` fn cube = (pos, scale) => { const sg = startSketchOn('XY') |> startProfileAt(pos, %) |> line([0, scale], %) |> line([scale, 0], %) |> line([0, -scale], %) return sg}const part001 = cube([0,0], 20) |> close(%) |> extrude(20, %) `
)
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . toHaveText (
` fn cube = (pos, scale) => { `
)
// Going elsewhere in the code should hide the ghost text.
await page . keyboard . press ( 'Backspace' )
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . not . toBeVisible ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( ` ` )
} )
test ( 'focus outside code pane rejects the suggestion' , async ( { page } ) = > {
const u = await getUtils ( page )
// const PUR = 400 / 37.5 //pixeltoUnitRatio
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
await u . codeLocator . click ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( ` ` )
await expect ( page . locator ( '.cm-ghostText' ) ) . not . toBeVisible ( )
await page . waitForTimeout ( 500 )
await page . keyboard . press ( 'Enter' )
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . toBeVisible ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
` fn cube = (pos, scale) => { const sg = startSketchOn('XY') |> startProfileAt(pos, %) |> line([0, scale], %) |> line([scale, 0], %) |> line([0, -scale], %) return sg}const part001 = cube([0,0], 20) |> close(%) |> extrude(20, %) `
)
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . toHaveText (
` fn cube = (pos, scale) => { `
)
// Going outside the editor should hide the ghost text.
await page . mouse . move ( 0 , 0 )
await page
. getByRole ( 'button' , { name : 'Start Sketch' } )
. waitFor ( { state : 'visible' } )
await page . getByRole ( 'button' , { name : 'Start Sketch' } ) . click ( )
await expect ( page . locator ( '.cm-ghostText' ) . first ( ) ) . not . toBeVisible ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( ` ` )
} )
2024-06-21 15:06:01 -07:00
} )
2024-07-03 14:34:45 +10:00
test . describe ( 'Testing settings' , ( ) = > {
test ( 'Stored settings are validated and fall back to defaults' , async ( {
page ,
} ) = > {
2024-06-29 18:10:07 -07:00
const u = await getUtils ( page )
2024-07-03 14:34:45 +10:00
// Override beforeEach test setup
// with corrupted settings
await page . addInitScript (
async ( { settingsKey , settings } ) = > {
localStorage . setItem ( settingsKey , settings )
} ,
{
settingsKey : TEST_SETTINGS_KEY ,
settings : TOML.stringify ( { settings : TEST_SETTINGS_CORRUPTED } ) ,
}
)
2024-06-29 18:10:07 -07:00
2024-07-03 14:34:45 +10:00
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-07-03 14:34:45 +10:00
await u . waitForAuthSkipAppStart ( )
2024-06-29 18:10:07 -07:00
2024-07-03 14:34:45 +10:00
// Check the settings were reset
const storedSettings = TOML . parse (
await page . evaluate (
( { settingsKey } ) = > localStorage . getItem ( settingsKey ) || '' ,
{ settingsKey : TEST_SETTINGS_KEY }
)
) as { settings : SaveSettingsPayload }
2024-06-29 18:10:07 -07:00
2024-07-03 14:34:45 +10:00
expect ( storedSettings . settings ? . app ? . theme ) . toBe ( undefined )
2024-06-29 18:10:07 -07:00
2024-07-03 14:34:45 +10:00
// Check that the invalid settings were removed
expect ( storedSettings . settings ? . modeling ? . defaultUnit ) . toBe ( undefined )
expect ( storedSettings . settings ? . modeling ? . mouseControls ) . toBe ( undefined )
expect ( storedSettings . settings ? . app ? . projectDirectory ) . toBe ( undefined )
expect ( storedSettings . settings ? . projects ? . defaultProjectName ) . toBe (
undefined
)
2024-03-22 18:10:49 +11:00
} )
2023-11-24 08:59:24 +11:00
2024-07-03 14:34:45 +10:00
test ( 'Project settings can be set and override user settings' , async ( {
page ,
} ) = > {
2024-07-03 12:41:24 +10:00
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
await page
. getByRole ( 'button' , { name : 'Start Sketch' } )
. waitFor ( { state : 'visible' } )
2024-04-02 10:29:34 -04:00
2024-07-03 12:41:24 +10:00
// Open the settings modal with the browser keyboard shortcut
await page . keyboard . press ( 'Meta+Shift+,' )
2024-04-02 10:29:34 -04:00
2024-07-03 12:41:24 +10:00
await expect (
page . getByRole ( 'heading' , { name : 'Settings' , exact : true } )
) . toBeVisible ( )
await page
. locator ( 'select[name="app-theme"]' )
. selectOption ( { value : 'light' } )
2024-04-02 10:29:34 -04:00
2024-07-03 12:41:24 +10:00
// Verify the toast appeared
await expect (
page . getByText ( ` Set theme to "light" for this project ` )
) . toBeVisible ( )
// Check that the theme changed
await expect ( page . locator ( 'body' ) ) . not . toHaveClass ( ` body-bg dark ` )
2024-04-02 10:29:34 -04:00
2024-07-03 12:41:24 +10:00
// Check that the user setting was not changed
await page . getByRole ( 'radio' , { name : 'User' } ) . click ( )
await expect ( page . locator ( 'select[name="app-theme"]' ) ) . toHaveValue ( 'dark' )
2024-04-02 10:29:34 -04:00
2024-07-03 12:41:24 +10:00
// Roll back to default "system" theme
await page
. getByText (
'themeRoll back themeRoll back to match defaultThe overall appearance of the appl'
)
. hover ( )
await page
. getByRole ( 'button' , {
name : 'Roll back theme ; Has tooltip: Roll back to match default' ,
} )
. click ( )
await expect ( page . locator ( 'select[name="app-theme"]' ) ) . toHaveValue ( 'system' )
2024-03-14 15:56:45 -04:00
2024-07-03 12:41:24 +10:00
// Check that the project setting did not change
await page . getByRole ( 'radio' , { name : 'Project' } ) . click ( )
await expect ( page . locator ( 'select[name="app-theme"]' ) ) . toHaveValue ( 'light' )
} )
2024-03-14 15:56:45 -04:00
2024-07-03 12:41:24 +10:00
test ( 'Project settings can be opened with keybinding from the editor' , async ( {
page ,
} ) = > {
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
await page
. getByRole ( 'button' , { name : 'Start Sketch' } )
. waitFor ( { state : 'visible' } )
2024-05-20 20:52:33 -07:00
2024-07-03 12:41:24 +10:00
// Put the cursor in the editor
await page . locator ( '.cm-content' ) . click ( )
2024-05-20 20:52:33 -07:00
2024-07-03 12:41:24 +10:00
// Open the settings modal with the browser keyboard shortcut
await page . keyboard . press ( 'Meta+Shift+,' )
2024-05-20 20:52:33 -07:00
2024-07-03 12:41:24 +10:00
await expect (
page . getByRole ( 'heading' , { name : 'Settings' , exact : true } )
) . toBeVisible ( )
await page
. locator ( 'select[name="app-theme"]' )
. selectOption ( { value : 'light' } )
2024-05-20 20:52:33 -07:00
2024-07-03 12:41:24 +10:00
// Verify the toast appeared
await expect (
page . getByText ( ` Set theme to "light" for this project ` )
) . toBeVisible ( )
// Check that the theme changed
await expect ( page . locator ( 'body' ) ) . not . toHaveClass ( ` body-bg dark ` )
2024-05-20 20:52:33 -07:00
2024-07-03 12:41:24 +10:00
// Check that the user setting was not changed
await page . getByRole ( 'radio' , { name : 'User' } ) . click ( )
await expect ( page . locator ( 'select[name="app-theme"]' ) ) . toHaveValue ( 'dark' )
2024-05-20 20:52:33 -07:00
2024-07-03 12:41:24 +10:00
// Roll back to default "system" theme
await page
. getByText (
'themeRoll back themeRoll back to match defaultThe overall appearance of the appl'
)
. hover ( )
await page
. getByRole ( 'button' , {
name : 'Roll back theme ; Has tooltip: Roll back to match default' ,
} )
. click ( )
await expect ( page . locator ( 'select[name="app-theme"]' ) ) . toHaveValue ( 'system' )
2024-05-20 20:52:33 -07:00
2024-07-03 12:41:24 +10:00
// Check that the project setting did not change
await page . getByRole ( 'radio' , { name : 'Project' } ) . click ( )
await expect ( page . locator ( 'select[name="app-theme"]' ) ) . toHaveValue ( 'light' )
} )
2024-05-20 20:52:33 -07:00
2024-07-03 12:41:24 +10:00
test ( 'Project and user settings can be reset' , async ( { page } ) = > {
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
await page
. getByRole ( 'button' , { name : 'Start Sketch' } )
. waitFor ( { state : 'visible' } )
2024-05-21 13:33:52 -07:00
2024-07-03 12:41:24 +10:00
// Put the cursor in the editor
await page . locator ( '.cm-content' ) . click ( )
2024-05-21 13:33:52 -07:00
2024-07-03 12:41:24 +10:00
// Open the settings modal with the browser keyboard shortcut
await page . keyboard . press ( 'Meta+Shift+,' )
2024-05-21 13:33:52 -07:00
2024-07-03 12:41:24 +10:00
await expect (
page . getByRole ( 'heading' , { name : 'Settings' , exact : true } )
) . toBeVisible ( )
2024-05-21 13:33:52 -07:00
2024-07-03 12:41:24 +10:00
// Click the reset settings button.
await page . getByRole ( 'button' , { name : 'Restore default settings' } ) . click ( )
2024-05-21 13:33:52 -07:00
2024-07-03 12:41:24 +10:00
await page
. locator ( 'select[name="app-theme"]' )
. selectOption ( { value : 'light' } )
2024-05-21 13:33:52 -07:00
2024-07-03 12:41:24 +10:00
// Verify the toast appeared
await expect (
page . getByText ( ` Set theme to "light" for this project ` )
) . toBeVisible ( )
// Check that the theme changed
await expect ( page . locator ( 'body' ) ) . not . toHaveClass ( ` body-bg dark ` )
await expect ( page . locator ( 'select[name="app-theme"]' ) ) . toHaveValue ( 'light' )
2024-05-21 13:33:52 -07:00
2024-07-03 12:41:24 +10:00
// Check that the user setting was not changed
await page . getByRole ( 'radio' , { name : 'User' } ) . click ( )
await expect ( page . locator ( 'select[name="app-theme"]' ) ) . toHaveValue ( 'system' )
2024-05-21 13:33:52 -07:00
2024-07-03 12:41:24 +10:00
// Click the reset settings button.
await page . getByRole ( 'button' , { name : 'Restore default settings' } ) . click ( )
2024-05-21 13:33:52 -07:00
2024-07-03 12:41:24 +10:00
// Verify it is now set to the default value
await expect ( page . locator ( 'select[name="app-theme"]' ) ) . toHaveValue ( 'system' )
2024-05-21 13:33:52 -07:00
2024-07-03 12:41:24 +10:00
// Set the user theme to light.
await page
. locator ( 'select[name="app-theme"]' )
. selectOption ( { value : 'light' } )
2024-05-21 13:33:52 -07:00
2024-07-03 12:41:24 +10:00
// Verify the toast appeared
await expect (
page . getByText ( ` Set theme to "light" as a user default ` )
) . toBeVisible ( )
// Check that the theme changed
await expect ( page . locator ( 'body' ) ) . not . toHaveClass ( ` body-bg dark ` )
await expect ( page . locator ( 'select[name="app-theme"]' ) ) . toHaveValue ( 'light' )
2024-05-21 13:33:52 -07:00
2024-07-03 12:41:24 +10:00
await page . getByRole ( 'radio' , { name : 'Project' } ) . click ( )
await expect ( page . locator ( 'select[name="app-theme"]' ) ) . toHaveValue ( 'light' )
2024-05-21 13:33:52 -07:00
2024-07-03 12:41:24 +10:00
// Click the reset settings button.
await page . getByRole ( 'button' , { name : 'Restore default settings' } ) . click ( )
// Verify it is now set to the default value
await expect ( page . locator ( 'select[name="app-theme"]' ) ) . toHaveValue ( 'system' )
2024-05-21 13:33:52 -07:00
2024-07-03 12:41:24 +10:00
await page . getByRole ( 'radio' , { name : 'User' } ) . click ( )
await expect ( page . locator ( 'select[name="app-theme"]' ) ) . toHaveValue ( 'system' )
2024-05-21 13:33:52 -07:00
2024-07-03 12:41:24 +10:00
// Click the reset settings button.
await page . getByRole ( 'button' , { name : 'Restore default settings' } ) . click ( )
2024-05-21 13:33:52 -07:00
2024-07-03 12:41:24 +10:00
// Verify it is now set to the default value
await expect ( page . locator ( 'select[name="app-theme"]' ) ) . toHaveValue ( 'system' )
} )
2024-05-21 13:33:52 -07:00
} )
2024-06-20 12:07:21 -04:00
test . describe ( 'Onboarding tests' , ( ) = > {
test ( 'Onboarding code is shown in the editor' , async ( { page } ) = > {
const u = await getUtils ( page )
2024-04-26 13:20:03 -04:00
2024-06-20 12:07:21 -04:00
// Override beforeEach test setup
await page . addInitScript (
async ( { settingsKey } ) = > {
// Give no initial code, so that the onboarding start is shown immediately
localStorage . removeItem ( 'persistCode' )
localStorage . removeItem ( settingsKey )
} ,
{ settingsKey : TEST_SETTINGS_KEY }
)
2024-04-26 13:20:03 -04:00
2024-06-20 12:07:21 -04:00
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-06-20 12:07:21 -04:00
await u . waitForAuthSkipAppStart ( )
2024-04-26 13:20:03 -04:00
2024-06-20 12:07:21 -04:00
// Test that the onboarding pane loaded
await expect ( page . getByText ( 'Welcome to Modeling App! This' ) ) . toBeVisible ( )
2024-04-26 13:20:03 -04:00
2024-06-20 12:07:21 -04:00
// *and* that the code is shown in the editor
await expect ( page . locator ( '.cm-content' ) ) . toContainText ( '// Shelf Bracket' )
} )
2024-04-26 13:20:03 -04:00
2024-06-20 12:07:21 -04:00
test ( 'Click through each onboarding step' , async ( { page } ) = > {
const u = await getUtils ( page )
2024-04-26 13:20:03 -04:00
2024-06-20 12:07:21 -04:00
// Override beforeEach test setup
await page . addInitScript (
async ( { settingsKey , settings } ) = > {
// Give no initial code, so that the onboarding start is shown immediately
localStorage . setItem ( 'persistCode' , '' )
localStorage . setItem ( settingsKey , settings )
} ,
{
settingsKey : TEST_SETTINGS_KEY ,
settings : TOML.stringify ( { settings : TEST_SETTINGS_ONBOARDING_START } ) ,
}
)
2024-04-26 13:20:03 -04:00
2024-06-20 12:07:21 -04:00
await page . setViewportSize ( { width : 1200 , height : 1080 } )
2024-06-29 18:10:07 -07:00
2024-06-20 12:07:21 -04:00
await u . waitForAuthSkipAppStart ( )
2024-04-26 13:20:03 -04:00
2024-06-20 12:07:21 -04:00
// Test that the onboarding pane loaded
await expect ( page . getByText ( 'Welcome to Modeling App! This' ) ) . toBeVisible ( )
2023-11-27 19:46:15 -05:00
2024-06-20 12:07:21 -04:00
const nextButton = page . getByTestId ( 'onboarding-next' )
while ( ( await nextButton . innerText ( ) ) !== 'Finish' ) {
await expect ( nextButton ) . toBeVisible ( )
await nextButton . click ( )
2024-04-11 13:37:49 -04:00
}
2023-11-27 19:46:15 -05:00
2024-06-20 12:07:21 -04:00
// Finish the onboarding
await expect ( nextButton ) . toBeVisible ( )
await nextButton . click ( )
2023-11-27 19:46:15 -05:00
2024-06-20 12:07:21 -04:00
// Test that the onboarding pane is gone
await expect ( page . getByTestId ( 'onboarding-content' ) ) . not . toBeVisible ( )
await expect ( page . url ( ) ) . not . toContain ( 'onboarding' )
} )
2023-11-27 19:46:15 -05:00
2024-06-20 12:07:21 -04:00
test ( 'Onboarding redirects and code updating' , async ( { page } ) = > {
const u = await getUtils ( page )
2023-11-27 19:46:15 -05:00
2024-06-20 12:07:21 -04:00
// Override beforeEach test setup
await page . addInitScript (
async ( { settingsKey , settings } ) = > {
// Give some initial code, so we can test that it's cleared
localStorage . setItem ( 'persistCode' , 'const sigmaAllow = 15000' )
localStorage . setItem ( settingsKey , settings )
} ,
{
settingsKey : TEST_SETTINGS_KEY ,
settings : TOML.stringify ( { settings : TEST_SETTINGS_ONBOARDING_EXPORT } ) ,
}
)
2023-11-27 19:46:15 -05:00
2024-06-20 12:07:21 -04:00
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-06-20 12:07:21 -04:00
await u . waitForAuthSkipAppStart ( )
2023-11-27 19:46:15 -05:00
2024-06-20 12:07:21 -04:00
// Test that the redirect happened
await expect ( page . url ( ) . split ( ':3000' ) . slice ( - 1 ) [ 0 ] ) . toBe (
` /file/%2Fbrowser%2Fmain.kcl/onboarding/export `
)
// Test that you come back to this page when you refresh
await page . reload ( )
await expect ( page . url ( ) . split ( ':3000' ) . slice ( - 1 ) [ 0 ] ) . toBe (
` /file/%2Fbrowser%2Fmain.kcl/onboarding/export `
)
// Test that the onboarding pane loaded
const title = page . locator ( '[data-testid="onboarding-content"]' )
await expect ( title ) . toBeAttached ( )
// Test that the code changes when you advance to the next step
await page . locator ( '[data-testid="onboarding-next"]' ) . click ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( '' )
// Test that the code is not empty when you click on the next step
await page . locator ( '[data-testid="onboarding-next"]' ) . click ( )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( /.+/ )
} )
2024-06-20 14:06:11 -04:00
2024-06-20 21:39:01 -04:00
test ( 'Onboarding code gets reset to demo on Interactive Numbers step' , async ( {
page ,
} ) = > {
test . skip (
process . platform === 'darwin' ,
"Skip on macOS, because Playwright isn't behaving the same as the actual browser"
)
const u = await getUtils ( page )
const badCode = ` // This is bad code we shouldn't see `
// Override beforeEach test setup
await page . addInitScript (
async ( { settingsKey , settings , badCode } ) = > {
localStorage . setItem ( 'persistCode' , badCode )
localStorage . setItem ( settingsKey , settings )
} ,
{
settingsKey : TEST_SETTINGS_KEY ,
settings : TOML.stringify ( {
settings : TEST_SETTINGS_ONBOARDING_PARAMETRIC_MODELING ,
} ) ,
badCode ,
}
)
await page . setViewportSize ( { width : 1200 , height : 1080 } )
2024-06-29 18:10:07 -07:00
await u . waitForAuthSkipAppStart ( )
2024-06-20 21:39:01 -04:00
await page . waitForURL ( '**' + onboardingPaths . PARAMETRIC_MODELING , {
waitUntil : 'domcontentloaded' ,
} )
const bracketNoNewLines = bracket . replace ( /\n/g , '' )
// Check the code got reset on load
await expect ( page . locator ( '#code-pane' ) ) . toBeVisible ( )
await expect ( u . codeLocator ) . toHaveText ( bracketNoNewLines , {
timeout : 10_000 ,
} )
// Mess with the code again
await u . codeLocator . selectText ( )
await u . codeLocator . fill ( badCode )
await expect ( u . codeLocator ) . toHaveText ( badCode )
// Click to the next step
await page . locator ( '[data-testid="onboarding-next"]' ) . click ( )
await page . waitForURL ( '**' + onboardingPaths . INTERACTIVE_NUMBERS , {
waitUntil : 'domcontentloaded' ,
} )
// Check that the code has been reset
await expect ( u . codeLocator ) . toHaveText ( bracketNoNewLines )
} )
2024-06-20 14:06:11 -04:00
test ( 'Avatar text updates depending on image load success' , async ( {
page ,
} ) = > {
// Override beforeEach test setup
await page . addInitScript (
async ( { settingsKey , settings } ) = > {
localStorage . setItem ( settingsKey , settings )
} ,
{
settingsKey : TEST_SETTINGS_KEY ,
settings : TOML.stringify ( {
settings : TEST_SETTINGS_ONBOARDING_USER_MENU ,
} ) ,
}
)
2024-06-29 18:10:07 -07:00
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
2024-06-20 14:06:11 -04:00
await page . waitForURL ( '**/file/**' , { waitUntil : 'domcontentloaded' } )
// Test that the text in this step is correct
2024-06-25 13:56:11 -04:00
const avatarLocator = await page
. getByTestId ( 'user-sidebar-toggle' )
. locator ( 'img' )
const onboardingOverlayLocator = await page
2024-06-20 14:06:11 -04:00
. 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' )
2024-06-25 13:56:11 -04:00
// 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
2024-06-20 14:06:11 -04:00
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' )
} )
2023-11-27 19:46:15 -05:00
} )
2023-11-28 21:23:20 +11:00
2024-06-06 21:55:22 +10:00
test . describe ( 'Testing selections' , ( ) = > {
2024-06-30 06:10:54 +10:00
test . setTimeout ( 90 _000 )
2024-06-06 21:55:22 +10:00
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 = await getUtils ( page )
const PUR = 400 / 37.5 //pixeltoUnitRatio
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-06-06 21:55:22 +10:00
await u . waitForAuthSkipAppStart ( )
await u . openDebugPanel ( )
2023-11-28 21:23:20 +11:00
2024-06-06 21:55:22 +10:00
const xAxisClick = ( ) = >
page . mouse . click ( 700 , 253 ) . then ( ( ) = > page . waitForTimeout ( 100 ) )
const emptySpaceClick = ( ) = >
page . mouse . click ( 700 , 343 ) . then ( ( ) = > page . waitForTimeout ( 100 ) )
const topHorzSegmentClick = ( ) = >
page . mouse . click ( 709 , 290 ) . then ( ( ) = > page . waitForTimeout ( 100 ) )
const bottomHorzSegmentClick = ( ) = >
page . mouse . click ( 767 , 396 ) . then ( ( ) = > page . waitForTimeout ( 100 ) )
2023-12-01 20:18:51 +11:00
2024-06-06 21:55:22 +10:00
await u . clearCommandLogs ( )
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . not . toBeDisabled ( )
await page . getByRole ( 'button' , { name : 'Start Sketch' } ) . click ( )
2023-11-28 21:23:20 +11:00
2024-06-06 21:55:22 +10:00
// select a plane
await page . mouse . click ( 700 , 200 )
await page . waitForTimeout ( 700 ) // wait for animation
2023-11-28 21:23:20 +11:00
2024-06-06 21:55:22 +10:00
const startXPx = 600
await u . closeDebugPanel ( )
await page . mouse . click ( startXPx + PUR * 10 , 500 - PUR * 10 )
await expect ( page . locator ( '.cm-content' ) )
. toHaveText ( ` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( $ { commonPoints . startAt } , % ) ` )
2024-02-11 12:59:00 +11:00
2024-06-06 21:55:22 +10:00
await page . waitForTimeout ( 100 )
await page . mouse . click ( startXPx + PUR * 20 , 500 - PUR * 10 )
2023-11-28 21:23:20 +11:00
2024-06-06 21:55:22 +10:00
await expect ( page . locator ( '.cm-content' ) )
. toHaveText ( ` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( $ { commonPoints . startAt } , % )
| > line ( [ $ { commonPoints . num1 } , 0 ] , % ) ` )
2023-11-28 21:23:20 +11:00
2024-06-06 21:55:22 +10:00
await page . waitForTimeout ( 100 )
await page . mouse . click ( startXPx + PUR * 20 , 500 - PUR * 20 )
await expect ( page . locator ( '.cm-content' ) )
. toHaveText ( ` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( $ { commonPoints . startAt } , % )
| > line ( [ $ { commonPoints . num1 } , 0 ] , % )
2024-06-18 16:08:41 +10:00
| > line ( [ 0 , $ { commonPoints . num1 + 0.01 } ] , % ) ` )
2024-06-06 21:55:22 +10:00
await page . waitForTimeout ( 100 )
await page . mouse . click ( startXPx , 500 - PUR * 20 )
await expect ( page . locator ( '.cm-content' ) )
. toHaveText ( ` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( $ { commonPoints . startAt } , % )
| > line ( [ $ { commonPoints . num1 } , 0 ] , % )
2024-06-18 16:08:41 +10:00
| > line ( [ 0 , $ { commonPoints . num1 + 0.01 } ] , % )
2024-06-06 21:55:22 +10:00
| > line ( [ - $ { commonPoints . num2 } , 0 ] , % ) ` )
2023-11-28 21:23:20 +11:00
2024-06-06 21:55:22 +10:00
// deselect line tool
await page . getByRole ( 'button' , { name : 'Line' } ) . click ( )
2023-11-28 21:23:20 +11:00
2024-06-06 21:55:22 +10:00
await u . closeDebugPanel ( )
2024-06-18 16:08:41 +10:00
const selectionSequence = async ( ) = > {
2024-06-06 21:55:22 +10:00
await expect ( page . getByTestId ( 'hover-highlight' ) ) . not . toBeVisible ( )
2023-11-28 21:23:20 +11:00
2024-06-06 21:55:22 +10:00
await page . waitForTimeout ( 100 )
2024-06-18 16:08:41 +10:00
await page . mouse . move ( startXPx + PUR * 15 , 500 - PUR * 10 )
2023-11-28 21:23:20 +11:00
2024-06-30 18:26:16 -07:00
await expect ( page . getByTestId ( 'hover-highlight' ) . first ( ) ) . toBeVisible ( )
2024-06-06 21:55:22 +10:00
// 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
2024-06-30 18:26:16 -07:00
await expect ( page . locator ( '.bg-yellow-200' ) . first ( ) ) . toBeVisible ( )
2024-06-06 21:55:22 +10:00
// 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 ( )
2024-06-18 16:08:41 +10:00
await page . mouse . move ( startXPx + PUR * 10 , 500 - PUR * 20 ) // mouse onto another line
2024-06-06 21:55:22 +10:00
await expect ( page . getByTestId ( 'hover-highlight' ) . first ( ) ) . toBeVisible ( )
// now check clicking works including axis
// click a segment hold shift and click an axis, see that a relevant constraint is enabled
await topHorzSegmentClick ( )
await page . keyboard . down ( 'Shift' )
2024-06-24 11:37:48 -04:00
const constrainButton = page . getByRole ( 'button' , { name : 'Constraints' } )
2024-06-06 21:55:22 +10:00
const absYButton = page . getByRole ( 'button' , { name : 'ABS Y' } )
await constrainButton . click ( )
await expect ( absYButton ) . toBeDisabled ( )
await page . waitForTimeout ( 100 )
await xAxisClick ( )
await page . keyboard . up ( 'Shift' )
await constrainButton . click ( )
await absYButton . and ( page . locator ( ':not([disabled])' ) ) . waitFor ( )
await expect ( absYButton ) . not . toBeDisabled ( )
2023-11-28 21:23:20 +11:00
2024-06-06 21:55:22 +10:00
// clear selection by clicking on nothing
await emptySpaceClick ( )
2023-12-01 20:18:51 +11:00
2024-06-06 21:55:22 +10:00
await page . waitForTimeout ( 100 )
// same selection but click the axis first
await xAxisClick ( )
await constrainButton . click ( )
await expect ( absYButton ) . toBeDisabled ( )
await page . keyboard . down ( 'Shift' )
await page . waitForTimeout ( 100 )
await topHorzSegmentClick ( )
await page . waitForTimeout ( 100 )
2023-12-01 20:18:51 +11:00
2024-06-06 21:55:22 +10:00
await page . keyboard . up ( 'Shift' )
await constrainButton . click ( )
await expect ( absYButton ) . not . toBeDisabled ( )
2023-12-01 20:18:51 +11:00
2024-06-06 21:55:22 +10:00
// clear selection by clicking on nothing
await emptySpaceClick ( )
2023-12-01 20:18:51 +11:00
2024-06-06 21:55:22 +10:00
// check the same selection again by putting cursor in code first then selecting axis
await page . getByText ( ` |> line([- ${ commonPoints . num2 } , 0], %) ` ) . click ( )
await page . keyboard . down ( 'Shift' )
await constrainButton . click ( )
await expect ( absYButton ) . toBeDisabled ( )
await page . waitForTimeout ( 100 )
await xAxisClick ( )
await page . keyboard . up ( 'Shift' )
await constrainButton . click ( )
await expect ( absYButton ) . not . toBeDisabled ( )
2024-02-11 12:59:00 +11:00
2024-06-06 21:55:22 +10:00
// clear selection by clicking on nothing
await emptySpaceClick ( )
2023-12-01 20:18:51 +11:00
2024-06-06 21:55:22 +10:00
// select segment in editor than another segment in scene and check there are two cursors
// TODO change this back to shift click in the scene, not cmd click in the editor
await bottomHorzSegmentClick ( )
2023-12-01 20:18:51 +11:00
2024-06-06 21:55:22 +10:00
await expect ( page . locator ( '.cm-cursor' ) ) . toHaveCount ( 1 )
await page . keyboard . down (
process . platform === 'linux' ? 'Control' : 'Meta'
)
await page . waitForTimeout ( 100 )
await page . getByText ( ` |> line([- ${ commonPoints . num2 } , 0], %) ` ) . click ( )
await expect ( page . locator ( '.cm-cursor' ) ) . toHaveCount ( 2 )
await page . waitForTimeout ( 500 )
await page . keyboard . up ( process . platform === 'linux' ? 'Control' : 'Meta' )
// clear selection by clicking on nothing
await emptySpaceClick ( )
}
await selectionSequence ( )
// hovering in fresh sketch worked, lets try exiting and re-entering
await u . openAndClearDebugPanel ( )
await page . getByRole ( 'button' , { name : 'Exit Sketch' } ) . click ( )
await page . waitForTimeout ( 200 )
// wait for execution done
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await u . closeDebugPanel ( )
// select a line, this verifies that sketches in the scene can be selected outside of sketch mode
await topHorzSegmentClick ( )
2024-04-22 20:14:06 +10:00
await page . waitForTimeout ( 100 )
2023-12-01 20:18:51 +11:00
2024-06-06 21:55:22 +10:00
// enter sketch again
await u . doAndWaitForCmd (
( ) = > page . getByRole ( 'button' , { name : 'Edit Sketch' } ) . click ( ) ,
'default_camera_get_settings'
)
await page . waitForTimeout ( 150 )
await page . waitForTimeout ( 300 ) // wait for animation
2023-12-01 20:18:51 +11:00
2024-06-18 16:08:41 +10:00
await u . openAndClearDebugPanel ( )
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_look_at' ,
center : { x : 0 , y : 0 , z : 0 } ,
vantage : { x : 0 , y : - 1378.01 , z : 0 } ,
up : { x : 0 , y : 0 , z : 1 } ,
} ,
} )
await page . waitForTimeout ( 100 )
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_get_settings' ,
} ,
} )
await page . waitForTimeout ( 100 )
await emptySpaceClick ( )
await u . closeDebugPanel ( )
2024-06-06 21:55:22 +10:00
// hover again and check it works
2024-06-18 16:08:41 +10:00
await selectionSequence ( )
2024-06-06 21:55:22 +10:00
} )
2024-06-29 10:36:04 -07:00
test ( 'Solids should be select and deletable' , async ( { page } ) = > {
test . setTimeout ( 90 _000 )
const u = await getUtils ( page )
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( [ - 79.26 , 95.04 ] , % )
| > line ( [ 112.54 , 127.64 ] , % , $seg02 )
| > line ( [ 170.36 , - 121.61 ] , % , $seg01 )
| > lineTo ( [ profileStartX ( % ) , profileStartY ( % ) ] , % )
| > close ( % )
const extrude001 = extrude ( 50 , sketch001 )
const sketch005 = startSketchOn ( extrude001 , 'END' )
| > startProfileAt ( [ 23.24 , 136.52 ] , % )
| > line ( [ - 8.44 , 36.61 ] , % )
| > line ( [ 49.4 , 2.05 ] , % )
| > line ( [ 29.69 , - 46.95 ] , % )
| > lineTo ( [ profileStartX ( % ) , profileStartY ( % ) ] , % )
| > close ( % )
const sketch003 = startSketchOn ( extrude001 , seg01 )
| > startProfileAt ( [ 21.23 , 17.81 ] , % )
| > line ( [ 51.97 , 21.32 ] , % )
| > line ( [ 4.07 , - 22.75 ] , % )
| > lineTo ( [ profileStartX ( % ) , profileStartY ( % ) ] , % )
| > close ( % )
const sketch002 = startSketchOn ( extrude001 , seg02 )
| > startProfileAt ( [ - 100.54 , 16.99 ] , % )
| > line ( [ 0 , 20.03 ] , % )
| > line ( [ 62.61 , 0 ] , % , $seg03 )
| > lineTo ( [ profileStartX ( % ) , profileStartY ( % ) ] , % )
| > close ( % )
const extrude002 = extrude ( 50 , sketch002 )
const sketch004 = startSketchOn ( extrude002 , seg03 )
| > startProfileAt ( [ 57.07 , 134.77 ] , % )
| > line ( [ - 4.72 , 22.84 ] , % )
| > line ( [ 28.8 , 6.71 ] , % )
| > line ( [ 9.19 , - 25.33 ] , % )
| > lineTo ( [ profileStartX ( % ) , profileStartY ( % ) ] , % )
| > close ( % )
const extrude003 = extrude ( 20 , sketch004 )
const pipeLength = 40
const pipeSmallDia = 10
const pipeLargeDia = 20
const thickness = 0.5
const part009 = startSketchOn ( 'XY' )
| > startProfileAt ( [ pipeLargeDia - ( thickness / 2 ) , 38 ] , % )
| > line ( [ thickness , 0 ] , % )
| > line ( [ 0 , - 1 ] , % )
| > angledLineToX ( {
angle : 60 ,
to : pipeSmallDia + thickness
} , % )
| > line ( [ 0 , - pipeLength ] , % )
| > angledLineToX ( {
angle : - 60 ,
to : pipeLargeDia + thickness
} , % )
| > line ( [ 0 , - 1 ] , % )
| > line ( [ - thickness , 0 ] , % )
| > line ( [ 0 , 1 ] , % )
| > angledLineToX ( { angle : 120 , to : pipeSmallDia } , % )
| > line ( [ 0 , pipeLength ] , % )
| > angledLineToX ( { angle : 60 , to : pipeLargeDia } , % )
| > close ( % )
const rev = revolve ( { axis : 'y' } , part009 )
`
)
} , KCL_DEFAULT_LENGTH )
await page . setViewportSize ( { width : 1000 , height : 500 } )
await page . goto ( '/' )
await u . waitForAuthSkipAppStart ( )
await u . openDebugPanel ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await u . closeDebugPanel ( )
await u . openAndClearDebugPanel ( )
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_look_at' ,
vantage : { x : 1139.49 , y : - 7053 , z : 8597.31 } ,
center : { x : - 2206.68 , y : - 1298.36 , z : 60 } ,
up : { x : 0 , y : 0 , z : 1 } ,
} ,
} )
await page . waitForTimeout ( 100 )
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_get_settings' ,
} ,
} )
await page . waitForTimeout ( 100 )
const revolve = { x : 646 , y : 248 }
const parentExtrude = { x : 915 , y : 133 }
const solid2d = { x : 770 , y : 167 }
// DELETE REVOLVE
await page . mouse . click ( revolve . x , revolve . y )
await page . waitForTimeout ( 100 )
await expect ( page . locator ( '.cm-activeLine' ) ) . toHaveText (
'|> line([0, -pipeLength], %)'
)
await u . clearCommandLogs ( )
await page . keyboard . press ( 'Backspace' )
await u . expectCmdLog ( '[data-message-type="execution-done"]' , 10 _000 )
await page . waitForTimeout ( 200 )
await expect ( u . codeLocator ) . not . toContainText (
` const rev = revolve({ axis: 'y' }, part009) `
)
// DELETE PARENT EXTRUDE
await page . mouse . click ( parentExtrude . x , parentExtrude . y )
await page . waitForTimeout ( 100 )
await expect ( page . locator ( '.cm-activeLine' ) ) . toHaveText (
'|> line([170.36, -121.61], %, $seg01)'
)
await u . clearCommandLogs ( )
await page . keyboard . press ( 'Backspace' )
await u . expectCmdLog ( '[data-message-type="execution-done"]' , 10 _000 )
await page . waitForTimeout ( 200 )
await expect ( u . codeLocator ) . not . toContainText (
` const extrude001 = extrude(50, sketch001) `
)
await expect ( u . codeLocator ) . toContainText ( ` const sketch005 = startSketchOn({
plane : {
origin : { x : 0 , y : - 50 , z : 0 } ,
x_axis : { x : 1 , y : 0 , z : 0 } ,
y_axis : { x : 0 , y : 0 , z : 1 } ,
z_axis : { x : 0 , y : - 1 , z : 0 }
}
} ) ` )
await expect ( u . codeLocator ) . toContainText ( ` const sketch003 = startSketchOn({
plane : {
origin : { x : 116.53 , y : 0 , z : 163.25 } ,
x_axis : { x : - 0.81 , y : 0 , z : 0.58 } ,
y_axis : { x : 0 , y : - 1 , z : 0 } ,
z_axis : { x : 0.58 , y : 0 , z : 0.81 }
}
} ) ` )
await expect ( u . codeLocator ) . toContainText ( ` const sketch002 = startSketchOn({
plane : {
origin : { x : - 91.74 , y : 0 , z : 80.89 } ,
x_axis : { x : - 0.66 , y : 0 , z : - 0.75 } ,
y_axis : { x : 0 , y : - 1 , z : 0 } ,
z_axis : { x : - 0.75 , y : 0 , z : 0.66 }
}
} ) ` )
// DELETE SOLID 2D
await page . mouse . click ( solid2d . x , solid2d . y )
await page . waitForTimeout ( 100 )
await expect ( page . locator ( '.cm-activeLine' ) ) . toHaveText (
'|> startProfileAt([23.24, 136.52], %)'
)
await u . clearCommandLogs ( )
await page . keyboard . press ( 'Backspace' )
await u . expectCmdLog ( '[data-message-type="execution-done"]' , 10 _000 )
await page . waitForTimeout ( 200 )
await expect ( u . codeLocator ) . not . toContainText (
` const sketch005 = startSketchOn({ `
)
} )
test ( "Deleting solid that the AST mod can't handle results in a toast message" , async ( {
page ,
} ) = > {
const u = await getUtils ( page )
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( [ - 79.26 , 95.04 ] , % )
| > line ( [ 112.54 , 127.64 ] , % , $seg02 )
| > line ( [ 170.36 , - 121.61 ] , % , $seg01 )
| > lineTo ( [ profileStartX ( % ) , profileStartY ( % ) ] , % )
| > close ( % )
const extrude001 = extrude ( 50 , sketch001 )
const launderExtrudeThroughVar = extrude001
const sketch002 = startSketchOn ( launderExtrudeThroughVar , seg02 )
| > startProfileAt ( [ - 100.54 , 16.99 ] , % )
| > line ( [ 0 , 20.03 ] , % )
| > line ( [ 62.61 , 0 ] , % , $seg03 )
| > lineTo ( [ profileStartX ( % ) , profileStartY ( % ) ] , % )
| > close ( % )
`
)
} , KCL_DEFAULT_LENGTH )
await page . setViewportSize ( { width : 1000 , height : 500 } )
await page . goto ( '/' )
await u . waitForAuthSkipAppStart ( )
await u . openDebugPanel ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' , 10 _000 )
await u . closeDebugPanel ( )
await u . openAndClearDebugPanel ( )
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_look_at' ,
vantage : { x : 1139.49 , y : - 7053 , z : 8597.31 } ,
center : { x : - 2206.68 , y : - 1298.36 , z : 60 } ,
up : { x : 0 , y : 0 , z : 1 } ,
} ,
} )
await page . waitForTimeout ( 100 )
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_get_settings' ,
} ,
} )
await page . waitForTimeout ( 100 )
// attempt delete
await page . mouse . click ( 930 , 139 )
await page . waitForTimeout ( 100 )
await expect ( page . locator ( '.cm-activeLine' ) ) . toHaveText (
'|> line([170.36, -121.61], %, $seg01)'
)
await u . clearCommandLogs ( )
await page . keyboard . press ( 'Backspace' )
await expect ( page . getByText ( 'Unable to delete part' ) ) . toBeVisible ( )
} )
2024-06-06 21:55:22 +10:00
test ( 'Hovering over 3d features highlights code' , async ( { page } ) = > {
const u = await getUtils ( page )
await page . addInitScript ( async ( KCL_DEFAULT_LENGTH ) = > {
localStorage . setItem (
'persistCode' ,
` const part001 = startSketchOn('XZ')
| > startProfileAt ( [ 20 , 0 ] , % )
| > line ( [ 7.13 , 4 + 0 ] , % )
| > angledLine ( { angle : 3 + 0 , length : 3.14 + 0 } , % )
| > lineTo ( [ 20.14 + 0 , - 0.14 + 0 ] , % )
| > xLineTo ( 29 + 0 , % )
2024-06-24 22:39:04 -07:00
| > yLine ( - 3.14 + 0 , % , $a )
2024-06-06 21:55:22 +10:00
| > xLine ( 1.63 , % )
| > angledLineOfXLength ( { angle : 3 + 0 , length : 3.14 } , % )
| > angledLineOfYLength ( { angle : 30 , length : 3 + 0 } , % )
| > angledLineToX ( { angle : 22.14 + 0 , to : 12 } , % )
| > angledLineToY ( { angle : 30 , to : 11.14 } , % )
| > angledLineThatIntersects ( {
angle : 3.14 ,
2024-06-24 22:39:04 -07:00
intersectTag : a ,
2024-06-06 21:55:22 +10:00
offset : 0
} , % )
| > tangentialArcTo ( [ 13.14 + 0 , 13.14 ] , % )
| > close ( % )
| > extrude ( 5 + 7 , % )
`
)
} , KCL_DEFAULT_LENGTH )
await page . setViewportSize ( { width : 1000 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-06-06 21:55:22 +10:00
await u . waitForAuthSkipAppStart ( )
2024-03-22 10:23:04 +11:00
2024-06-06 21:55:22 +10:00
// wait for execution done
await u . openDebugPanel ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await u . closeDebugPanel ( )
2024-03-22 10:23:04 +11:00
2024-06-06 21:55:22 +10:00
await u . openAndClearDebugPanel ( )
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_look_at' ,
vantage : { x : 0 , y : - 1250 , z : 580 } ,
center : { x : 0 , y : 0 , z : 0 } ,
up : { x : 0 , y : 0 , z : 1 } ,
} ,
} )
await page . waitForTimeout ( 100 )
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_get_settings' ,
} ,
} )
2024-03-22 10:23:04 +11:00
await page . waitForTimeout ( 100 )
2024-06-30 18:26:16 -07:00
await u . closeDebugPanel ( )
2024-03-22 10:23:04 +11:00
2024-06-06 21:55:22 +10:00
const extrusionTop : Coords2d = [ 800 , 240 ]
const flatExtrusionFace : Coords2d = [ 960 , 160 ]
const arc : Coords2d = [ 840 , 160 ]
const close : Coords2d = [ 720 , 200 ]
const nothing : Coords2d = [ 600 , 200 ]
2023-12-01 20:18:51 +11:00
2024-06-06 21:55:22 +10:00
await page . mouse . move ( nothing [ 0 ] , nothing [ 1 ] )
await page . mouse . click ( nothing [ 0 ] , nothing [ 1 ] )
2023-12-01 20:18:51 +11:00
2024-06-06 21:55:22 +10:00
await expect ( page . getByTestId ( 'hover-highlight' ) ) . not . toBeVisible ( )
await page . waitForTimeout ( 200 )
2023-11-28 21:23:20 +11:00
2024-06-06 21:55:22 +10:00
await page . mouse . move ( extrusionTop [ 0 ] , extrusionTop [ 1 ] )
2024-06-30 18:26:16 -07:00
await expect ( page . getByTestId ( 'hover-highlight' ) . first ( ) ) . toBeVisible ( )
2024-06-06 21:55:22 +10:00
await page . mouse . move ( nothing [ 0 ] , nothing [ 1 ] )
2024-06-30 18:26:16 -07:00
await expect ( page . getByTestId ( 'hover-highlight' ) . first ( ) ) . not . toBeVisible ( )
2024-02-11 12:59:00 +11:00
2024-06-06 21:55:22 +10:00
await page . mouse . move ( arc [ 0 ] , arc [ 1 ] )
2024-06-30 18:26:16 -07:00
await expect ( page . getByTestId ( 'hover-highlight' ) . first ( ) ) . toBeVisible ( )
2024-06-06 21:55:22 +10:00
await page . mouse . move ( nothing [ 0 ] , nothing [ 1 ] )
2024-06-30 18:26:16 -07:00
await expect ( page . getByTestId ( 'hover-highlight' ) . first ( ) ) . not . toBeVisible ( )
2023-11-28 21:23:20 +11:00
2024-06-06 21:55:22 +10:00
await page . mouse . move ( close [ 0 ] , close [ 1 ] )
2024-06-30 18:26:16 -07:00
await expect ( page . getByTestId ( 'hover-highlight' ) . first ( ) ) . toBeVisible ( )
2024-06-06 21:55:22 +10:00
await page . mouse . move ( nothing [ 0 ] , nothing [ 1 ] )
2024-06-30 18:26:16 -07:00
await expect ( page . getByTestId ( 'hover-highlight' ) . first ( ) ) . not . toBeVisible ( )
2023-11-28 21:23:20 +11:00
2024-06-06 21:55:22 +10:00
await page . mouse . move ( flatExtrusionFace [ 0 ] , flatExtrusionFace [ 1 ] )
2024-07-03 21:28:51 -07:00
await expect ( page . getByTestId ( 'hover-highlight' ) ) . toHaveCount ( 5 ) // multiple lines
2024-06-06 21:55:22 +10:00
await page . mouse . move ( nothing [ 0 ] , nothing [ 1 ] )
await page . waitForTimeout ( 100 )
2024-06-30 18:26:16 -07:00
await expect ( page . getByTestId ( 'hover-highlight' ) . first ( ) ) . not . toBeVisible ( )
2024-06-06 21:55:22 +10:00
} )
2024-06-21 13:20:42 +10:00
test ( "Extrude button should be disabled if there's no extrudable geometry when nothing is selected" , async ( {
page ,
} ) = > {
const u = await getUtils ( page )
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( [ 3.29 , 7.86 ] , % )
| > line ( [ 2.48 , 2.44 ] , % )
| > line ( [ 2.66 , 1.17 ] , % )
| > line ( [ 3.75 , 0.46 ] , % )
2024-06-24 22:39:04 -07:00
| > line ( [ 4.99 , - 0.46 ] , % , $seg01 )
2024-06-21 13:20:42 +10:00
| > line ( [ 3.3 , - 2.12 ] , % )
| > line ( [ 2.16 , - 3.33 ] , % )
| > line ( [ 0.85 , - 3.08 ] , % )
| > line ( [ - 0.18 , - 3.36 ] , % )
| > line ( [ - 3.86 , - 2.73 ] , % )
| > line ( [ - 17.67 , 0.85 ] , % )
| > close ( % )
const extrude001 = extrude ( 10 , sketch001 )
`
)
} )
await page . setViewportSize ( { width : 1000 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-06-21 13:20:42 +10:00
await u . waitForAuthSkipAppStart ( )
// wait for execution done
await u . openDebugPanel ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await u . closeDebugPanel ( )
const selectUnExtrudable = ( ) = >
2024-06-24 22:39:04 -07:00
page . getByText ( ` line([4.99, -0.46], %, $ seg01) ` ) . click ( )
2024-06-21 13:20:42 +10:00
const clickEmpty = ( ) = > page . mouse . click ( 700 , 460 )
await selectUnExtrudable ( )
// expect extrude button to be disabled
await expect ( page . getByRole ( 'button' , { name : 'Extrude' } ) ) . toBeDisabled ( )
await clickEmpty ( )
// expect active line to contain nothing
await expect ( page . locator ( '.cm-activeLine' ) ) . toHaveText ( '' )
// and extrude to still be disabled
await expect ( page . getByRole ( 'button' , { name : 'Extrude' } ) ) . toBeDisabled ( )
const codeToAdd = ` ${ await u . codeLocator . allInnerTexts ( ) }
2024-06-24 22:39:04 -07:00
const sketch002 = startSketchOn ( extrude001 , $seg01 )
2024-06-21 13:20:42 +10:00
| > startProfileAt ( [ - 12.94 , 6.6 ] , % )
| > line ( [ 2.45 , - 0.2 ] , % )
| > line ( [ - 2 , - 1.25 ] , % )
| > lineTo ( [ profileStartX ( % ) , profileStartY ( % ) ] , % )
| > close ( % )
`
await u . codeLocator . fill ( codeToAdd )
await selectUnExtrudable ( )
// expect extrude button to be disabled
await expect ( page . getByRole ( 'button' , { name : 'Extrude' } ) ) . toBeDisabled ( )
await clickEmpty ( )
await expect ( page . locator ( '.cm-activeLine' ) ) . toHaveText ( '' )
// there's not extrudable geometry, so button should be enabled
await expect (
page . getByRole ( 'button' , { name : 'Extrude' } )
) . not . toBeDisabled ( )
} )
2024-04-22 20:14:06 +10:00
2024-07-03 14:34:45 +10:00
const removeAfterFirstParenthesis = ( inputString : string ) = > {
const index = inputString . indexOf ( '(' )
if ( index !== - 1 ) {
return inputString . substring ( 0 , index )
}
return inputString // return the original string if '(' is not found
}
2024-06-06 21:55:22 +10:00
test ( 'Testing selections (and hovers) work on sketches when NOT in sketch mode' , async ( {
page ,
} ) = > {
const cases = [
{
pos : [ 694 , 185 ] ,
2024-06-24 22:39:04 -07:00
expectedCode : 'line([74.36, 130.4], %, $seg01)' ,
2024-06-06 21:55:22 +10:00
} ,
{
pos : [ 816 , 244 ] ,
2024-06-24 22:39:04 -07:00
expectedCode : 'angledLine([segAng(seg01, %), yo], %)' ,
2024-06-06 21:55:22 +10:00
} ,
{
pos : [ 1107 , 161 ] ,
expectedCode : 'tangentialArcTo([167.95, -28.85], %)' ,
} ,
] as const
await page . addInitScript (
async ( { cases } ) = > {
localStorage . setItem (
'persistCode' ,
` const yo = 79
const part001 = startSketchOn ( 'XZ' )
| > startProfileAt ( [ - 7.54 , - 26.74 ] , % )
| > $ { cases [ 0 ] . expectedCode }
| > line ( [ - 3.19 , - 138.43 ] , % )
| > $ { cases [ 1 ] . expectedCode }
| > line ( [ 41.19 , 28.97 + 5 ] , % )
| > $ { cases [ 2 ] . expectedCode } `
)
} ,
{ cases }
)
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-06-06 21:55:22 +10:00
await u . waitForAuthSkipAppStart ( )
await u . openAndClearDebugPanel ( )
2023-11-28 21:23:20 +11:00
2024-06-06 21:55:22 +10:00
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_look_at' ,
vantage : { x : - 449 , y : - 7503 , z : 99 } ,
center : { x : - 449 , y : 0 , z : 99 } ,
up : { x : 0 , y : 0 , z : 1 } ,
} ,
} )
await u . waitForCmdReceive ( 'default_camera_look_at' )
await u . clearAndCloseDebugPanel ( )
// end setup, now test hover and selects
for ( const { pos , expectedCode } of cases ) {
// hover over segment, check it's content
await page . mouse . move ( pos [ 0 ] , pos [ 1 ] , { steps : 5 } )
await expect ( page . getByTestId ( 'hover-highlight' ) . first ( ) ) . toBeVisible ( )
await expect ( page . getByTestId ( 'hover-highlight' ) . first ( ) ) . toHaveText (
2024-07-03 21:28:51 -07:00
expectedCode
2024-06-06 21:55:22 +10:00
)
// hover over segment, click it and check the cursor has move to the right place
await page . mouse . click ( pos [ 0 ] , pos [ 1 ] )
await expect ( page . locator ( '.cm-activeLine' ) ) . toHaveText (
'|> ' + expectedCode
)
}
} )
2024-06-28 14:40:59 +10:00
test ( "Hovering and selection of extruded faces works, and is not overridden shortly after user's click" , async ( {
page ,
} ) = > {
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( [ - 79.26 , 95.04 ] , % )
| > line ( [ 112.54 , 127.64 ] , % )
| > line ( [ 170.36 , - 121.61 ] , % , $seg01 )
| > lineTo ( [ profileStartX ( % ) , profileStartY ( % ) ] , % )
| > close ( % )
const extrude001 = extrude ( 50 , sketch001 )
`
)
} )
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-06-28 14:40:59 +10:00
await u . waitForAuthSkipAppStart ( )
await u . openAndClearDebugPanel ( )
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_look_at' ,
vantage : { x : 6615 , y : - 9505 , z : 10344 } ,
center : { x : 1579 , y : - 635 , z : 4035 } ,
up : { x : 0 , y : 0 , z : 1 } ,
} ,
} )
await u . waitForCmdReceive ( 'default_camera_look_at' )
await u . clearAndCloseDebugPanel ( )
await page . waitForTimeout ( 1000 )
let noHoverColor : [ number , number , number ] = [ 82 , 82 , 82 ]
let hoverColor : [ number , number , number ] = [ 116 , 116 , 116 ]
let selectColor : [ number , number , number ] = [ 144 , 148 , 97 ]
const extrudeWall = { x : 670 , y : 275 }
const extrudeText = ` line([170.36, -121.61], %, $ seg01) `
const cap = { x : 594 , y : 283 }
const capText = ` startProfileAt([-79.26, 95.04], %) `
const nothing = { x : 946 , y : 229 }
expect ( await u . getGreatestPixDiff ( extrudeWall , noHoverColor ) ) . toBeLessThan (
5
)
await page . mouse . move ( nothing . x , nothing . y )
await page . waitForTimeout ( 100 )
await page . mouse . move ( extrudeWall . x , extrudeWall . y )
2024-06-30 18:26:16 -07:00
await expect ( page . getByTestId ( 'hover-highlight' ) . first ( ) ) . toBeVisible ( )
await expect ( page . getByTestId ( 'hover-highlight' ) . first ( ) ) . toContainText (
removeAfterFirstParenthesis ( extrudeText )
)
2024-06-28 14:40:59 +10:00
await page . waitForTimeout ( 200 )
await expect (
await u . getGreatestPixDiff ( extrudeWall , hoverColor )
) . toBeLessThan ( 5 )
await page . mouse . click ( extrudeWall . x , extrudeWall . y )
await expect ( page . locator ( '.cm-activeLine' ) ) . toHaveText ( ` |> ${ extrudeText } ` )
await page . waitForTimeout ( 200 )
await expect (
await u . getGreatestPixDiff ( extrudeWall , selectColor )
) . toBeLessThan ( 5 )
await page . waitForTimeout ( 1000 )
// check color stays there, i.e. not overridden (this was a bug previously)
await expect (
await u . getGreatestPixDiff ( extrudeWall , selectColor )
) . toBeLessThan ( 5 )
await page . mouse . move ( nothing . x , nothing . y )
await page . waitForTimeout ( 300 )
await expect ( page . getByTestId ( 'hover-highlight' ) ) . not . toBeVisible ( )
// because of shading, color is not exact everywhere on the face
noHoverColor = [ 104 , 104 , 104 ]
hoverColor = [ 134 , 134 , 134 ]
selectColor = [ 158 , 162 , 110 ]
await expect ( await u . getGreatestPixDiff ( cap , noHoverColor ) ) . toBeLessThan ( 5 )
await page . mouse . move ( cap . x , cap . y )
2024-06-30 18:26:16 -07:00
await expect ( page . getByTestId ( 'hover-highlight' ) . first ( ) ) . toBeVisible ( )
await expect ( page . getByTestId ( 'hover-highlight' ) . first ( ) ) . toContainText (
removeAfterFirstParenthesis ( capText )
)
2024-06-28 14:40:59 +10:00
await page . waitForTimeout ( 200 )
await expect ( await u . getGreatestPixDiff ( cap , hoverColor ) ) . toBeLessThan ( 5 )
await page . mouse . click ( cap . x , cap . y )
await expect ( page . locator ( '.cm-activeLine' ) ) . toHaveText ( ` |> ${ capText } ` )
await page . waitForTimeout ( 200 )
await expect ( await u . getGreatestPixDiff ( cap , selectColor ) ) . toBeLessThan ( 5 )
await page . waitForTimeout ( 1000 )
// check color stays there, i.e. not overridden (this was a bug previously)
await expect ( await u . getGreatestPixDiff ( cap , selectColor ) ) . toBeLessThan ( 5 )
} )
2024-07-03 14:34:45 +10:00
test ( "Various pipe expressions should and shouldn't allow edit and or extrude" , async ( {
page ,
} ) = > {
const u = await getUtils ( page )
const selectionsSnippets = {
extrudeAndEditBlocked : '|> startProfileAt([10.81, 32.99], %)' ,
extrudeAndEditBlockedInFunction : '|> startProfileAt(pos, %)' ,
extrudeAndEditAllowed : '|> startProfileAt([15.72, 4.7], %)' ,
editOnly : '|> startProfileAt([15.79, -14.6], %)' ,
}
await page . addInitScript (
async ( {
extrudeAndEditBlocked ,
extrudeAndEditBlockedInFunction ,
extrudeAndEditAllowed ,
editOnly ,
} : any ) = > {
localStorage . setItem (
'persistCode' ,
` const part001 = startSketchOn('XZ')
$ { extrudeAndEditBlocked }
| > line ( [ 25.96 , 2.93 ] , % )
| > line ( [ 5.25 , - 5.72 ] , % )
| > line ( [ - 2.01 , - 10.35 ] , % )
| > line ( [ - 27.65 , - 2.78 ] , % )
| > close ( % )
| > extrude ( 5 , % )
const sketch002 = startSketchOn ( 'XZ' )
$ { extrudeAndEditAllowed }
| > line ( [ 10.32 , 6.47 ] , % )
| > line ( [ 9.71 , - 6.16 ] , % )
| > line ( [ - 3.08 , - 9.86 ] , % )
| > line ( [ - 12.02 , - 1.54 ] , % )
| > close ( % )
const sketch003 = startSketchOn ( 'XZ' )
$ { editOnly }
| > line ( [ 27.55 , - 1.65 ] , % )
| > line ( [ 4.95 , - 8 ] , % )
| > line ( [ - 20.38 , - 10.12 ] , % )
| > line ( [ - 15.79 , 17.08 ] , % )
fn yohey = ( pos ) = > {
const sketch004 = startSketchOn ( 'XZ' )
$ { extrudeAndEditBlockedInFunction }
| > line ( [ 27.55 , - 1.65 ] , % )
| > line ( [ 4.95 , - 10.53 ] , % )
| > line ( [ - 20.38 , - 8 ] , % )
| > line ( [ - 15.79 , 17.08 ] , % )
return ''
}
yohey ( [ 15.79 , - 34.6 ] )
`
)
} ,
selectionsSnippets
)
await page . setViewportSize ( { width : 1200 , height : 1000 } )
await u . waitForAuthSkipAppStart ( )
// wait for execution done
await u . openDebugPanel ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await u . closeDebugPanel ( )
// wait for start sketch as a proxy for the stream being ready
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . not . toBeDisabled ( )
await page . getByText ( selectionsSnippets . extrudeAndEditBlocked ) . click ( )
await expect ( page . getByRole ( 'button' , { name : 'Extrude' } ) ) . toBeDisabled ( )
await page . getByText ( selectionsSnippets . extrudeAndEditAllowed ) . click ( )
await expect (
page . getByRole ( 'button' , { name : 'Extrude' } )
) . not . toBeDisabled ( )
await expect (
page . getByRole ( 'button' , { name : 'Edit Sketch' } )
) . not . toBeDisabled ( )
await page . getByText ( selectionsSnippets . editOnly ) . click ( )
await expect ( page . getByRole ( 'button' , { name : 'Extrude' } ) ) . toBeDisabled ( )
await expect (
page . getByRole ( 'button' , { name : 'Edit Sketch' } )
) . not . toBeDisabled ( )
await page
. getByText ( selectionsSnippets . extrudeAndEditBlockedInFunction )
. click ( )
await expect ( page . getByRole ( 'button' , { name : 'Extrude' } ) ) . toBeDisabled ( )
await expect (
page . getByRole ( 'button' , { name : 'Edit Sketch' } )
) . not . toBeVisible ( )
// selecting an editable sketch but clicking "start sketch" should start a new sketch and not edit the existing one
await page . getByText ( selectionsSnippets . extrudeAndEditAllowed ) . click ( )
await page . getByRole ( 'button' , { name : 'Start Sketch' } ) . click ( )
await page . waitForTimeout ( 200 )
await page . getByTestId ( 'KCL Code' ) . click ( )
await page . waitForTimeout ( 200 )
await page . mouse . click ( 734 , 134 )
await page . waitForTimeout ( 100 )
await page . getByTestId ( 'KCL Code' ) . click ( )
// expect main content to contain `sketch005` i.e. started a new sketch
await page . waitForTimeout ( 300 )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
/sketch001 = startSketchOn\('XZ'\)/
)
} )
test ( 'Deselecting line tool should mean nothing happens on click' , async ( {
page ,
} ) = > {
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
await u . openDebugPanel ( )
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . not . toBeDisabled ( )
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . toBeVisible ( )
// click on "Start Sketch" button
await u . clearCommandLogs ( )
await u . doAndWaitForImageDiff (
( ) = > page . getByRole ( 'button' , { name : 'Start Sketch' } ) . click ( ) ,
200
)
await page . mouse . click ( 700 , 200 )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
` const sketch001 = startSketchOn('XZ') `
)
await page . waitForTimeout ( 600 )
let previousCodeContent = await page . locator ( '.cm-content' ) . innerText ( )
// deselect the line tool by clicking it
await page . getByRole ( 'button' , { name : 'Line' } ) . click ( )
await page . mouse . click ( 700 , 200 )
await page . waitForTimeout ( 100 )
await page . mouse . click ( 700 , 250 )
await page . waitForTimeout ( 100 )
await page . mouse . click ( 750 , 200 )
await page . waitForTimeout ( 100 )
// expect no change
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( previousCodeContent )
// select line tool again
await page . getByRole ( 'button' , { name : 'Line' } ) . click ( )
await u . closeDebugPanel ( )
// line tool should work as expected again
await page . mouse . click ( 700 , 200 )
await expect ( page . locator ( '.cm-content' ) ) . not . toHaveText (
previousCodeContent
)
previousCodeContent = await page . locator ( '.cm-content' ) . innerText ( )
await page . waitForTimeout ( 100 )
await page . mouse . click ( 700 , 300 )
await expect ( page . locator ( '.cm-content' ) ) . not . toHaveText (
previousCodeContent
)
previousCodeContent = await page . locator ( '.cm-content' ) . innerText ( )
await page . waitForTimeout ( 100 )
await page . mouse . click ( 750 , 300 )
await expect ( page . locator ( '.cm-content' ) ) . not . toHaveText (
previousCodeContent
)
previousCodeContent = await page . locator ( '.cm-content' ) . innerText ( )
} )
2023-11-28 21:23:20 +11:00
} )
2023-12-06 14:44:13 -05:00
2024-04-02 10:29:34 -04:00
test . describe ( 'Command bar tests' , ( ) = > {
2024-07-03 14:34:45 +10:00
test ( 'Extrude from command bar selects extrude line after' , async ( {
page ,
} ) = > {
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const sketch001 = startSketchOn('XY')
| > startProfileAt ( [ - 10 , - 10 ] , % )
| > line ( [ 20 , 0 ] , % )
| > line ( [ 0 , 20 ] , % )
| > xLine ( - 20 , % )
| > close ( % )
`
)
} )
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
await u . openDebugPanel ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await u . closeDebugPanel ( )
// Click the line of code for xLine.
await page . getByText ( ` close(%) ` ) . click ( ) // TODO remove this and reinstate // await topHorzSegmentClick()
await page . waitForTimeout ( 100 )
await page . getByRole ( 'button' , { name : 'Extrude' } ) . click ( )
await page . waitForTimeout ( 100 )
await page . keyboard . press ( 'Enter' )
await page . waitForTimeout ( 100 )
await page . keyboard . press ( 'Enter' )
await page . waitForTimeout ( 100 )
await expect ( page . locator ( '.cm-activeLine' ) ) . toHaveText (
` const extrude001 = extrude( ${ KCL_DEFAULT_LENGTH } , sketch001) `
)
} )
2024-04-02 10:29:34 -04:00
test ( 'Command bar works and can change a setting' , async ( { page } ) = > {
2024-06-29 18:10:07 -07:00
const u = await getUtils ( page )
2024-04-02 10:29:34 -04:00
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
await u . waitForAuthSkipAppStart ( )
2024-04-02 10:29:34 -04:00
2024-06-24 11:45:40 -04:00
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . not . toBeDisabled ( )
2024-04-02 10:29:34 -04:00
// First try opening the command bar and closing it
await page
2024-05-08 09:57:16 -04:00
. getByRole ( 'button' , { name : 'Commands' , exact : false } )
2024-04-02 10:29:34 -04:00
. or ( page . getByRole ( 'button' , { name : '⌘K' } ) )
. click ( )
2024-06-24 11:45:40 -04:00
2024-06-28 14:40:59 +10:00
let cmdSearchBar = page . getByPlaceholder ( 'Search commands' )
2024-04-02 10:29:34 -04:00
await expect ( cmdSearchBar ) . toBeVisible ( )
await page . keyboard . press ( 'Escape' )
2024-06-28 14:40:59 +10:00
cmdSearchBar = page . getByPlaceholder ( 'Search commands' )
2024-04-02 10:29:34 -04:00
await expect ( cmdSearchBar ) . not . toBeVisible ( )
// Now try the same, but with the keyboard shortcut, check focus
2024-07-03 15:26:04 -07:00
await page . keyboard . press ( 'Meta+K' )
2024-06-28 14:40:59 +10:00
cmdSearchBar = page . getByPlaceholder ( 'Search commands' )
2024-04-02 10:29:34 -04:00
await expect ( cmdSearchBar ) . toBeVisible ( )
await expect ( cmdSearchBar ) . toBeFocused ( )
// Try typing in the command bar
await page . keyboard . type ( 'theme' )
const themeOption = page . getByRole ( 'option' , {
name : 'Settings · app · theme' ,
} )
await expect ( themeOption ) . toBeVisible ( )
await themeOption . click ( )
const themeInput = page . getByPlaceholder ( 'Select an option' )
await expect ( themeInput ) . toBeVisible ( )
await expect ( themeInput ) . toBeFocused ( )
// Select dark theme
await page . keyboard . press ( 'ArrowDown' )
await page . keyboard . press ( 'ArrowDown' )
2024-05-20 20:52:33 -07:00
await page . keyboard . press ( 'ArrowDown' )
await expect ( page . getByRole ( 'option' , { name : 'system' } ) ) . toHaveAttribute (
'data-headlessui-state' ,
'active'
)
await page . keyboard . press ( 'Enter' )
// Check the toast appeared
await expect (
page . getByText ( ` Set theme to "system" for this project ` )
) . toBeVisible ( )
// Check that the theme changed
await expect ( page . locator ( 'body' ) ) . not . toHaveClass ( ` body-bg dark ` )
} )
test ( 'Command bar keybinding works from code editor and can change a setting' , async ( {
page ,
} ) = > {
2024-06-29 18:10:07 -07:00
const u = await getUtils ( page )
2024-05-20 20:52:33 -07:00
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
await u . waitForAuthSkipAppStart ( )
2024-05-20 20:52:33 -07:00
2024-06-24 11:45:40 -04:00
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . not . toBeDisabled ( )
2024-05-20 20:52:33 -07:00
// Put the cursor in the code editor
2024-06-07 12:31:22 +10:00
await page . locator ( '.cm-content' ) . click ( )
2024-05-20 20:52:33 -07:00
// Now try the same, but with the keyboard shortcut, check focus
2024-07-03 15:26:04 -07:00
await page . keyboard . press ( 'Meta+K' )
2024-06-24 11:45:40 -04:00
let cmdSearchBar = page . getByPlaceholder ( 'Search commands' )
2024-05-20 20:52:33 -07:00
await expect ( cmdSearchBar ) . toBeVisible ( )
await expect ( cmdSearchBar ) . toBeFocused ( )
// Try typing in the command bar
await page . keyboard . type ( 'theme' )
const themeOption = page . getByRole ( 'option' , {
name : 'Settings · app · theme' ,
} )
await expect ( themeOption ) . toBeVisible ( )
await themeOption . click ( )
const themeInput = page . getByPlaceholder ( 'Select an option' )
await expect ( themeInput ) . toBeVisible ( )
await expect ( themeInput ) . toBeFocused ( )
// Select dark theme
await page . keyboard . press ( 'ArrowDown' )
await page . keyboard . press ( 'ArrowDown' )
2024-04-02 10:29:34 -04:00
await page . keyboard . press ( 'ArrowDown' )
await expect ( page . getByRole ( 'option' , { name : 'system' } ) ) . toHaveAttribute (
'data-headlessui-state' ,
'active'
Command bar: add extrude command, nonlinear editing, etc (#1204)
* Tweak toaster look and feel
* Add icons, tweak plus icon names
* Rename commandBarMeta to commandBarConfig
* Refactor command bar, add support for icons
* Create a tailwind plugin for aria-pressed button state
* Remove overlay from behind command bar
* Clean up toolbar
* Button and other style tweaks
* Icon tweaks follow-up: make old icons work with new sizing
* Delete unused static icons
* More CSS tweaks
* Small CSS tweak to project sidebar
* Add command bar E2E test
* fumpt
* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)
* fix typo in a comment
* Fix icon padding (built version only)
* Update onboarding and warning banner icons padding
* Misc minor style fixes
* Get Extrude opening and canceling from command bar
* Iconography tweaks
* Get extrude kind of working
* Refactor command bar config types and organization
* Move command bar configs to be co-located with each other
* Start building a state machine for the command bar
* Start converting command bar to state machine
* Add support for multiple args, confirmation step
* Submission behavior, hotkeys, code organization
* Add new test for extruding from command bar
* Polish step back and selection hotkeys, CSS tweaks
* Loading style tweaks
* Validate selection inputs, polish UX of args re-editing
* Prevent submission with multiple selection on singlular arg
* Remove stray console logs
* Tweak test, CSS nit, remove extrude "result" argument
* Fix linting warnings
* Show Ctrl+/ instead of ⌘K on all platforms but Mac
* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)
* Add "Enter sketch" to command bar
* fix command bar test
* Fix flaky cmd bar extrude test by waiting for engine select response
* Cover both button labels '⌘K' and 'Ctrl+/' in test
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-12-13 12:49:01 -05:00
)
2024-04-02 10:29:34 -04:00
await page . keyboard . press ( 'Enter' )
// Check the toast appeared
await expect (
page . getByText ( ` Set theme to "system" for this project ` )
) . toBeVisible ( )
// Check that the theme changed
await expect ( page . locator ( 'body' ) ) . not . toHaveClass ( ` body-bg dark ` )
Command bar: add extrude command, nonlinear editing, etc (#1204)
* Tweak toaster look and feel
* Add icons, tweak plus icon names
* Rename commandBarMeta to commandBarConfig
* Refactor command bar, add support for icons
* Create a tailwind plugin for aria-pressed button state
* Remove overlay from behind command bar
* Clean up toolbar
* Button and other style tweaks
* Icon tweaks follow-up: make old icons work with new sizing
* Delete unused static icons
* More CSS tweaks
* Small CSS tweak to project sidebar
* Add command bar E2E test
* fumpt
* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)
* fix typo in a comment
* Fix icon padding (built version only)
* Update onboarding and warning banner icons padding
* Misc minor style fixes
* Get Extrude opening and canceling from command bar
* Iconography tweaks
* Get extrude kind of working
* Refactor command bar config types and organization
* Move command bar configs to be co-located with each other
* Start building a state machine for the command bar
* Start converting command bar to state machine
* Add support for multiple args, confirmation step
* Submission behavior, hotkeys, code organization
* Add new test for extruding from command bar
* Polish step back and selection hotkeys, CSS tweaks
* Loading style tweaks
* Validate selection inputs, polish UX of args re-editing
* Prevent submission with multiple selection on singlular arg
* Remove stray console logs
* Tweak test, CSS nit, remove extrude "result" argument
* Fix linting warnings
* Show Ctrl+/ instead of ⌘K on all platforms but Mac
* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)
* Add "Enter sketch" to command bar
* fix command bar test
* Fix flaky cmd bar extrude test by waiting for engine select response
* Cover both button labels '⌘K' and 'Ctrl+/' in test
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-12-13 12:49:01 -05:00
} )
2024-04-11 13:37:49 -04:00
test ( 'Can extrude from the command bar' , async ( { page } ) = > {
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
2024-04-15 12:04:17 -04:00
` const distance = sqrt(20)
2024-06-04 13:57:01 -04:00
const sketch001 = startSketchOn ( 'XZ' )
2024-05-07 20:01:52 -04:00
| > startProfileAt ( [ - 6.95 , 10.98 ] , % )
| > line ( [ 25.1 , 0.41 ] , % )
| > line ( [ 0.73 , - 20.93 ] , % )
| > line ( [ - 23.44 , 0.52 ] , % )
| > close ( % )
`
2024-04-11 13:37:49 -04:00
)
} )
2024-04-02 10:29:34 -04:00
2024-05-23 02:20:40 -07:00
const u = await getUtils ( page )
2024-04-02 10:29:34 -04:00
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-04-02 10:29:34 -04:00
await u . waitForAuthSkipAppStart ( )
// Make sure the stream is up
await u . openDebugPanel ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
2024-03-02 03:22:04 +11:00
2024-04-02 10:29:34 -04:00
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . not . toBeDisabled ( )
2024-04-15 12:04:17 -04:00
await u . clearCommandLogs ( )
await page . getByRole ( 'button' , { name : 'Extrude' } ) . isEnabled ( )
2024-04-02 10:29:34 -04:00
let cmdSearchBar = page . getByPlaceholder ( 'Search commands' )
2024-07-03 15:26:04 -07:00
await page . keyboard . press ( 'Meta+K' )
2024-04-02 10:29:34 -04:00
await expect ( cmdSearchBar ) . toBeVisible ( )
// Search for extrude command and choose it
await page . getByRole ( 'option' , { name : 'Extrude' } ) . click ( )
2024-05-07 20:01:52 -04:00
// Assert that we're on the selection step
await expect ( page . getByRole ( 'button' , { name : 'selection' } ) ) . toBeDisabled ( )
// Select a face
await page . mouse . move ( 700 , 200 )
await page . mouse . click ( 700 , 200 )
2024-04-02 10:29:34 -04:00
// Assert that we're on the distance step
await expect ( page . getByRole ( 'button' , { name : 'distance' } ) ) . toBeDisabled ( )
// Assert that the an alternative variable name is chosen,
// since the default variable name is already in use (distance)
await page . getByRole ( 'button' , { name : 'Create new variable' } ) . click ( )
await expect ( page . getByPlaceholder ( 'Variable name' ) ) . toHaveValue (
'distance001'
)
2024-04-15 12:04:17 -04:00
const continueButton = page . getByRole ( 'button' , { name : 'Continue' } )
const submitButton = page . getByRole ( 'button' , { name : 'Submit command' } )
await continueButton . click ( )
2024-04-02 10:29:34 -04:00
// Review step and argument hotkeys
2024-04-15 12:04:17 -04:00
await expect ( submitButton ) . toBeEnabled ( )
2024-04-02 10:29:34 -04:00
await page . keyboard . press ( 'Backspace' )
2024-04-15 12:04:17 -04:00
// Assert we're back on the distance step
2024-04-02 10:29:34 -04:00
await expect (
2024-05-17 10:29:04 -04:00
page . getByRole ( 'button' , { name : 'Distance 5' , exact : false } )
2024-04-02 10:29:34 -04:00
) . toBeDisabled ( )
2024-04-15 12:04:17 -04:00
await continueButton . click ( )
await submitButton . click ( )
2024-04-02 10:29:34 -04:00
// Check that the code was updated
2024-04-15 12:04:17 -04:00
await u . waitForCmdReceive ( 'extrude' )
2024-04-02 10:29:34 -04:00
// Unfortunately this indentation seems to matter for the test
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
` const distance = sqrt(20)
2024-05-17 10:29:04 -04:00
const distance001 = $ { KCL_DEFAULT_LENGTH }
2024-06-04 13:57:01 -04:00
const sketch001 = startSketchOn ( 'XZ' )
2024-05-07 20:01:52 -04:00
| > startProfileAt ( [ - 6.95 , 10.98 ] , % )
2024-04-02 10:29:34 -04:00
| > line ( [ 25.1 , 0.41 ] , % )
2024-05-07 20:01:52 -04:00
| > line ( [ 0.73 , - 20.93 ] , % )
2024-04-02 10:29:34 -04:00
| > line ( [ - 23.44 , 0.52 ] , % )
| > close ( % )
2024-06-04 13:57:01 -04:00
const extrude001 = extrude ( distance001 , sketch001 ) ` .replace(
/(\r\n|\n|\r)/gm ,
''
) // remove newlines
2024-04-02 10:29:34 -04:00
)
} )
Command bar: add extrude command, nonlinear editing, etc (#1204)
* Tweak toaster look and feel
* Add icons, tweak plus icon names
* Rename commandBarMeta to commandBarConfig
* Refactor command bar, add support for icons
* Create a tailwind plugin for aria-pressed button state
* Remove overlay from behind command bar
* Clean up toolbar
* Button and other style tweaks
* Icon tweaks follow-up: make old icons work with new sizing
* Delete unused static icons
* More CSS tweaks
* Small CSS tweak to project sidebar
* Add command bar E2E test
* fumpt
* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)
* fix typo in a comment
* Fix icon padding (built version only)
* Update onboarding and warning banner icons padding
* Misc minor style fixes
* Get Extrude opening and canceling from command bar
* Iconography tweaks
* Get extrude kind of working
* Refactor command bar config types and organization
* Move command bar configs to be co-located with each other
* Start building a state machine for the command bar
* Start converting command bar to state machine
* Add support for multiple args, confirmation step
* Submission behavior, hotkeys, code organization
* Add new test for extruding from command bar
* Polish step back and selection hotkeys, CSS tweaks
* Loading style tweaks
* Validate selection inputs, polish UX of args re-editing
* Prevent submission with multiple selection on singlular arg
* Remove stray console logs
* Tweak test, CSS nit, remove extrude "result" argument
* Fix linting warnings
* Show Ctrl+/ instead of ⌘K on all platforms but Mac
* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)
* Add "Enter sketch" to command bar
* fix command bar test
* Fix flaky cmd bar extrude test by waiting for engine select response
* Cover both button labels '⌘K' and 'Ctrl+/' in test
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-12-13 12:49:01 -05:00
} )
2024-02-11 12:59:00 +11:00
2024-07-03 14:34:45 +10:00
test . describe ( 'Regression tests' , ( ) = > {
// bugs we found that don't fit neatly into other categories
test ( 'executes on load' , async ( { page } ) = > {
const u = await getUtils ( page )
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const sketch001 = startSketchOn('-XZ')
| > startProfileAt ( [ - 6.95 , 4.98 ] , % )
| > line ( [ 25.1 , 0.41 ] , % )
| > line ( [ 0.73 , - 14.93 ] , % )
| > line ( [ - 23.44 , 0.52 ] , % ) `
)
} )
await page . setViewportSize ( { width : 1000 , height : 500 } )
2024-02-11 12:59:00 +11:00
2024-07-03 14:34:45 +10:00
await u . waitForAuthSkipAppStart ( )
2024-02-11 12:59:00 +11:00
2024-07-03 14:34:45 +10:00
// expand variables section
const variablesTabButton = page . getByRole ( 'tab' , {
name : 'Variables' ,
exact : false ,
} )
await variablesTabButton . click ( )
// can find sketch001 in the variables summary (pretty-json-container, makes sure we're not looking in the code editor)
// sketch001 only shows up in the variables summary if it's been executed
await page . waitForFunction ( ( ) = > {
const variablesElement = document . querySelector (
'.pretty-json-container'
) as HTMLDivElement
return variablesElement . innerHTML . includes ( 'sketch001' )
} )
await expect (
page . locator ( '.pretty-json-container >> text=sketch001' )
) . toBeVisible ( )
} )
2024-02-11 12:59:00 +11:00
2024-07-03 14:34:45 +10:00
test ( 're-executes' , async ( { page } ) = > {
const u = await getUtils ( page )
await page . addInitScript ( async ( ) = > {
localStorage . setItem ( 'persistCode' , ` const myVar = 5 ` )
} )
await page . setViewportSize ( { width : 1000 , height : 500 } )
2024-02-11 12:59:00 +11:00
2024-07-03 14:34:45 +10:00
await u . waitForAuthSkipAppStart ( )
2024-02-11 12:59:00 +11:00
2024-07-03 14:34:45 +10:00
const variablesTabButton = page . getByRole ( 'tab' , {
name : 'Variables' ,
exact : false ,
} )
await variablesTabButton . click ( )
// expect to see "myVar:5"
await expect (
page . locator ( '.pretty-json-container >> text=myVar:5' )
) . toBeVisible ( )
2024-02-11 12:59:00 +11:00
2024-07-03 14:34:45 +10:00
// change 5 to 67
await page . getByText ( 'const myVar' ) . click ( )
await page . keyboard . press ( 'End' )
await page . keyboard . press ( 'Backspace' )
await page . keyboard . type ( '67' )
2024-02-11 12:59:00 +11:00
2024-07-03 14:34:45 +10:00
await expect (
page . locator ( '.pretty-json-container >> text=myVar:67' )
) . toBeVisible ( )
} )
test ( 'ProgramMemory can be serialised' , async ( { page } ) = > {
const u = await getUtils ( page )
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const part = startSketchOn('XY')
| > startProfileAt ( [ 0 , 0 ] , % )
| > line ( [ 0 , 1 ] , % )
| > line ( [ 1 , 0 ] , % )
| > line ( [ 0 , - 1 ] , % )
| > close ( % )
| > extrude ( 1 , % )
| > patternLinear3d ( {
axis : [ 1 , 0 , 1 ] ,
repetitions : 3 ,
distance : 6
} , % ) `
)
} )
await page . setViewportSize ( { width : 1000 , height : 500 } )
2024-02-11 12:59:00 +11:00
2024-07-03 14:34:45 +10:00
const messages : string [ ] = [ ]
2024-02-11 12:59:00 +11:00
2024-07-03 14:34:45 +10:00
// Listen for all console events and push the message text to an array
page . on ( 'console' , ( message ) = > messages . push ( message . text ( ) ) )
await u . waitForAuthSkipAppStart ( )
2024-02-11 12:59:00 +11:00
2024-07-03 14:34:45 +10:00
// wait for execution done
await u . openDebugPanel ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
2024-04-22 20:14:06 +10:00
2024-07-03 14:34:45 +10:00
const forbiddenMessages = [ 'cannot serialize tagged newtype variant' ]
forbiddenMessages . forEach ( ( forbiddenMessage ) = > {
messages . forEach ( ( message ) = > {
expect ( message ) . not . toContain ( forbiddenMessage )
} )
} )
} )
test ( 'ensure the Zoo logo is not a link in browser app' , async ( { page } ) = > {
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1000 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
2024-02-11 12:59:00 +11:00
2024-07-03 14:34:45 +10:00
const zooLogo = page . locator ( '[data-testid="app-logo"]' )
// Make sure it's not a link
await expect ( zooLogo ) . not . toHaveAttribute ( 'href' )
} )
2024-07-03 22:06:52 -07:00
test ( 'Position _ Is Out Of Range... regression test' , async ( { page } ) = > {
const u = await getUtils ( page )
// const PUR = 400 / 37.5 //pixeltoUnitRatio
await page . setViewportSize ( { width : 1200 , height : 500 } )
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const exampleSketch = startSketchOn("XZ")
2024-07-03 14:34:45 +10:00
| > startProfileAt ( [ 0 , 0 ] , % )
| > angledLine ( { angle : 50 , length : 45 } , % )
| > yLineTo ( 0 , % )
| > close ( % )
| >
const example = extrude ( 5 , exampleSketch )
shell ( { faces : [ 'end' ] , thickness : 0.25 } , exampleSketch ) `
2024-07-03 22:06:52 -07:00
)
} )
2024-02-11 12:59:00 +11:00
2024-07-05 05:42:54 +10:00
await page . goto ( '/' )
await u . waitForPageLoad ( )
2024-02-11 12:59:00 +11:00
2024-07-03 22:06:52 -07:00
// error in guter
await expect ( page . locator ( '.cm-lint-marker-error' ) ) . toBeVisible ( )
2024-07-05 05:42:54 +10:00
await page . waitForTimeout ( 200 )
// expect it still to be there (sometimes it just clears for a bit?)
await expect ( page . locator ( '.cm-lint-marker-error' ) ) . toBeVisible ( {
timeout : 10_000 ,
} )
2024-02-11 15:08:54 -08:00
2024-07-03 22:06:52 -07:00
// error text on hover
await page . hover ( '.cm-lint-marker-error' )
await expect ( page . getByText ( 'Unexpected token' ) . first ( ) ) . toBeVisible ( )
2024-06-29 18:10:07 -07:00
2024-07-03 22:06:52 -07:00
// Okay execution finished, let's start editing text below the error.
await u . codeLocator . click ( )
// Go to the end of the editor
// This bug happens when there is a diagnostic in the editor and you try to
// edit text below it.
// Or delete a huge chunk of text and then try to edit below it.
await page . keyboard . press ( 'End' )
await page . keyboard . down ( 'Shift' )
await page . keyboard . press ( 'ArrowUp' )
await page . keyboard . press ( 'ArrowUp' )
await page . keyboard . press ( 'ArrowUp' )
await page . keyboard . press ( 'ArrowUp' )
await page . keyboard . press ( 'ArrowUp' )
2024-07-05 05:42:54 +10:00
await page . keyboard . press ( 'End' )
2024-07-03 22:06:52 -07:00
await page . keyboard . up ( 'Shift' )
await page . keyboard . press ( 'Backspace' )
await expect ( page . locator ( '.cm-lint-marker-error' ) ) . not . toBeVisible ( )
2024-02-11 15:08:54 -08:00
2024-07-03 22:06:52 -07:00
await page . keyboard . press ( 'Enter' )
await page . keyboard . press ( 'Enter' )
await page . keyboard . type ( 'thing: "blah"' , { delay : 100 } )
await page . keyboard . press ( 'Enter' )
2024-07-05 05:42:54 +10:00
await page . keyboard . press ( 'ArrowLeft' )
2024-02-11 15:08:54 -08:00
2024-07-03 22:06:52 -07:00
await expect ( page . locator ( '.cm-content' ) )
. toContainText ( ` const exampleSketch = startSketchOn("XZ")
2024-07-03 14:34:45 +10:00
| > startProfileAt ( [ 0 , 0 ] , % )
| > angledLine ( { angle : 50 , length : 45 } , % )
| > yLineTo ( 0 , % )
2024-07-05 05:42:54 +10:00
| > close ( % )
2024-07-03 22:06:52 -07:00
2024-07-03 14:34:45 +10:00
thing : "blah" ` )
2024-02-11 15:08:54 -08:00
2024-07-03 22:06:52 -07:00
await expect ( page . locator ( '.cm-lint-marker-error' ) ) . toBeVisible ( )
} )
2024-02-11 15:08:54 -08:00
} )
2024-02-19 17:23:03 +11:00
2024-07-03 14:34:45 +10:00
test . describe ( 'Sketch tests' , ( ) = > {
test ( 'multi-sketch file shows multiple Edit Sketch buttons' , async ( {
page ,
context ,
} ) = > {
const u = await getUtils ( page )
const selectionsSnippets = {
startProfileAt1 :
'|> startProfileAt([-width / 4 + screwRadius, height / 2], %)' ,
startProfileAt2 : '|> startProfileAt([-width / 2, 0], %)' ,
startProfileAt3 : '|> startProfileAt([0, thickness], %)' ,
}
await context . addInitScript (
async ( { startProfileAt1 , startProfileAt2 , startProfileAt3 } : any ) = > {
localStorage . setItem (
'persistCode' ,
`
const width = 20
const height = 10
const thickness = 5
const screwRadius = 3
const wireRadius = 2
const wireOffset = 0.5
const screwHole = startSketchOn ( 'XY' )
$ { startProfileAt1 }
| > arc ( {
radius : screwRadius ,
angle_start : 0 ,
angle_end : 360
} , % )
const part001 = startSketchOn ( 'XY' )
$ { startProfileAt2 }
| > xLine ( width * . 5 , % )
| > yLine ( height , % )
| > xLine ( - width * . 5 , % )
| > close ( % )
| > hole ( screwHole , % )
| > extrude ( thickness , % )
const part002 = startSketchOn ( '-XZ' )
$ { startProfileAt3 }
| > xLine ( width / 4 , % )
| > tangentialArcTo ( [ width / 2 , 0 ] , % )
| > xLine ( - width / 4 + wireRadius , % )
| > yLine ( wireOffset , % )
| > arc ( {
radius : wireRadius ,
angle_start : 0 ,
angle_end : 180
} , % )
| > yLine ( - wireOffset , % )
| > xLine ( - width / 4 , % )
| > close ( % )
| > extrude ( - height , % )
`
)
} ,
selectionsSnippets
)
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-03-02 03:22:04 +11:00
2024-07-03 14:34:45 +10:00
await u . waitForAuthSkipAppStart ( )
2024-06-29 18:10:07 -07:00
2024-07-03 14:34:45 +10:00
// wait for execution done
await u . openDebugPanel ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await u . closeDebugPanel ( )
2024-02-19 17:23:03 +11:00
2024-07-03 14:34:45 +10:00
await page . getByText ( selectionsSnippets . startProfileAt1 ) . click ( )
await expect ( page . getByRole ( 'button' , { name : 'Extrude' } ) ) . toBeDisabled ( )
await expect (
page . getByRole ( 'button' , { name : 'Edit Sketch' } )
) . toBeVisible ( )
2024-02-19 17:23:03 +11:00
2024-07-03 14:34:45 +10:00
await page . getByText ( selectionsSnippets . startProfileAt2 ) . click ( )
await expect ( page . getByRole ( 'button' , { name : 'Extrude' } ) ) . toBeDisabled ( )
await expect (
page . getByRole ( 'button' , { name : 'Edit Sketch' } )
) . toBeVisible ( )
2024-02-26 21:02:33 +11:00
2024-07-03 14:34:45 +10:00
await page . getByText ( selectionsSnippets . startProfileAt3 ) . click ( )
await expect ( page . getByRole ( 'button' , { name : 'Extrude' } ) ) . toBeDisabled ( )
await expect (
page . getByRole ( 'button' , { name : 'Edit Sketch' } )
) . toBeVisible ( )
} )
2024-07-04 15:53:58 -07:00
test ( 'Can exit selection of face' , async ( { page } ) = > {
// Load the app with the code panes
await page . addInitScript ( async ( ) = > {
localStorage . setItem ( 'persistCode' , ` ` )
} )
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
await page . getByRole ( 'button' , { name : 'Start Sketch' } ) . click ( )
await expect (
page . getByRole ( 'button' , { name : 'Exit Sketch' } )
) . toBeVisible ( )
await expect (
page . getByText ( 'click plane or face to sketch on' )
) . toBeVisible ( )
await page . keyboard . press ( 'Escape' )
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . toBeVisible ( )
} )
2024-07-03 14:34:45 +10:00
test . describe ( 'Can edit segments by dragging their handles' , ( ) = > {
const doEditSegmentsByDraggingHandle = async (
page : Page ,
openPanes : string [ ]
) = > {
// Load the app with the code panes
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( [ 4.61 , - 14.01 ] , % )
| > line ( [ 12.73 , - 0.09 ] , % )
| > tangentialArcTo ( [ 24.95 , - 5.38 ] , % )
| > close ( % ) `
)
} )
2024-02-19 17:23:03 +11:00
2024-07-03 14:34:45 +10:00
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-02-19 17:23:03 +11:00
2024-07-03 14:34:45 +10:00
await u . waitForAuthSkipAppStart ( )
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . not . toBeDisabled ( )
2024-02-19 17:23:03 +11:00
2024-07-03 14:34:45 +10:00
await page . waitForTimeout ( 100 )
await u . openAndClearDebugPanel ( )
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_look_at' ,
vantage : { x : 0 , y : - 1250 , z : 580 } ,
center : { x : 0 , y : 0 , z : 0 } ,
up : { x : 0 , y : 0 , z : 1 } ,
} ,
} )
await page . waitForTimeout ( 100 )
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_get_settings' ,
} ,
} )
await page . waitForTimeout ( 100 )
await u . closeDebugPanel ( )
2024-02-19 17:23:03 +11:00
2024-07-03 14:34:45 +10:00
// If we have the code pane open, we should see the code.
if ( openPanes . includes ( 'code' ) ) {
await expect ( u . codeLocator )
. toHaveText ( ` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( [ 4.61 , - 14.01 ] , % )
| > line ( [ 12.73 , - 0.09 ] , % )
| > tangentialArcTo ( [ 24.95 , - 5.38 ] , % )
| > close ( % ) ` )
} else {
// Ensure we don't see the code.
await expect ( u . codeLocator ) . not . toBeVisible ( )
}
2024-02-20 11:04:42 +11:00
2024-07-03 14:34:45 +10:00
const startPX = [ 665 , 458 ]
2024-06-29 18:10:07 -07:00
2024-07-03 14:34:45 +10:00
const dragPX = 30
let prevContent = ''
2024-02-20 11:04:42 +11:00
2024-07-03 14:34:45 +10:00
if ( openPanes . includes ( 'code' ) ) {
await page . getByText ( 'startProfileAt([4.61, -14.01], %)' ) . click ( )
} else {
// Wait for the render.
await page . waitForTimeout ( 1000 )
// Select the sketch
await page . mouse . click ( 700 , 370 )
}
await expect (
page . getByRole ( 'button' , { name : 'Edit Sketch' } )
) . toBeVisible ( )
await page . getByRole ( 'button' , { name : 'Edit Sketch' } ) . click ( )
await page . waitForTimeout ( 400 )
if ( openPanes . includes ( 'code' ) ) {
prevContent = await page . locator ( '.cm-content' ) . innerText ( )
}
2024-02-20 11:04:42 +11:00
2024-07-03 14:34:45 +10:00
const step5 = { steps : 5 }
2024-02-20 11:04:42 +11:00
2024-07-03 14:34:45 +10:00
await expect ( page . getByTestId ( 'segment-overlay' ) ) . toHaveCount ( 2 )
2024-02-20 11:04:42 +11:00
2024-07-03 14:34:45 +10:00
// drag startProfieAt handle
await page . mouse . move ( startPX [ 0 ] , startPX [ 1 ] )
await page . mouse . down ( )
await page . mouse . move ( startPX [ 0 ] + dragPX , startPX [ 1 ] - dragPX , step5 )
await page . mouse . up ( )
2024-02-20 11:04:42 +11:00
2024-07-03 14:34:45 +10:00
if ( openPanes . includes ( 'code' ) ) {
await expect ( page . locator ( '.cm-content' ) ) . not . toHaveText ( prevContent )
prevContent = await page . locator ( '.cm-content' ) . innerText ( )
}
2024-02-20 11:04:42 +11:00
2024-07-03 14:34:45 +10:00
// drag line handle
await page . waitForTimeout ( 100 )
2024-02-20 11:04:42 +11:00
2024-07-03 14:34:45 +10:00
const lineEnd = await u . getBoundingBox ( '[data-overlay-index="0"]' )
await page . mouse . move ( lineEnd . x - 5 , lineEnd . y )
await page . mouse . down ( )
await page . mouse . move ( lineEnd . x + dragPX , lineEnd . y - dragPX , step5 )
await page . mouse . up ( )
await page . waitForTimeout ( 100 )
if ( openPanes . includes ( 'code' ) ) {
await expect ( page . locator ( '.cm-content' ) ) . not . toHaveText ( prevContent )
prevContent = await page . locator ( '.cm-content' ) . innerText ( )
}
2024-02-20 11:04:42 +11:00
2024-07-03 14:34:45 +10:00
// drag tangentialArcTo handle
const tangentEnd = await u . getBoundingBox ( '[data-overlay-index="1"]' )
await page . mouse . move ( tangentEnd . x , tangentEnd . y - 5 )
await page . mouse . down ( )
await page . mouse . move ( tangentEnd . x + dragPX , tangentEnd . y - dragPX , step5 )
await page . mouse . up ( )
await page . waitForTimeout ( 100 )
if ( openPanes . includes ( 'code' ) ) {
await expect ( page . locator ( '.cm-content' ) ) . not . toHaveText ( prevContent )
}
2024-02-20 11:04:42 +11:00
2024-07-03 14:34:45 +10:00
// Open the code pane
await u . openKclCodePanel ( )
// expect the code to have changed
await expect ( page . locator ( '.cm-content' ) )
. toHaveText ( ` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( [ 6.44 , - 12.07 ] , % )
| > line ( [ 14.72 , 1.97 ] , % )
| > tangentialArcTo ( [ 24.95 , - 5.38 ] , % )
| > line ( [ 1.97 , 2.06 ] , % )
| > close ( % ) ` )
}
test ( 'code pane open at start-handles' , async ( { page } ) = > {
// Load the app with the code panes
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'store' ,
JSON . stringify ( {
state : {
openPanes : [ 'code' ] ,
} ,
version : 0 ,
} )
)
} )
await doEditSegmentsByDraggingHandle ( page , [ 'code' ] )
} )
2024-02-20 11:04:42 +11:00
2024-07-03 14:34:45 +10:00
test ( 'code pane closed at start-handles' , async ( { page } ) = > {
// Load the app with the code panes
await page . addInitScript ( async ( persistModelingContext ) = > {
localStorage . setItem (
persistModelingContext ,
JSON . stringify ( { openPanes : [ ] } )
)
} , PERSIST_MODELING_CONTEXT )
await doEditSegmentsByDraggingHandle ( page , [ ] )
} )
} )
2024-02-20 11:04:42 +11:00
2024-07-03 14:34:45 +10:00
test ( 'Can edit a sketch that has been extruded in the same pipe' , async ( {
page ,
} ) = > {
const u = await getUtils ( page )
await page . addInitScript ( async ( ) = > {
2024-05-22 13:19:29 -04:00
localStorage . setItem (
'persistCode' ,
2024-07-03 14:34:45 +10:00
` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( [ 4.61 , - 14.01 ] , % )
| > line ( [ 12.73 , - 0.09 ] , % )
| > tangentialArcTo ( [ 24.95 , - 5.38 ] , % )
| > close ( % )
| > extrude ( 5 , % ) `
2024-05-22 13:19:29 -04:00
)
2024-07-03 14:34:45 +10:00
} )
2024-06-29 18:10:07 -07:00
2024-07-03 14:34:45 +10:00
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-03-02 20:08:13 +11:00
2024-07-03 14:34:45 +10:00
await u . waitForAuthSkipAppStart ( )
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . not . toBeDisabled ( )
2024-06-22 02:21:13 -07:00
2024-07-03 14:34:45 +10:00
await page . waitForTimeout ( 100 )
await u . openAndClearDebugPanel ( )
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_look_at' ,
vantage : { x : 0 , y : - 1250 , z : 580 } ,
center : { x : 0 , y : 0 , z : 0 } ,
up : { x : 0 , y : 0 , z : 1 } ,
} ,
} )
await page . waitForTimeout ( 100 )
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_get_settings' ,
} ,
} )
await page . waitForTimeout ( 100 )
2024-05-23 17:05:54 -07:00
2024-07-03 14:34:45 +10:00
const startPX = [ 665 , 458 ]
2024-03-02 20:08:13 +11:00
2024-07-03 14:34:45 +10:00
const dragPX = 40
2024-06-22 02:21:13 -07:00
await page . getByText ( 'startProfileAt([4.61, -14.01], %)' ) . click ( )
2024-07-03 14:34:45 +10:00
await expect (
page . getByRole ( 'button' , { name : 'Edit Sketch' } )
) . toBeVisible ( )
await page . getByRole ( 'button' , { name : 'Edit Sketch' } ) . click ( )
await page . waitForTimeout ( 400 )
let prevContent = await page . locator ( '.cm-content' ) . innerText ( )
2024-05-24 20:54:42 +10:00
2024-07-03 14:34:45 +10:00
await expect ( page . getByTestId ( 'segment-overlay' ) ) . toHaveCount ( 2 )
2024-04-22 20:14:06 +10:00
2024-07-03 14:34:45 +10:00
// drag startProfieAt handle
await page . dragAndDrop ( '#stream' , '#stream' , {
sourcePosition : { x : startPX [ 0 ] , y : startPX [ 1 ] } ,
targetPosition : { x : startPX [ 0 ] + dragPX , y : startPX [ 1 ] + dragPX } ,
} )
await page . waitForTimeout ( 100 )
2024-06-22 02:21:13 -07:00
await expect ( page . locator ( '.cm-content' ) ) . not . toHaveText ( prevContent )
prevContent = await page . locator ( '.cm-content' ) . innerText ( )
2024-03-02 20:08:13 +11:00
2024-07-03 14:34:45 +10:00
// drag line handle
await page . waitForTimeout ( 100 )
2024-05-24 20:54:42 +10:00
2024-07-03 14:34:45 +10:00
const lineEnd = await u . getBoundingBox ( '[data-overlay-index="0"]' )
await page . waitForTimeout ( 100 )
await page . dragAndDrop ( '#stream' , '#stream' , {
sourcePosition : { x : lineEnd.x - 5 , y : lineEnd.y } ,
targetPosition : { x : lineEnd.x + dragPX , y : lineEnd.y + dragPX } ,
} )
2024-06-22 02:21:13 -07:00
await expect ( page . locator ( '.cm-content' ) ) . not . toHaveText ( prevContent )
prevContent = await page . locator ( '.cm-content' ) . innerText ( )
2024-03-02 20:08:13 +11:00
2024-07-03 14:34:45 +10:00
// drag tangentialArcTo handle
const tangentEnd = await u . getBoundingBox ( '[data-overlay-index="1"]' )
await page . dragAndDrop ( '#stream' , '#stream' , {
sourcePosition : { x : tangentEnd.x , y : tangentEnd.y - 5 } ,
targetPosition : {
x : tangentEnd.x + dragPX ,
y : tangentEnd.y + dragPX ,
} ,
} )
await page . waitForTimeout ( 100 )
2024-06-22 02:21:13 -07:00
await expect ( page . locator ( '.cm-content' ) ) . not . toHaveText ( prevContent )
2024-03-02 20:08:13 +11:00
2024-07-03 14:34:45 +10:00
// expect the code to have changed
await expect ( page . locator ( '.cm-content' ) )
. toHaveText ( ` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( [ 7.12 , - 16.82 ] , % )
| > line ( [ 15.4 , - 2.74 ] , % )
| > tangentialArcTo ( [ 24.95 , - 5.38 ] , % )
| > line ( [ 2.65 , - 2.69 ] , % )
| > close ( % )
| > extrude ( 5 , % ) ` )
} )
2024-06-22 02:21:13 -07:00
2024-07-03 14:34:45 +10:00
test ( 'Can edit a sketch that has been revolved in the same pipe' , async ( {
page ,
} ) = > {
const u = await getUtils ( page )
2024-06-22 02:21:13 -07:00
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
2024-07-03 14:34:45 +10:00
'persistCode' ,
` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( [ 4.61 , - 14.01 ] , % )
| > line ( [ 12.73 , - 0.09 ] , % )
| > tangentialArcTo ( [ 24.95 , - 5.38 ] , % )
| > close ( % )
| > revolve ( { axis : "X" , } , % ) `
2024-06-22 02:21:13 -07:00
)
} )
2024-06-29 18:10:07 -07:00
2024-07-03 14:34:45 +10:00
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-21 23:50:30 -07:00
2024-07-03 14:34:45 +10:00
await u . waitForAuthSkipAppStart ( )
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . not . toBeDisabled ( )
2024-06-21 23:50:30 -07:00
2024-07-03 14:34:45 +10:00
await page . waitForTimeout ( 100 )
await u . openAndClearDebugPanel ( )
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_look_at' ,
vantage : { x : 0 , y : - 1250 , z : 580 } ,
center : { x : 0 , y : 0 , z : 0 } ,
up : { x : 0 , y : 0 , z : 1 } ,
} ,
} )
await page . waitForTimeout ( 100 )
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_get_settings' ,
} ,
} )
await page . waitForTimeout ( 100 )
2024-06-21 23:50:30 -07:00
2024-07-03 14:34:45 +10:00
const startPX = [ 665 , 458 ]
2024-06-21 23:50:30 -07:00
2024-07-03 14:34:45 +10:00
const dragPX = 30
2024-06-21 23:50:30 -07:00
2024-07-03 14:34:45 +10:00
await page . getByText ( 'startProfileAt([4.61, -14.01], %)' ) . click ( )
await expect (
page . getByRole ( 'button' , { name : 'Edit Sketch' } )
) . toBeVisible ( )
await page . getByRole ( 'button' , { name : 'Edit Sketch' } ) . click ( )
await page . waitForTimeout ( 400 )
let prevContent = await page . locator ( '.cm-content' ) . innerText ( )
2024-06-21 23:50:30 -07:00
2024-07-03 14:34:45 +10:00
const step5 = { steps : 5 }
2024-06-29 18:10:07 -07:00
2024-07-03 14:34:45 +10:00
await expect ( page . getByTestId ( 'segment-overlay' ) ) . toHaveCount ( 2 )
2024-03-04 08:14:37 +11:00
2024-07-03 14:34:45 +10:00
// drag startProfieAt handle
await page . mouse . move ( startPX [ 0 ] , startPX [ 1 ] )
await page . mouse . down ( )
await page . mouse . move ( startPX [ 0 ] + dragPX , startPX [ 1 ] - dragPX , step5 )
await page . mouse . up ( )
2024-04-18 15:16:08 -07:00
2024-07-03 14:34:45 +10:00
await expect ( page . locator ( '.cm-content' ) ) . not . toHaveText ( prevContent )
prevContent = await page . locator ( '.cm-content' ) . innerText ( )
2024-03-04 08:14:37 +11:00
2024-07-03 14:34:45 +10:00
// drag line handle
await page . waitForTimeout ( 100 )
2024-03-04 08:14:37 +11:00
2024-07-03 14:34:45 +10:00
const lineEnd = await u . getBoundingBox ( '[data-overlay-index="0"]' )
await page . mouse . move ( lineEnd . x - 5 , lineEnd . y )
await page . mouse . down ( )
await page . mouse . move ( lineEnd . x + dragPX , lineEnd . y - dragPX , step5 )
await page . mouse . up ( )
await page . waitForTimeout ( 100 )
await expect ( page . locator ( '.cm-content' ) ) . not . toHaveText ( prevContent )
prevContent = await page . locator ( '.cm-content' ) . innerText ( )
2024-03-04 08:14:37 +11:00
2024-07-03 14:34:45 +10:00
// drag tangentialArcTo handle
const tangentEnd = await u . getBoundingBox ( '[data-overlay-index="1"]' )
await page . mouse . move ( tangentEnd . x , tangentEnd . y - 5 )
await page . mouse . down ( )
await page . mouse . move ( tangentEnd . x + dragPX , tangentEnd . y - dragPX , step5 )
await page . mouse . up ( )
await page . waitForTimeout ( 100 )
await expect ( page . locator ( '.cm-content' ) ) . not . toHaveText ( prevContent )
2024-06-25 13:56:11 -04:00
2024-07-03 14:34:45 +10:00
// expect the code to have changed
await expect ( page . locator ( '.cm-content' ) )
. toHaveText ( ` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( [ 6.44 , - 12.07 ] , % )
| > line ( [ 14.72 , 2.01 ] , % )
| > tangentialArcTo ( [ 24.95 , - 5.38 ] , % )
| > line ( [ 1.97 , 2.06 ] , % )
| > close ( % )
| > revolve ( { axis : "X" } , % ) ` )
} )
test ( 'Can add multiple sketches' , async ( { page } ) = > {
test . skip ( process . platform === 'darwin' , 'Can add multiple sketches' )
const u = await getUtils ( page )
const viewportSize = { width : 1200 , height : 500 }
await page . setViewportSize ( viewportSize )
2024-03-04 08:14:37 +11:00
2024-07-03 14:34:45 +10:00
await u . waitForAuthSkipAppStart ( )
await u . openDebugPanel ( )
2024-03-04 08:14:37 +11:00
2024-07-03 14:34:45 +10:00
const center = { x : viewportSize.width / 2 , y : viewportSize.height / 2 }
const { toSU , click00r } = getMovementUtils ( { center , page } )
2024-03-04 08:14:37 +11:00
2024-07-03 14:34:45 +10:00
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . not . toBeDisabled ( )
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . toBeVisible ( )
2024-03-04 08:14:37 +11:00
2024-07-03 14:34:45 +10:00
// click on "Start Sketch" button
await u . clearCommandLogs ( )
await u . doAndWaitForImageDiff (
( ) = > page . getByRole ( 'button' , { name : 'Start Sketch' } ) . click ( ) ,
200
)
2024-03-04 08:14:37 +11:00
2024-07-03 14:34:45 +10:00
let codeStr = "const sketch001 = startSketchOn('XY')"
2024-03-04 08:14:37 +11:00
2024-07-03 14:34:45 +10:00
await page . mouse . click ( center . x , viewportSize . height * 0.55 )
await expect ( u . codeLocator ) . toHaveText ( codeStr )
await u . closeDebugPanel ( )
await page . waitForTimeout ( 500 ) // TODO detect animation ending, or disable animation
2024-03-04 08:14:37 +11:00
2024-07-03 14:34:45 +10:00
await click00r ( 0 , 0 )
codeStr += ` |> startProfileAt( ${ toSU ( [ 0 , 0 ] ) } , %) `
await expect ( u . codeLocator ) . toHaveText ( codeStr )
2024-03-04 08:14:37 +11:00
2024-07-03 14:34:45 +10:00
await click00r ( 50 , 0 )
await page . waitForTimeout ( 100 )
codeStr += ` |> line( ${ toSU ( [ 50 , 0 ] ) } , %) `
await expect ( u . codeLocator ) . toHaveText ( codeStr )
2024-03-22 10:23:04 +11:00
2024-07-03 14:34:45 +10:00
await click00r ( 0 , 50 )
codeStr += ` |> line( ${ toSU ( [ 0 , 50 ] ) } , %) `
await expect ( u . codeLocator ) . toHaveText ( codeStr )
2024-03-22 10:23:04 +11:00
2024-07-03 14:34:45 +10:00
await click00r ( - 50 , 0 )
codeStr += ` |> line( ${ toSU ( [ - 50 , 0 ] ) } , %) `
await expect ( u . codeLocator ) . toHaveText ( codeStr )
2024-06-29 18:10:07 -07:00
2024-07-03 14:34:45 +10:00
// exit the sketch, reset relative clicker
click00r ( undefined , undefined )
await u . openAndClearDebugPanel ( )
await page . getByRole ( 'button' , { name : 'Exit Sketch' } ) . click ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await page . waitForTimeout ( 250 )
await u . clearCommandLogs ( )
2024-05-24 12:32:15 -07:00
2024-07-03 14:34:45 +10:00
// start a new sketch
await page . getByRole ( 'button' , { name : 'Start Sketch' } ) . click ( )
2024-05-24 12:32:15 -07:00
2024-07-03 14:34:45 +10:00
// when exiting the sketch above the camera is still looking down at XY,
// so selecting the plane again is a bit easier.
await page . mouse . click ( center . x + 200 , center . y + 100 )
await page . waitForTimeout ( 600 ) // TODO detect animation ending, or disable animation
codeStr += "const sketch002 = startSketchOn('XY')"
await expect ( u . codeLocator ) . toHaveText ( codeStr )
await u . closeDebugPanel ( )
2024-03-22 10:23:04 +11:00
2024-07-03 14:34:45 +10:00
await click00r ( 30 , 0 )
codeStr += ` |> startProfileAt([1.53, 0], %) `
await expect ( u . codeLocator ) . toHaveText ( codeStr )
2024-03-22 10:23:04 +11:00
2024-07-03 14:34:45 +10:00
await click00r ( 30 , 0 )
codeStr += ` |> line([1.53, 0], %) `
await expect ( u . codeLocator ) . toHaveText ( codeStr )
2024-03-22 10:23:04 +11:00
2024-07-03 14:34:45 +10:00
await click00r ( 0 , 30 )
codeStr += ` |> line([0, -1.53], %) `
await expect ( u . codeLocator ) . toHaveText ( codeStr )
2024-03-22 10:23:04 +11:00
2024-07-03 14:34:45 +10:00
await click00r ( - 30 , 0 )
codeStr += ` |> line([-1.53, 0], %) `
await expect ( u . codeLocator ) . toHaveText ( codeStr )
2024-03-22 10:23:04 +11:00
2024-07-03 14:34:45 +10:00
await click00r ( undefined , undefined )
await u . openAndClearDebugPanel ( )
await page . getByRole ( 'button' , { name : 'Exit Sketch' } ) . click ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await u . updateCamPosition ( [ 100 , 100 , 100 ] )
await u . clearCommandLogs ( )
} )
test . describe ( 'Snap to close works (at any scale)' , ( ) = > {
const doSnapAtDifferentScales = async (
page : any ,
camPos : [ number , number , number ] ,
scale = 1
) = > {
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-03-22 10:23:04 +11:00
2024-07-03 14:34:45 +10:00
await u . waitForAuthSkipAppStart ( )
await u . openDebugPanel ( )
2024-03-22 10:23:04 +11:00
2024-07-03 14:34:45 +10:00
const code = ` const sketch001 = startSketchOn('-XZ')
| > startProfileAt ( [ $ { roundOff ( scale * 69.6 ) } , $ { roundOff ( scale * 34.8 ) } ] , % )
| > line ( [ $ { roundOff ( scale * 139.19 ) } , 0 ] , % )
| > line ( [ 0 , - $ { roundOff ( scale * 139.2 ) } ] , % )
| > lineTo ( [ profileStartX ( % ) , profileStartY ( % ) ] , % )
| > close ( % ) `
2024-03-22 10:23:04 +11:00
2024-07-03 14:34:45 +10:00
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . not . toBeDisabled ( )
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . toBeVisible ( )
2024-03-22 10:23:04 +11:00
2024-07-03 14:34:45 +10:00
await u . clearCommandLogs ( )
await page . getByRole ( 'button' , { name : 'Start Sketch' } ) . click ( )
await page . waitForTimeout ( 100 )
2024-03-22 10:23:04 +11:00
2024-07-03 14:34:45 +10:00
await u . openAndClearDebugPanel ( )
await u . updateCamPosition ( camPos )
await u . closeDebugPanel ( )
2024-03-22 10:23:04 +11:00
2024-07-03 14:34:45 +10:00
await page . mouse . move ( 0 , 0 )
2024-03-22 10:23:04 +11:00
2024-07-03 14:34:45 +10:00
// select a plane
await page . mouse . move ( 700 , 200 , { steps : 10 } )
await page . mouse . click ( 700 , 200 , { delay : 200 } )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
` const sketch001 = startSketchOn('-XZ') `
)
2024-03-22 10:23:04 +11:00
2024-07-03 14:34:45 +10:00
let prevContent = await page . locator ( '.cm-content' ) . innerText ( )
2024-03-22 10:23:04 +11:00
2024-07-03 14:34:45 +10:00
const pointA = [ 700 , 200 ]
const pointB = [ 900 , 200 ]
const pointC = [ 900 , 400 ]
2024-05-02 15:26:23 +10:00
2024-07-03 14:34:45 +10:00
// draw three lines
await page . waitForTimeout ( 500 )
await page . mouse . move ( pointA [ 0 ] , pointA [ 1 ] , { steps : 10 } )
await page . mouse . click ( pointA [ 0 ] , pointA [ 1 ] , { delay : 200 } )
await page . waitForTimeout ( 100 )
await expect ( page . locator ( '.cm-content' ) ) . not . toHaveText ( prevContent )
prevContent = await page . locator ( '.cm-content' ) . innerText ( )
2024-03-22 10:23:04 +11:00
2024-07-03 14:34:45 +10:00
await page . mouse . move ( pointB [ 0 ] , pointB [ 1 ] , { steps : 10 } )
await page . mouse . click ( pointB [ 0 ] , pointB [ 1 ] , { delay : 200 } )
await page . waitForTimeout ( 100 )
await expect ( page . locator ( '.cm-content' ) ) . not . toHaveText ( prevContent )
prevContent = await page . locator ( '.cm-content' ) . innerText ( )
2024-03-22 10:23:04 +11:00
2024-07-03 14:34:45 +10:00
await page . mouse . move ( pointC [ 0 ] , pointC [ 1 ] , { steps : 10 } )
await page . mouse . click ( pointC [ 0 ] , pointC [ 1 ] , { delay : 200 } )
await page . waitForTimeout ( 100 )
await expect ( page . locator ( '.cm-content' ) ) . not . toHaveText ( prevContent )
prevContent = await page . locator ( '.cm-content' ) . innerText ( )
2024-03-22 10:23:04 +11:00
2024-07-03 14:34:45 +10:00
await page . mouse . move ( pointA [ 0 ] - 12 , pointA [ 1 ] + 12 , { steps : 10 } )
const pointNotQuiteA = [ pointA [ 0 ] - 7 , pointA [ 1 ] + 7 ]
await page . mouse . move ( pointNotQuiteA [ 0 ] , pointNotQuiteA [ 1 ] , { steps : 10 } )
2024-03-22 10:23:04 +11:00
2024-07-03 14:34:45 +10:00
await page . mouse . click ( pointNotQuiteA [ 0 ] , pointNotQuiteA [ 1 ] , {
delay : 200 ,
} )
await expect ( page . locator ( '.cm-content' ) ) . not . toHaveText ( prevContent )
prevContent = await page . locator ( '.cm-content' ) . innerText ( )
2024-03-22 10:23:04 +11:00
2024-07-03 14:34:45 +10:00
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( code )
// Assert the tool was unequipped
await expect (
page . getByRole ( 'button' , { name : 'Line' } )
) . not . toHaveAttribute ( 'aria-pressed' , 'true' )
2024-03-22 10:23:04 +11:00
2024-07-03 14:34:45 +10:00
// exit sketch
await u . openAndClearDebugPanel ( )
await page . getByRole ( 'button' , { name : 'Exit Sketch' } ) . click ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await u . removeCurrentCode ( )
}
test ( '[0, 100, 100]' , async ( { page } ) = > {
await doSnapAtDifferentScales ( page , [ 0 , 100 , 100 ] , 0.01 )
} )
2024-04-18 20:09:40 -07:00
2024-07-03 14:34:45 +10:00
test ( '[0, 10000, 10000]' , async ( { page } ) = > {
await doSnapAtDifferentScales ( page , [ 0 , 10000 , 10000 ] )
} )
2024-04-18 20:09:40 -07:00
} )
2024-07-03 22:03:04 +10:00
test ( "Existing sketch with bad code delete user's code" , async ( { page } ) = > {
// this was a regression https://github.com/KittyCAD/modeling-app/issues/2832
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( [ - 0.45 , 0.87 ] , % )
| > line ( [ 1.32 , 0.38 ] , % )
| > line ( [ 1.02 , - 1.32 ] , % , $seg01 )
| > line ( [ - 1.01 , - 0.77 ] , % )
| > lineTo ( [ profileStartX ( % ) , profileStartY ( % ) ] , % )
| > close ( % )
const extrude001 = extrude ( 5 , sketch001 )
`
)
} )
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
await u . openDebugPanel ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await u . closeDebugPanel ( )
await page . getByRole ( 'button' , { name : 'Start Sketch' } ) . click ( )
await page . mouse . click ( 622 , 355 )
await page . waitForTimeout ( 800 )
await page . getByText ( ` END') ` ) . click ( )
await page . keyboard . press ( 'End' )
await page . keyboard . press ( 'Enter' )
await page . keyboard . type ( ' |>' , { delay : 100 } )
await page . waitForTimeout ( 100 )
await expect ( page . locator ( '.cm-lint-marker-error' ) ) . toBeVisible ( )
await page . getByRole ( 'button' , { name : 'Exit Sketch' } ) . click ( )
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . toBeVisible ( )
await expect ( ( await u . codeLocator . innerText ( ) ) . replace ( /\s/g , '' ) ) . toBe (
` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( [ - 0.45 , 0.87 ] , % )
| > line ( [ 1.32 , 0.38 ] , % )
| > line ( [ 1.02 , - 1.32 ] , % , $seg01 )
| > line ( [ - 1.01 , - 0.77 ] , % )
| > lineTo ( [ profileStartX ( % ) , profileStartY ( % ) ] , % )
| > close ( % )
const extrude001 = extrude ( 5 , sketch001 )
const sketch002 = startSketchOn ( extrude001 , 'END' )
| >
` .replace(/ \ s/g, '')
)
} )
2024-07-03 14:34:45 +10:00
} )
2024-04-18 20:09:40 -07:00
2024-07-03 14:34:45 +10:00
test . describe ( 'Testing constraints' , ( ) = > {
test ( 'Can constrain line length' , async ( { page } ) = > {
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const sketch001 = startSketchOn('XY')
| > startProfileAt ( [ - 10 , - 10 ] , % )
| > line ( [ 20 , 0 ] , % )
| > line ( [ 0 , 20 ] , % )
| > xLine ( - 20 , % )
`
)
} )
2024-04-18 20:09:40 -07:00
2024-07-03 14:34:45 +10:00
const u = await getUtils ( page )
const PUR = 400 / 37.5 //pixeltoUnitRatio
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-04-18 20:09:40 -07:00
2024-07-03 14:34:45 +10:00
await u . waitForAuthSkipAppStart ( )
2024-05-23 17:05:54 -07:00
2024-07-03 14:34:45 +10:00
await u . openDebugPanel ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await u . closeDebugPanel ( )
2024-04-18 20:09:40 -07:00
2024-07-03 14:34:45 +10:00
// Click the line of code for line.
await page . getByText ( ` line([0, 20], %) ` ) . click ( ) // TODO remove this and reinstate // await topHorzSegmentClick()
await page . waitForTimeout ( 100 )
2024-05-23 17:05:54 -07:00
2024-07-03 14:34:45 +10:00
// enter sketch again
await page . getByRole ( 'button' , { name : 'Edit Sketch' } ) . click ( )
await page . waitForTimeout ( 500 ) // wait for animation
2024-05-23 17:05:54 -07:00
2024-07-03 14:34:45 +10:00
const startXPx = 500
await page . mouse . move ( startXPx + PUR * 15 , 250 - PUR * 10 )
await page . keyboard . down ( 'Shift' )
await page . mouse . click ( 834 , 244 )
await page . keyboard . up ( 'Shift' )
2024-05-23 17:05:54 -07:00
2024-07-03 14:34:45 +10:00
await page . getByRole ( 'button' , { name : 'Constraints' , exact : true } ) . click ( )
await page . getByRole ( 'button' , { name : 'length' , exact : true } ) . click ( )
await page . getByText ( 'Add constraining value' ) . click ( )
2024-04-19 14:24:40 -07:00
2024-07-03 14:34:45 +10:00
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
` const length001 = 20const sketch001 = startSketchOn('XY') |> startProfileAt([-10, -10], %) |> line([20, 0], %) |> angledLine([90, length001], %) |> xLine(-20, %) `
2024-04-19 14:24:40 -07:00
)
2024-05-24 12:32:15 -07:00
2024-07-03 14:34:45 +10:00
// Make sure we didn't pop out of sketch mode.
await expect (
page . getByRole ( 'button' , { name : 'Exit Sketch' } )
) . toBeVisible ( )
2024-04-19 14:24:40 -07:00
2024-07-03 14:34:45 +10:00
await page . waitForTimeout ( 500 ) // wait for animation
2024-05-22 11:07:02 -04:00
2024-07-03 14:34:45 +10:00
// Exit sketch
await page . mouse . move ( startXPx + PUR * 15 , 250 - PUR * 10 )
await page . keyboard . press ( 'Escape' )
await expect (
page . getByRole ( 'button' , { name : 'Exit Sketch' } )
) . not . toBeVisible ( )
} )
2024-06-03 22:40:59 +10:00
test ( ` Test remove constraints ` , async ( { page } ) = > {
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const yo = 79
const part001 = startSketchOn ( 'XZ' )
| > startProfileAt ( [ - 7.54 , - 26.74 ] , % )
2024-06-24 22:39:04 -07:00
| > line ( [ 74.36 , 130.4 ] , % , $seg01 )
2024-06-03 22:40:59 +10:00
| > line ( [ 78.92 , - 120.11 ] , % )
2024-06-24 22:39:04 -07:00
| > angledLine ( [ segAng ( seg01 , % ) , yo ] , % )
2024-06-03 22:40:59 +10:00
| > line ( [ 41.19 , 28.97 + 5 ] , % )
const part002 = startSketchOn ( 'XZ' )
| > startProfileAt ( [ 299.05 , 231.45 ] , % )
2024-06-24 22:39:04 -07:00
| > xLine ( - 425.34 , % , $seg_what )
2024-06-03 22:40:59 +10:00
| > yLine ( - 264.06 , % )
2024-06-24 22:39:04 -07:00
| > xLine ( segLen ( seg_what , % ) , % )
2024-06-03 22:40:59 +10:00
| > lineTo ( [ profileStartX ( % ) , profileStartY ( % ) ] , % ) `
)
} )
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-06-03 22:40:59 +10:00
await u . waitForAuthSkipAppStart ( )
2024-06-24 22:39:04 -07:00
await page . getByText ( 'line([74.36, 130.4], %, $seg01)' ) . click ( )
2024-06-03 22:40:59 +10:00
await page . getByRole ( 'button' , { name : 'Edit Sketch' } ) . click ( )
const line3 = await u . getSegmentBodyCoords ( ` [data-overlay-index=" ${ 2 } "] ` )
await page . mouse . click ( line3 . x , line3 . y )
await page . waitForTimeout ( 100 ) // this wait is needed for webkit - not sure why
await page
. getByRole ( 'button' , {
2024-06-24 11:37:48 -04:00
name : 'Constraints' ,
2024-06-03 22:40:59 +10:00
} )
. click ( )
await page
. getByRole ( 'button' , { name : 'remove constraints' , exact : true } )
. click ( )
2024-06-24 11:45:40 -04:00
await page . getByText ( 'line([39.13, 68.63], %)' ) . click ( )
2024-06-03 22:40:59 +10:00
const activeLinesContent = await page . locator ( '.cm-activeLine' ) . all ( )
await expect ( activeLinesContent ) . toHaveLength ( 1 )
await expect ( activeLinesContent [ 0 ] ) . toHaveText ( '|> line([39.13, 68.63], %)' )
// 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 ( 4 )
} )
test . describe ( 'Test perpendicular distance constraint' , ( ) = > {
const cases = [
{
testName : 'Add variable' ,
offset : '-offset001' ,
} ,
{
testName : 'No variable' ,
offset : '-128.05' ,
} ,
] as const
for ( const { testName , offset } of cases ) {
test ( ` ${ testName } ` , async ( { page } ) = > {
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const yo = 5
const part001 = startSketchOn ( 'XZ' )
| > startProfileAt ( [ - 7.54 , - 26.74 ] , % )
2024-06-24 22:39:04 -07:00
| > line ( [ 74.36 , 130.4 ] , % , $seg01 )
2024-06-03 22:40:59 +10:00
| > line ( [ 78.92 , - 120.11 ] , % )
2024-06-24 22:39:04 -07:00
| > angledLine ( [ segAng ( seg01 , % ) , 78.33 ] , % )
2024-06-03 22:40:59 +10:00
| > line ( [ 41.19 , 28.97 ] , % )
const part002 = startSketchOn ( 'XZ' )
| > startProfileAt ( [ 299.05 , 231.45 ] , % )
2024-06-24 22:39:04 -07:00
| > xLine ( - 425.34 , % , $seg_what )
2024-06-03 22:40:59 +10:00
| > yLine ( - 264.06 , % )
2024-06-24 22:39:04 -07:00
| > xLine ( segLen ( seg_what , % ) , % )
2024-06-03 22:40:59 +10:00
| > lineTo ( [ profileStartX ( % ) , profileStartY ( % ) ] , % ) `
)
} )
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-06-03 22:40:59 +10:00
await u . waitForAuthSkipAppStart ( )
2024-06-24 22:39:04 -07:00
await page . getByText ( 'line([74.36, 130.4], %, $seg01)' ) . click ( )
2024-06-03 22:40:59 +10:00
await page . getByRole ( 'button' , { name : 'Edit Sketch' } ) . click ( )
const [ line1 , line3 ] = await Promise . all ( [
u . getSegmentBodyCoords ( ` [data-overlay-index=" ${ 0 } "] ` ) ,
u . getSegmentBodyCoords ( ` [data-overlay-index=" ${ 2 } "] ` ) ,
] )
await page . mouse . click ( line1 . x , line1 . y )
await page . keyboard . down ( 'Shift' )
await page . mouse . click ( line3 . x , line3 . y )
await page . waitForTimeout ( 100 ) // this wait is needed for webkit - not sure why
await page . keyboard . up ( 'Shift' )
await page
. getByRole ( 'button' , {
2024-06-24 11:37:48 -04:00
name : 'Constraints' ,
2024-06-03 22:40:59 +10:00
} )
. click ( )
await page
. getByRole ( 'button' , { name : 'perpendicular distance' , exact : true } )
. click ( )
const createNewVariableCheckbox = page . getByTestId (
'create-new-variable-checkbox'
)
const isChecked = await createNewVariableCheckbox . isChecked ( )
const addVariable = testName === 'Add variable'
XOR ( isChecked , addVariable ) && // XOR because no need to click the checkbox if the state is already correct
( await createNewVariableCheckbox . click ( ) )
await page
. getByRole ( 'button' , { name : 'Add constraining value' } )
. click ( )
2024-06-24 11:45:40 -04:00
// Wait for the codemod to take effect
await expect ( page . locator ( '.cm-content' ) ) . toContainText ( ` angle: -57, ` )
await expect ( page . locator ( '.cm-content' ) ) . toContainText (
` offset: ${ offset } , `
)
2024-06-03 22:40:59 +10:00
const activeLinesContent = await page . locator ( '.cm-activeLine' ) . all ( )
await expect ( activeLinesContent [ 0 ] ) . toHaveText (
2024-06-24 22:39:04 -07:00
` |> line([74.36, 130.4], %, $ seg01) `
2024-06-03 22:40:59 +10:00
)
await expect ( activeLinesContent [ 1 ] ) . toHaveText ( ` }, %) ` )
// 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 ( 4 )
} )
}
} )
2024-06-03 15:37:23 +10:00
test . describe ( 'Test distance between constraint' , ( ) = > {
const cases = [
{
testName : 'Add variable' ,
constraint : 'horizontal distance' ,
2024-06-24 22:39:04 -07:00
value : 'segEndX(seg01, %) + xDis001, 61.34' ,
2024-06-03 15:37:23 +10:00
} ,
{
testName : 'No variable' ,
constraint : 'horizontal distance' ,
2024-06-24 22:39:04 -07:00
value : 'segEndX(seg01, %) + 88.08, 61.34' ,
2024-06-03 15:37:23 +10:00
} ,
{
testName : 'Add variable' ,
constraint : 'vertical distance' ,
2024-06-24 22:39:04 -07:00
value : '154.9, segEndY(seg01, %) - yDis001' ,
2024-06-03 15:37:23 +10:00
} ,
{
testName : 'No variable' ,
constraint : 'vertical distance' ,
2024-06-24 22:39:04 -07:00
value : '154.9, segEndY(seg01, %) - 42.32' ,
2024-06-03 15:37:23 +10:00
} ,
] as const
for ( const { testName , value , constraint } of cases ) {
test ( ` ${ constraint } - ${ testName } ` , async ( { page } ) = > {
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const yo = 5
const part001 = startSketchOn ( 'XZ' )
| > startProfileAt ( [ - 7.54 , - 26.74 ] , % )
| > line ( [ 74.36 , 130.4 ] , % )
| > line ( [ 78.92 , - 120.11 ] , % )
| > line ( [ 9.16 , 77.79 ] , % )
| > line ( [ 41.19 , 28.97 ] , % )
const part002 = startSketchOn ( 'XZ' )
| > startProfileAt ( [ 299.05 , 231.45 ] , % )
2024-06-24 22:39:04 -07:00
| > xLine ( - 425.34 , % , $seg_what )
2024-06-03 15:37:23 +10:00
| > yLine ( - 264.06 , % )
2024-06-24 22:39:04 -07:00
| > xLine ( segLen ( seg_what , % ) , % )
2024-06-03 15:37:23 +10:00
| > lineTo ( [ profileStartX ( % ) , profileStartY ( % ) ] , % ) `
)
} )
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-06-03 15:37:23 +10:00
await u . waitForAuthSkipAppStart ( )
await page . getByText ( 'line([74.36, 130.4], %)' ) . click ( )
await page . getByRole ( 'button' , { name : 'Edit Sketch' } ) . click ( )
const [ line1 , line3 ] = await Promise . all ( [
u . getSegmentBodyCoords ( ` [data-overlay-index=" ${ 0 } "] ` ) ,
u . getSegmentBodyCoords ( ` [data-overlay-index=" ${ 2 } "] ` ) ,
] )
await page . mouse . click ( line1 . x , line1 . y )
await page . keyboard . down ( 'Shift' )
await page . mouse . click ( line3 . x , line3 . y )
await page . waitForTimeout ( 100 ) // this wait is needed for webkit - not sure why
await page . keyboard . up ( 'Shift' )
await page
. getByRole ( 'button' , {
2024-06-24 11:37:48 -04:00
name : 'Constraints' ,
2024-06-03 15:37:23 +10:00
} )
. click ( )
await page
. getByRole ( 'button' , { name : constraint , exact : true } )
. click ( )
const createNewVariableCheckbox = page . getByTestId (
'create-new-variable-checkbox'
)
const isChecked = await createNewVariableCheckbox . isChecked ( )
const addVariable = testName === 'Add variable'
XOR ( isChecked , addVariable ) && // XOR because no need to click the checkbox if the state is already correct
( await createNewVariableCheckbox . click ( ) )
await page
. getByRole ( 'button' , { name : 'Add constraining value' } )
. click ( )
// checking activeLines assures the cursors are where they should be
const codeAfter = [
2024-06-24 22:39:04 -07:00
` |> line([74.36, 130.4], %, $ seg01) ` ,
2024-06-03 15:37:23 +10:00
` |> lineTo([ ${ value } ], %) ` ,
]
const activeLinesContent = await page . locator ( '.cm-activeLine' ) . all ( )
await Promise . all (
activeLinesContent . map ( async ( line , i ) = > {
await expect ( page . locator ( '.cm-content' ) ) . toContainText (
codeAfter [ i ]
)
// if the code is an active line then the cursor should be on that line
await expect ( line ) . toHaveText ( codeAfter [ i ] )
} )
)
// 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 ( 4 )
} )
}
} )
2024-05-31 14:00:32 +10:00
test . describe ( 'Test ABS distance constraint' , ( ) = > {
const cases = [
{
testName : 'Add variable' ,
addVariable : true ,
constraint : 'ABS X' ,
value : 'xDis001, 61.34' ,
} ,
{
testName : 'No variable' ,
addVariable : false ,
constraint : 'ABS X' ,
value : '154.9, 61.34' ,
} ,
{
testName : 'Add variable' ,
addVariable : true ,
constraint : 'ABS Y' ,
value : '154.9, yDis001' ,
} ,
{
testName : 'No variable' ,
addVariable : false ,
constraint : 'ABS Y' ,
value : '154.9, 61.34' ,
} ,
] as const
for ( const { testName , addVariable , value , constraint } of cases ) {
test ( ` ${ constraint } - ${ testName } ` , async ( { page } ) = > {
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const yo = 5
const part001 = startSketchOn ( 'XZ' )
| > startProfileAt ( [ - 7.54 , - 26.74 ] , % )
| > line ( [ 74.36 , 130.4 ] , % )
| > line ( [ 78.92 , - 120.11 ] , % )
| > line ( [ 9.16 , 77.79 ] , % )
| > line ( [ 41.19 , 28.97 ] , % )
const part002 = startSketchOn ( 'XZ' )
| > startProfileAt ( [ 299.05 , 231.45 ] , % )
2024-06-24 22:39:04 -07:00
| > xLine ( - 425.34 , % , $seg_what )
2024-05-31 14:00:32 +10:00
| > yLine ( - 264.06 , % )
2024-06-24 22:39:04 -07:00
| > xLine ( segLen ( seg_what , % ) , % )
2024-05-31 14:00:32 +10:00
| > lineTo ( [ profileStartX ( % ) , profileStartY ( % ) ] , % ) `
)
} )
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-05-31 14:00:32 +10:00
await u . waitForAuthSkipAppStart ( )
await page . getByText ( 'line([74.36, 130.4], %)' ) . click ( )
await page . getByRole ( 'button' , { name : 'Edit Sketch' } ) . click ( )
const [ line3 ] = await Promise . all ( [
u . getSegmentBodyCoords ( ` [data-overlay-index=" ${ 2 } "] ` ) ,
] )
if ( constraint === 'ABS X' ) {
await page . mouse . click ( 600 , 130 )
} else {
await page . mouse . click ( 900 , 250 )
}
await page . keyboard . down ( 'Shift' )
await page . mouse . click ( line3 . x , line3 . y )
await page . waitForTimeout ( 100 ) // this wait is needed for webkit - not sure why
await page . keyboard . up ( 'Shift' )
await page
. getByRole ( 'button' , {
2024-06-24 11:37:48 -04:00
name : 'Constraints' ,
2024-05-31 14:00:32 +10:00
} )
. click ( )
await page
. getByRole ( 'button' , { name : constraint , exact : true } )
. click ( )
const createNewVariableCheckbox = page . getByTestId (
'create-new-variable-checkbox'
)
const isChecked = await createNewVariableCheckbox . isChecked ( )
2024-06-03 15:37:23 +10:00
XOR ( isChecked , addVariable ) && // XOR because no need to click the checkbox if the state is already correct
2024-05-31 14:00:32 +10:00
( await createNewVariableCheckbox . click ( ) )
await page
. getByRole ( 'button' , { name : 'Add constraining value' } )
. click ( )
// checking activeLines assures the cursors are where they should be
const codeAfter = [ ` |> lineTo([ ${ value } ], %) ` ]
const activeLinesContent = await page . locator ( '.cm-activeLine' ) . all ( )
await Promise . all (
activeLinesContent . map ( async ( line , i ) = > {
await expect ( page . locator ( '.cm-content' ) ) . toContainText (
codeAfter [ i ]
)
// if the code is an active line then the cursor should be on that line
await expect ( line ) . toHaveText ( codeAfter [ i ] )
} )
)
// 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 ( 4 )
} )
}
} )
2024-05-31 11:36:08 +10:00
test . describe ( 'Test Angle constraint double segment selection' , ( ) = > {
const cases = [
{
testName : 'Add variable' ,
addVariable : true ,
axisSelect : false ,
2024-06-24 22:39:04 -07:00
value : 'segAng(seg01, %) + angle001' ,
2024-05-31 11:36:08 +10:00
} ,
{
testName : 'No variable' ,
addVariable : false ,
axisSelect : false ,
2024-06-24 22:39:04 -07:00
value : 'segAng(seg01, %) + 22.69' ,
2024-05-31 11:36:08 +10:00
} ,
{
testName : 'Add variable, selecting axis' ,
addVariable : true ,
axisSelect : true ,
value : 'QUARTER_TURN - angle001' ,
} ,
{
testName : 'No variable, selecting axis' ,
addVariable : false ,
axisSelect : true ,
value : 'QUARTER_TURN - 7' ,
} ,
] as const
for ( const { testName , addVariable , value , axisSelect } of cases ) {
test ( ` ${ testName } ` , async ( { page } ) = > {
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const yo = 5
const part001 = startSketchOn ( 'XZ' )
| > startProfileAt ( [ - 7.54 , - 26.74 ] , % )
| > line ( [ 74.36 , 130.4 ] , % )
| > line ( [ 78.92 , - 120.11 ] , % )
| > line ( [ 9.16 , 77.79 ] , % )
| > line ( [ 41.19 , 28.97 ] , % )
const part002 = startSketchOn ( 'XZ' )
| > startProfileAt ( [ 299.05 , 231.45 ] , % )
2024-06-24 22:39:04 -07:00
| > xLine ( - 425.34 , % , $seg_what )
2024-05-31 11:36:08 +10:00
| > yLine ( - 264.06 , % )
2024-06-24 22:39:04 -07:00
| > xLine ( segLen ( seg_what , % ) , % )
2024-05-31 11:36:08 +10:00
| > lineTo ( [ profileStartX ( % ) , profileStartY ( % ) ] , % ) `
)
} )
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-05-31 11:36:08 +10:00
await u . waitForAuthSkipAppStart ( )
await page . getByText ( 'line([74.36, 130.4], %)' ) . click ( )
await page . getByRole ( 'button' , { name : 'Edit Sketch' } ) . click ( )
const [ line1 , line3 ] = await Promise . all ( [
u . getSegmentBodyCoords ( ` [data-overlay-index=" ${ 0 } "] ` ) ,
u . getSegmentBodyCoords ( ` [data-overlay-index=" ${ 2 } "] ` ) ,
] )
if ( axisSelect ) {
await page . mouse . click ( 600 , 130 )
} else {
await page . mouse . click ( line1 . x , line1 . y )
}
await page . keyboard . down ( 'Shift' )
await page . mouse . click ( line3 . x , line3 . y )
await page . waitForTimeout ( 100 ) // this wait is needed for webkit - not sure why
await page . keyboard . up ( 'Shift' )
await page
. getByRole ( 'button' , {
2024-06-24 11:37:48 -04:00
name : 'Constraints' ,
2024-05-31 11:36:08 +10:00
} )
. click ( )
await page . getByTestId ( 'angle' ) . click ( )
const createNewVariableCheckbox = page . getByTestId (
'create-new-variable-checkbox'
)
const isChecked = await createNewVariableCheckbox . isChecked ( )
2024-06-03 15:37:23 +10:00
XOR ( isChecked , addVariable ) && // XOR because no need to click the checkbox if the state is already correct
2024-05-31 11:36:08 +10:00
( await createNewVariableCheckbox . click ( ) )
await page
. getByRole ( 'button' , { name : 'Add constraining value' } )
. click ( )
// checking activeLines assures the cursors are where they should be
const codeAfter = [
2024-06-24 22:39:04 -07:00
'|> line([74.36, 130.4], %, $seg01)' ,
2024-05-31 11:36:08 +10:00
` |> angledLine([ ${ value } , 78.33], %) ` ,
]
if ( axisSelect ) codeAfter . shift ( )
const activeLinesContent = await page . locator ( '.cm-activeLine' ) . all ( )
await Promise . all (
activeLinesContent . map ( async ( line , i ) = > {
await expect ( page . locator ( '.cm-content' ) ) . toContainText (
codeAfter [ i ]
)
// if the code is an active line then the cursor should be on that line
await expect ( line ) . toHaveText ( codeAfter [ i ] )
} )
)
// 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 ( 4 )
} )
}
} )
2024-06-03 18:30:30 +10:00
test . describe ( 'Test Angle/Length constraint single selection' , ( ) = > {
2024-05-31 11:36:08 +10:00
const cases = [
{
2024-06-03 18:30:30 +10:00
testName : 'Angle - Add variable' ,
2024-05-31 11:36:08 +10:00
addVariable : true ,
2024-06-03 18:30:30 +10:00
constraint : 'angle' ,
value : 'angle001, 78.33' ,
2024-05-31 11:36:08 +10:00
} ,
{
2024-06-03 18:30:30 +10:00
testName : 'Angle - No variable' ,
2024-05-31 11:36:08 +10:00
addVariable : false ,
2024-06-03 18:30:30 +10:00
constraint : 'angle' ,
value : '83, 78.33' ,
} ,
{
testName : 'Length - Add variable' ,
addVariable : true ,
constraint : 'length' ,
value : '83, length001' ,
} ,
{
testName : 'Length - No variable' ,
addVariable : false ,
constraint : 'length' ,
value : '83, 78.33' ,
2024-05-31 11:36:08 +10:00
} ,
] as const
2024-06-03 18:30:30 +10:00
for ( const { testName , addVariable , value , constraint } of cases ) {
2024-05-31 11:36:08 +10:00
test ( ` ${ testName } ` , async ( { page } ) = > {
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const yo = 5
2024-06-03 18:30:30 +10:00
const part001 = startSketchOn ( 'XZ' )
| > startProfileAt ( [ - 7.54 , - 26.74 ] , % )
| > line ( [ 74.36 , 130.4 ] , % )
| > line ( [ 78.92 , - 120.11 ] , % )
| > line ( [ 9.16 , 77.79 ] , % )
| > line ( [ 41.19 , 28.97 ] , % )
const part002 = startSketchOn ( 'XZ' )
| > startProfileAt ( [ 299.05 , 231.45 ] , % )
2024-06-24 22:39:04 -07:00
| > xLine ( - 425.34 , % , $seg_what )
2024-06-03 18:30:30 +10:00
| > yLine ( - 264.06 , % )
2024-06-24 22:39:04 -07:00
| > xLine ( segLen ( seg_what , % ) , % )
2024-06-03 18:30:30 +10:00
| > lineTo ( [ profileStartX ( % ) , profileStartY ( % ) ] , % ) `
2024-05-31 11:36:08 +10:00
)
} )
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-05-31 11:36:08 +10:00
await u . waitForAuthSkipAppStart ( )
await page . getByText ( 'line([74.36, 130.4], %)' ) . click ( )
await page . getByRole ( 'button' , { name : 'Edit Sketch' } ) . click ( )
const line3 = await u . getSegmentBodyCoords (
` [data-overlay-index=" ${ 2 } "] `
)
await page . mouse . click ( line3 . x , line3 . y )
await page
. getByRole ( 'button' , {
2024-06-24 11:37:48 -04:00
name : 'Constraints' ,
2024-05-31 11:36:08 +10:00
} )
. click ( )
2024-06-03 18:30:30 +10:00
await page . getByTestId ( constraint ) . click ( )
2024-05-31 11:36:08 +10:00
if ( ! addVariable ) {
await page . getByTestId ( 'create-new-variable-checkbox' ) . click ( )
}
await page
. getByRole ( 'button' , { name : 'Add constraining value' } )
. click ( )
2024-06-03 18:30:30 +10:00
const changedCode = ` |> angledLine([ ${ value } ], %) `
2024-05-31 11:36:08 +10:00
await expect ( page . locator ( '.cm-content' ) ) . toContainText ( changedCode )
// checking active assures the cursor is where it should be
await expect ( page . locator ( '.cm-activeLine' ) ) . toHaveText ( changedCode )
// 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 ( 4 )
} )
}
} )
2024-05-30 19:43:35 +10:00
test . describe ( 'Many segments - no modal constraints' , ( ) = > {
const cases = [
{
constraintName : 'Vertical' ,
codeAfter : [
` |> yLine(130.4, %) ` ,
` |> yLine(77.79, %) ` ,
` |> yLine(28.97, %) ` ,
] ,
} ,
{
codeAfter : [
` |> xLine(74.36, %) ` ,
` |> xLine(9.16, %) ` ,
` |> xLine(41.19, %) ` ,
] ,
constraintName : 'Horizontal' ,
} ,
] as const
for ( const { codeAfter , constraintName } of cases ) {
test ( ` ${ constraintName } ` , async ( { page } ) = > {
2024-06-03 22:40:59 +10:00
await page . addInitScript ( async ( customCode ) = > {
2024-05-30 19:43:35 +10:00
localStorage . setItem (
'persistCode' ,
` const yo = 5
const part001 = startSketchOn ( 'XZ' )
| > startProfileAt ( [ - 7.54 , - 26.74 ] , % )
| > line ( [ 74.36 , 130.4 ] , % )
| > line ( [ 78.92 , - 120.11 ] , % )
| > line ( [ 9.16 , 77.79 ] , % )
| > line ( [ 41.19 , 28.97 ] , % )
const part002 = startSketchOn ( 'XZ' )
| > startProfileAt ( [ 299.05 , 231.45 ] , % )
2024-06-24 22:39:04 -07:00
| > xLine ( - 425.34 , % , $seg_what )
2024-05-30 19:43:35 +10:00
| > yLine ( - 264.06 , % )
2024-06-24 22:39:04 -07:00
| > xLine ( segLen ( seg_what , % ) , % )
2024-05-30 19:43:35 +10:00
| > lineTo ( [ profileStartX ( % ) , profileStartY ( % ) ] , % ) `
)
} )
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-05-30 19:43:35 +10:00
await u . waitForAuthSkipAppStart ( )
await page . getByText ( 'line([74.36, 130.4], %)' ) . click ( )
await page . getByRole ( 'button' , { name : 'Edit Sketch' } ) . click ( )
2024-06-03 22:40:59 +10:00
const line1 = await u . getSegmentBodyCoords (
` [data-overlay-index=" ${ 0 } "] `
)
const line3 = await u . getSegmentBodyCoords (
` [data-overlay-index=" ${ 2 } "] `
)
const line4 = await u . getSegmentBodyCoords (
` [data-overlay-index=" ${ 3 } "] `
)
2024-05-30 19:43:35 +10:00
// select two segments by holding down shift
2024-06-03 22:40:59 +10:00
await page . mouse . click ( line1 . x , line1 . y )
2024-05-30 19:43:35 +10:00
await page . keyboard . down ( 'Shift' )
2024-06-03 22:40:59 +10:00
await page . mouse . click ( line3 . x , line3 . y )
await page . mouse . click ( line4 . x , line4 . y )
2024-05-30 19:43:35 +10:00
await page . keyboard . up ( 'Shift' )
2024-06-24 11:45:40 -04:00
// check actives lines
const activeLinesContent = await page . locator ( '.cm-activeLine' ) . all ( )
await expect ( activeLinesContent ) . toHaveLength ( codeAfter . length )
2024-05-30 19:43:35 +10:00
const constraintMenuButton = page . getByRole ( 'button' , {
2024-06-24 11:37:48 -04:00
name : 'Constraints' ,
2024-05-30 19:43:35 +10:00
} )
const constraintButton = page
. getByRole ( 'button' , {
name : constraintName ,
} )
. first ( )
// apply the constraint
await constraintMenuButton . click ( )
2024-06-24 11:45:40 -04:00
await constraintButton . click ( { delay : 200 } )
2024-05-30 19:43:35 +10:00
// check there are still 3 cursors (they should stay on the same lines as before constraint was applied)
await expect ( page . locator ( '.cm-cursor' ) ) . toHaveCount ( codeAfter . length )
// check both cursors are where they should be after constraint is applied and the code is correct
await Promise . all (
activeLinesContent . map ( async ( line , i ) = > {
await expect ( page . locator ( '.cm-content' ) ) . toContainText (
codeAfter [ i ]
)
// if the code is an active line then the cursor should be on that line
await expect ( line ) . toHaveText ( codeAfter [ i ] )
} )
)
} )
}
} )
2024-05-30 13:28:29 +10:00
test . describe ( 'Two segment - no modal constraints' , ( ) = > {
const cases = [
{
2024-06-24 22:39:04 -07:00
codeAfter : ` |> angledLine([83, segLen(seg01, %)], %) ` ,
2024-05-30 13:28:29 +10:00
constraintName : 'Equal Length' ,
} ,
{
2024-06-24 22:39:04 -07:00
codeAfter : ` |> angledLine([segAng(seg01, %), 78.33], %) ` ,
2024-05-30 13:28:29 +10:00
constraintName : 'Parallel' ,
} ,
{
2024-06-24 22:39:04 -07:00
codeAfter : ` |> lineTo([segEndX(seg01, %), 61.34], %) ` ,
2024-05-30 13:28:29 +10:00
constraintName : 'Vertically Align' ,
} ,
{
2024-06-24 22:39:04 -07:00
codeAfter : ` |> lineTo([154.9, segEndY(seg01, %)], %) ` ,
2024-05-30 13:28:29 +10:00
constraintName : 'Horizontally Align' ,
} ,
] as const
for ( const { codeAfter , constraintName } of cases ) {
test ( ` ${ constraintName } ` , async ( { page } ) = > {
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const yo = 5
const part001 = startSketchOn ( 'XZ' )
| > startProfileAt ( [ - 7.54 , - 26.74 ] , % )
| > line ( [ 74.36 , 130.4 ] , % )
| > line ( [ 78.92 , - 120.11 ] , % )
| > line ( [ 9.16 , 77.79 ] , % )
const part002 = startSketchOn ( 'XZ' )
| > startProfileAt ( [ 299.05 , 231.45 ] , % )
2024-06-24 22:39:04 -07:00
| > xLine ( - 425.34 , % , $seg_what )
2024-05-30 13:28:29 +10:00
| > yLine ( - 264.06 , % )
2024-06-24 22:39:04 -07:00
| > xLine ( segLen ( seg_what , % ) , % )
2024-05-30 13:28:29 +10:00
| > lineTo ( [ profileStartX ( % ) , profileStartY ( % ) ] , % ) `
)
} )
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-05-30 13:28:29 +10:00
await u . waitForAuthSkipAppStart ( )
await page . getByText ( 'line([74.36, 130.4], %)' ) . click ( )
await page . getByRole ( 'button' , { name : 'Edit Sketch' } ) . click ( )
const line1 = await u . getBoundingBox ( ` [data-overlay-index=" ${ 0 } "] ` )
const line3 = await u . getBoundingBox ( ` [data-overlay-index=" ${ 2 } "] ` )
// select two segments by holding down shift
await page . mouse . click ( line1 . x - 20 , line1 . y + 20 )
await page . keyboard . down ( 'Shift' )
await page . mouse . click ( line3 . x - 3 , line3 . y + 20 )
await page . keyboard . up ( 'Shift' )
const constraintMenuButton = page . getByRole ( 'button' , {
2024-06-24 11:37:48 -04:00
name : 'Constraints' ,
2024-05-30 13:28:29 +10:00
} )
const constraintButton = page . getByRole ( 'button' , {
name : constraintName ,
} )
// apply the constraint
await constraintMenuButton . click ( )
await constraintButton . click ( )
await expect ( page . locator ( '.cm-content' ) ) . toContainText ( codeAfter )
// expect the string 'seg01' to appear twice in '.cm-content' the tag segment and referencing the tag
const content = await page . locator ( '.cm-content' ) . innerText ( )
await expect ( content . match ( /seg01/g ) ) . toHaveLength ( 2 )
// check there are still 2 cursors (they should stay on the same lines as before constraint was applied)
await expect ( page . locator ( '.cm-cursor' ) ) . toHaveCount ( 2 )
// check actives lines
const activeLinesContent = await page . locator ( '.cm-activeLine' ) . all ( )
await expect ( activeLinesContent ) . toHaveLength ( 2 )
// check both cursors are where they should be after constraint is applied
await expect ( activeLinesContent [ 0 ] ) . toHaveText (
2024-06-24 22:39:04 -07:00
'|> line([74.36, 130.4], %, $seg01)'
2024-05-30 13:28:29 +10:00
)
await expect ( activeLinesContent [ 1 ] ) . toHaveText ( codeAfter )
} )
}
} )
test . describe ( 'Axis & segment - no modal constraints' , ( ) = > {
const cases = [
{
codeAfter : ` |> lineTo([154.9, ZERO], %) ` ,
axisClick : { x : 950 , y : 250 } ,
constraintName : 'Snap To X' ,
} ,
{
codeAfter : ` |> lineTo([ZERO, 61.34], %) ` ,
axisClick : { x : 600 , y : 150 } ,
constraintName : 'Snap To Y' ,
} ,
] as const
for ( const { codeAfter , constraintName , axisClick } of cases ) {
test ( ` ${ constraintName } ` , async ( { page } ) = > {
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const yo = 5
const part001 = startSketchOn ( 'XZ' )
| > startProfileAt ( [ - 7.54 , - 26.74 ] , % )
| > line ( [ 74.36 , 130.4 ] , % )
| > line ( [ 78.92 , - 120.11 ] , % )
| > line ( [ 9.16 , 77.79 ] , % )
const part002 = startSketchOn ( 'XZ' )
| > startProfileAt ( [ 299.05 , 231.45 ] , % )
2024-06-24 22:39:04 -07:00
| > xLine ( - 425.34 , % , $seg_what )
2024-05-30 13:28:29 +10:00
| > yLine ( - 264.06 , % )
2024-06-24 22:39:04 -07:00
| > xLine ( segLen ( seg_what , % ) , % )
2024-05-30 13:28:29 +10:00
| > lineTo ( [ profileStartX ( % ) , profileStartY ( % ) ] , % ) `
)
} )
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-05-30 13:28:29 +10:00
await u . waitForAuthSkipAppStart ( )
await page . getByText ( 'line([74.36, 130.4], %)' ) . click ( )
await page . getByRole ( 'button' , { name : 'Edit Sketch' } ) . click ( )
const line3 = await u . getBoundingBox ( ` [data-overlay-index=" ${ 2 } "] ` )
// select segment and axis by holding down shift
await page . mouse . click ( line3 . x - 3 , line3 . y + 20 )
await page . keyboard . down ( 'Shift' )
await page . waitForTimeout ( 100 )
await page . mouse . click ( axisClick . x , axisClick . y )
await page . keyboard . up ( 'Shift' )
const constraintMenuButton = page . getByRole ( 'button' , {
2024-06-24 11:37:48 -04:00
name : 'Constraints' ,
2024-05-30 13:28:29 +10:00
} )
const constraintButton = page . getByRole ( 'button' , {
name : constraintName ,
} )
// apply the constraint
await constraintMenuButton . click ( )
await expect ( constraintButton ) . toBeVisible ( )
await constraintButton . click ( )
// check the cursor is where is should be after constraint is applied
await expect ( page . locator ( '.cm-content' ) ) . toContainText ( codeAfter )
await expect ( page . locator ( '.cm-activeLine' ) ) . toHaveText ( codeAfter )
} )
}
} )
2024-06-22 04:49:31 -04:00
test ( 'Horizontally constrained line remains selected after applying constraint' , async ( {
page ,
} ) = > {
2024-07-02 17:16:27 +10:00
test . setTimeout ( 70 _000 )
2024-06-22 04:49:31 -04:00
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const sketch001 = startSketchOn('XY')
| > startProfileAt ( [ - 1.05 , - 1.07 ] , % )
2024-06-24 22:39:04 -07:00
| > line ( [ 3.79 , 2.68 ] , % , $seg01 )
2024-06-22 04:49:31 -04:00
| > line ( [ 3.13 , - 2.4 ] , % ) `
)
} )
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-06-22 04:49:31 -04:00
await u . waitForAuthSkipAppStart ( )
2024-06-24 22:39:04 -07:00
await page . getByText ( 'line([3.79, 2.68], %, $seg01)' ) . click ( )
2024-07-02 17:16:27 +10:00
await expect ( page . getByRole ( 'button' , { name : 'Edit Sketch' } ) ) . toBeEnabled (
{ timeout : 10_000 }
)
2024-06-22 04:49:31 -04:00
await page . getByRole ( 'button' , { name : 'Edit Sketch' } ) . click ( )
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' , {
2024-06-24 11:37:48 -04:00
name : 'Constraints' ,
2024-06-22 04:49:31 -04:00
} )
. click ( )
await page . getByRole ( 'button' , { name : 'horizontal' , exact : true } ) . click ( )
let activeLinesContent = await page . locator ( '.cm-activeLine' ) . all ( )
await expect ( activeLinesContent [ 0 ] ) . toHaveText ( ` |> xLine(3.13, %) ` )
// If the overlay-angle is updated the THREE.js scene is in a good state
await expect (
await page . locator ( '[data-overlay-index="1"]' )
) . toHaveAttribute ( 'data-overlay-angle' , '0' )
const lineAfter = await u . getSegmentBodyCoords (
` [data-overlay-index="1"] ` ,
0
)
expect (
await u . getGreatestPixDiff ( lineAfter , TEST_COLORS . BLUE )
) . toBeLessThan ( 3 )
2024-07-02 17:16:27 +10:00
await page . waitForTimeout ( 300 )
2024-06-22 04:49:31 -04:00
await page
. getByRole ( 'button' , {
2024-06-24 11:37:48 -04:00
name : 'Constraints' ,
2024-06-22 04:49:31 -04:00
} )
. click ( )
2024-07-02 17:16:27 +10:00
// 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 . locator ( '[data-testid="length"]' ) . click ( )
2024-06-22 04:49:31 -04:00
await page . getByLabel ( 'length Value' ) . fill ( '10' )
await page . getByRole ( 'button' , { name : 'Add constraining value' } ) . click ( )
activeLinesContent = await page . locator ( '.cm-activeLine' ) . all ( )
await expect ( activeLinesContent [ 0 ] ) . toHaveText ( ` |> xLine(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 )
} )
2024-05-30 13:28:29 +10:00
} )
2024-05-24 20:54:42 +10:00
test . describe ( 'Testing segment overlays' , ( ) = > {
test . describe ( 'Hover over a segment should show its overlay, hovering over the input overlays should show its popover, clicking the input overlay should constrain/unconstrain it:\nfor the following segments' , ( ) = > {
/ * *
* Clicks on an constrained element
* @param { Page } page - The page to perform the action on
* @param { Object } options - The options for the action
* @param { Object } options . hoverPos - The position to hover over
* @param { Object } options . constraintType - The type of constraint
* @param { number } options . ang - The angle
* @param { number } options . steps - The number of steps to perform
* /
const _clickConstrained =
( page : Page ) = >
async ( {
hoverPos ,
constraintType ,
expectBeforeUnconstrained ,
expectAfterUnconstrained ,
expectFinal ,
ang = 45 ,
2024-06-04 08:32:24 -04:00
steps = 10 ,
2024-06-24 11:45:40 -04:00
locator ,
2024-05-24 20:54:42 +10:00
} : {
hoverPos : { x : number ; y : number }
constraintType :
| 'horizontal'
| 'vertical'
| 'tangentialWithPrevious'
| LineInputsType
expectBeforeUnconstrained : string
expectAfterUnconstrained : string
expectFinal : string
ang? : number
steps? : number
2024-06-24 11:45:40 -04:00
locator? : string
2024-05-24 20:54:42 +10:00
} ) = > {
await expect ( page . getByText ( 'Added variable' ) ) . not . toBeVisible ( )
2024-06-04 08:32:24 -04:00
await page . mouse . move ( 0 , 0 )
await page . waitForTimeout ( 1000 )
let x = 0 ,
y = 0
x = hoverPos . x + Math . cos ( ang * deg ) * 32
y = hoverPos . y - Math . sin ( ang * deg ) * 32
await page . mouse . move ( x , y )
2024-06-24 11:45:40 -04:00
await wiggleMove ( page , x , y , 20 , 30 , ang , 10 , 5 , locator )
2024-06-04 08:32:24 -04:00
2024-05-24 20:54:42 +10:00
await expect ( page . locator ( '.cm-content' ) ) . toContainText (
expectBeforeUnconstrained
)
const constrainedLocator = page . locator (
` [data-constraint-type=" ${ constraintType } "][data-is-constrained="true"] `
)
await expect ( constrainedLocator ) . toBeVisible ( )
await constrainedLocator . hover ( )
await expect (
await page . getByTestId ( 'constraint-symbol-popover' ) . count ( )
) . toBeGreaterThan ( 0 )
await constrainedLocator . click ( )
await expect ( page . locator ( '.cm-content' ) ) . toContainText (
expectAfterUnconstrained
)
2024-06-04 08:32:24 -04:00
await page . mouse . move ( 0 , 0 )
await page . waitForTimeout ( 1000 )
x = hoverPos . x + Math . cos ( ang * deg ) * 32
y = hoverPos . y - Math . sin ( ang * deg ) * 32
await page . mouse . move ( x , y )
2024-06-24 11:45:40 -04:00
await wiggleMove ( page , x , y , 20 , 30 , ang , 10 , 5 , locator )
2024-06-04 08:32:24 -04:00
2024-05-24 20:54:42 +10:00
const unconstrainedLocator = page . locator (
` [data-constraint-type=" ${ constraintType } "][data-is-constrained="false"] `
)
await expect ( unconstrainedLocator ) . toBeVisible ( )
await unconstrainedLocator . hover ( )
await expect (
await page . getByTestId ( 'constraint-symbol-popover' ) . count ( )
) . toBeGreaterThan ( 0 )
await unconstrainedLocator . click ( )
await page . getByText ( 'Add variable' ) . click ( )
await expect ( page . locator ( '.cm-content' ) ) . toContainText ( expectFinal )
}
/ * *
* Clicks on an unconstrained element
* @param { Page } page - The page to perform the action on
* @param { Object } options - The options for the action
* @param { Object } options . hoverPos - The position to hover over
* @param { Object } options . constraintType - The type of constraint
* @param { number } options . ang - The angle
* @param { number } options . steps - The number of steps to perform
* /
const _clickUnconstrained =
( page : Page ) = >
async ( {
hoverPos ,
constraintType ,
expectBeforeUnconstrained ,
expectAfterUnconstrained ,
expectFinal ,
ang = 45 ,
steps = 5 ,
2024-06-24 11:45:40 -04:00
locator ,
2024-05-24 20:54:42 +10:00
} : {
hoverPos : { x : number ; y : number }
constraintType :
| 'horizontal'
| 'vertical'
| 'tangentialWithPrevious'
| LineInputsType
expectBeforeUnconstrained : string
expectAfterUnconstrained : string
expectFinal : string
ang? : number
steps? : number
2024-06-24 11:45:40 -04:00
locator? : string
2024-05-24 20:54:42 +10:00
} ) = > {
2024-06-04 08:32:24 -04:00
await page . mouse . move ( 0 , 0 )
await page . waitForTimeout ( 1000 )
let x = 0 ,
y = 0
x = hoverPos . x + Math . cos ( ang * deg ) * 32
y = hoverPos . y - Math . sin ( ang * deg ) * 32
await page . mouse . move ( x , y )
2024-06-24 11:45:40 -04:00
await wiggleMove ( page , x , y , 20 , 30 , ang , 10 , 5 , locator )
2024-05-24 20:54:42 +10:00
await expect ( page . getByText ( 'Added variable' ) ) . not . toBeVisible ( )
await expect ( page . locator ( '.cm-content' ) ) . toContainText (
expectBeforeUnconstrained
)
const unconstrainedLocator = page . locator (
` [data-constraint-type=" ${ constraintType } "][data-is-constrained="false"] `
)
await expect ( unconstrainedLocator ) . toBeVisible ( )
await unconstrainedLocator . hover ( )
await expect (
await page . getByTestId ( 'constraint-symbol-popover' ) . count ( )
) . toBeGreaterThan ( 0 )
await unconstrainedLocator . click ( )
await page . getByText ( 'Add variable' ) . click ( )
await expect ( page . locator ( '.cm-content' ) ) . toContainText (
expectAfterUnconstrained
)
await expect ( page . getByText ( 'Added variable' ) ) . not . toBeVisible ( )
2024-06-04 08:32:24 -04:00
await page . mouse . move ( 0 , 0 )
await page . waitForTimeout ( 1000 )
x = hoverPos . x + Math . cos ( ang * deg ) * 32
y = hoverPos . y - Math . sin ( ang * deg ) * 32
await page . mouse . move ( x , y )
2024-06-24 11:45:40 -04:00
await wiggleMove ( page , x , y , 20 , 30 , ang , 10 , 5 , locator )
2024-06-04 08:32:24 -04:00
2024-05-24 20:54:42 +10:00
const constrainedLocator = page . locator (
` [data-constraint-type=" ${ constraintType } "][data-is-constrained="true"] `
)
await expect ( constrainedLocator ) . toBeVisible ( )
await constrainedLocator . hover ( )
await expect (
await page . getByTestId ( 'constraint-symbol-popover' ) . count ( )
) . toBeGreaterThan ( 0 )
await constrainedLocator . click ( )
await expect ( page . locator ( '.cm-content' ) ) . toContainText ( expectFinal )
}
2024-06-04 08:32:24 -04:00
test . setTimeout ( 120000 )
2024-05-24 20:54:42 +10:00
test ( 'for segments [line, angledLine, lineTo, xLineTo]' , async ( {
page ,
} ) = > {
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const part001 = startSketchOn('XZ')
2024-06-04 08:32:24 -04:00
| > startProfileAt ( [ 5 + 0 , 20 + 0 ] , % )
2024-05-24 20:54:42 +10:00
| > line ( [ 0.5 , - 14 + 0 ] , % )
| > angledLine ( { angle : 3 + 0 , length : 32 + 0 } , % )
2024-06-04 08:32:24 -04:00
| > lineTo ( [ 5 + 33 , 20 + 11.5 + 0 ] , % )
| > xLineTo ( 5 + 9 - 5 , % )
2024-06-24 22:39:04 -07:00
| > yLineTo ( 20 + - 10.77 , % , $a )
2024-05-24 20:54:42 +10:00
| > xLine ( 26.04 , % )
| > yLine ( 21.14 + 0 , % )
| > angledLineOfXLength ( { angle : 181 + 0 , length : 23.14 } , % )
| > angledLineOfYLength ( { angle : - 91 , length : 19 + 0 } , % )
2024-06-04 08:32:24 -04:00
| > angledLineToX ( { angle : 3 + 0 , to : 5 + 26 } , % )
| > angledLineToY ( { angle : 89 , to : 20 + 9.14 + 0 } , % )
2024-05-24 20:54:42 +10:00
| > angledLineThatIntersects ( {
angle : 4.14 ,
2024-06-24 22:39:04 -07:00
intersectTag : a ,
2024-05-24 20:54:42 +10:00
offset : 9
} , % )
2024-06-04 08:32:24 -04:00
| > tangentialArcTo ( [ 5 + 3.14 + 13 , 20 + 3.14 ] , % )
2024-05-24 20:54:42 +10:00
`
)
} )
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-05-24 20:54:42 +10:00
await u . waitForAuthSkipAppStart ( )
2024-05-24 12:32:15 -07:00
// wait for execution done
await u . openDebugPanel ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await u . closeDebugPanel ( )
2024-06-06 16:48:54 -07:00
await page . getByText ( 'xLineTo(5 + 9 - 5, %)' ) . click ( )
await page . waitForTimeout ( 100 )
await page . getByRole ( 'button' , { name : 'Edit Sketch' } ) . click ( )
await page . waitForTimeout ( 500 )
await expect ( page . getByTestId ( 'segment-overlay' ) ) . toHaveCount ( 13 )
const clickUnconstrained = _clickUnconstrained ( page )
const clickConstrained = _clickConstrained ( page )
2024-05-24 20:54:42 +10:00
await u . openAndClearDebugPanel ( )
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_look_at' ,
2024-06-06 16:48:54 -07:00
vantage : { x : 80 , y : - 1350 , z : 510 } ,
center : { x : 80 , y : 0 , z : 510 } ,
2024-05-24 20:54:42 +10:00
up : { x : 0 , y : 0 , z : 1 } ,
} ,
} )
await page . waitForTimeout ( 100 )
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_get_settings' ,
} ,
} )
await page . waitForTimeout ( 100 )
2024-06-04 08:32:24 -04:00
await u . closeDebugPanel ( )
2024-05-24 20:54:42 +10:00
2024-06-04 08:32:24 -04:00
let ang = 0
2024-05-24 20:54:42 +10:00
const line = await u . getBoundingBox ( ` [data-overlay-index=" ${ 0 } "] ` )
2024-06-04 08:32:24 -04:00
ang = await u . getAngle ( ` [data-overlay-index=" ${ 0 } "] ` )
console . log ( 'line1' , line , ang )
2024-05-24 20:54:42 +10:00
await clickConstrained ( {
2024-06-04 08:32:24 -04:00
hoverPos : { x : line.x , y : line.y } ,
2024-05-24 20:54:42 +10:00
constraintType : 'yRelative' ,
expectBeforeUnconstrained : '|> line([0.5, -14 + 0], %)' ,
expectAfterUnconstrained : '|> line([0.5, -14], %)' ,
expectFinal : '|> line([0.5, yRel001], %)' ,
2024-06-04 08:32:24 -04:00
ang : ang + 180 ,
2024-06-24 11:45:40 -04:00
locator : '[data-overlay-toolbar-index="0"]' ,
2024-05-24 20:54:42 +10:00
} )
console . log ( 'line2' )
await clickUnconstrained ( {
2024-06-04 08:32:24 -04:00
hoverPos : { x : line.x , y : line.y } ,
2024-05-24 20:54:42 +10:00
constraintType : 'xRelative' ,
expectBeforeUnconstrained : '|> line([0.5, yRel001], %)' ,
expectAfterUnconstrained : 'line([xRel001, yRel001], %)' ,
expectFinal : '|> line([0.5, yRel001], %)' ,
2024-06-04 08:32:24 -04:00
ang : ang + 180 ,
2024-06-24 11:45:40 -04:00
locator : '[data-overlay-index="0"]' ,
2024-05-24 20:54:42 +10:00
} )
const angledLine = await u . getBoundingBox ( ` [data-overlay-index="1"] ` )
2024-06-04 08:32:24 -04:00
ang = await u . getAngle ( ` [data-overlay-index="1"] ` )
2024-05-24 20:54:42 +10:00
console . log ( 'angledLine1' )
await clickConstrained ( {
2024-06-04 08:32:24 -04:00
hoverPos : { x : angledLine.x , y : angledLine.y } ,
2024-05-24 20:54:42 +10:00
constraintType : 'angle' ,
expectBeforeUnconstrained :
'angledLine({ angle: 3 + 0, length: 32 + 0 }, %)' ,
expectAfterUnconstrained : 'angledLine({ angle: 3, length: 32 + 0 }, %)' ,
expectFinal : 'angledLine({ angle: angle001, length: 32 + 0 }, %)' ,
2024-06-04 08:32:24 -04:00
ang : ang + 180 ,
2024-06-24 11:45:40 -04:00
locator : '[data-overlay-toolbar-index="1"]' ,
2024-05-24 20:54:42 +10:00
} )
console . log ( 'angledLine2' )
await clickConstrained ( {
2024-06-04 08:32:24 -04:00
hoverPos : { x : angledLine.x , y : angledLine.y } ,
2024-05-24 20:54:42 +10:00
constraintType : 'length' ,
expectBeforeUnconstrained :
'angledLine({ angle: angle001, length: 32 + 0 }, %)' ,
expectAfterUnconstrained :
'angledLine({ angle: angle001, length: 32 }, %)' ,
expectFinal : 'angledLine({ angle: angle001, length: len001 }, %)' ,
2024-06-04 08:32:24 -04:00
ang : ang + 180 ,
2024-06-24 11:45:40 -04:00
locator : '[data-overlay-toolbar-index="1"]' ,
2024-05-24 20:54:42 +10:00
} )
await page . mouse . move ( 700 , 250 )
2024-06-06 16:48:54 -07:00
await page . waitForTimeout ( 100 )
2024-05-24 20:54:42 +10:00
2024-06-04 08:32:24 -04:00
let lineTo = await u . getBoundingBox ( ` [data-overlay-index="2"] ` )
ang = await u . getAngle ( ` [data-overlay-index="2"] ` )
2024-05-24 20:54:42 +10:00
console . log ( 'lineTo1' )
await clickConstrained ( {
2024-06-04 08:32:24 -04:00
hoverPos : { x : lineTo.x , y : lineTo.y } ,
2024-05-24 20:54:42 +10:00
constraintType : 'yAbsolute' ,
2024-06-04 08:32:24 -04:00
expectBeforeUnconstrained : 'lineTo([5 + 33, 20 + 11.5 + 0], %)' ,
expectAfterUnconstrained : 'lineTo([5 + 33, 31.5], %)' ,
expectFinal : 'lineTo([5 + 33, yAbs001], %)' ,
2024-05-24 20:54:42 +10:00
steps : 8 ,
2024-06-04 08:32:24 -04:00
ang : ang + 180 ,
2024-06-24 11:45:40 -04:00
locator : '[data-overlay-toolbar-index="2"]' ,
2024-05-24 20:54:42 +10:00
} )
console . log ( 'lineTo2' )
2024-06-04 08:32:24 -04:00
await clickConstrained ( {
hoverPos : { x : lineTo.x , y : lineTo.y } ,
2024-05-24 20:54:42 +10:00
constraintType : 'xAbsolute' ,
2024-06-04 08:32:24 -04:00
expectBeforeUnconstrained : 'lineTo([5 + 33, yAbs001], %)' ,
expectAfterUnconstrained : 'lineTo([38, yAbs001], %)' ,
expectFinal : 'lineTo([xAbs001, yAbs001], %)' ,
2024-05-24 20:54:42 +10:00
steps : 8 ,
2024-06-04 08:32:24 -04:00
ang : ang + 180 ,
2024-06-24 11:45:40 -04:00
locator : '[data-overlay-toolbar-index="2"]' ,
2024-05-24 20:54:42 +10:00
} )
const xLineTo = await u . getBoundingBox ( ` [data-overlay-index="3"] ` )
2024-06-04 08:32:24 -04:00
ang = await u . getAngle ( ` [data-overlay-index="3"] ` )
2024-05-24 20:54:42 +10:00
console . log ( 'xlineTo1' )
await clickConstrained ( {
2024-06-04 08:32:24 -04:00
hoverPos : { x : xLineTo.x , y : xLineTo.y } ,
2024-05-24 20:54:42 +10:00
constraintType : 'xAbsolute' ,
2024-06-04 08:32:24 -04:00
expectBeforeUnconstrained : 'xLineTo(5 + 9 - 5, %)' ,
expectAfterUnconstrained : 'xLineTo(9, %)' ,
2024-05-24 20:54:42 +10:00
expectFinal : 'xLineTo(xAbs002, %)' ,
2024-06-04 08:32:24 -04:00
ang : ang + 180 ,
2024-05-24 20:54:42 +10:00
steps : 8 ,
2024-06-24 11:45:40 -04:00
locator : '[data-overlay-toolbar-index="3"]' ,
2024-05-24 20:54:42 +10:00
} )
} )
test ( 'for segments [yLineTo, xLine]' , async ( { page } ) = > {
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const yRel001 = -14
const xRel001 = 0.5
const angle001 = 3
const len001 = 32
const yAbs001 = 11.5
const xAbs001 = 33
const xAbs002 = 4
const part001 = startSketchOn ( 'XZ' )
| > startProfileAt ( [ 0 , 0 ] , % )
| > line ( [ 0.5 , yRel001 ] , % )
| > angledLine ( { angle : angle001 , length : len001 } , % )
| > lineTo ( [ 33 , yAbs001 ] , % )
| > xLineTo ( xAbs002 , % )
2024-06-24 22:39:04 -07:00
| > yLineTo ( - 10.77 , % , $a )
2024-05-24 20:54:42 +10:00
| > xLine ( 26.04 , % )
| > yLine ( 21.14 + 0 , % )
| > angledLineOfXLength ( { angle : 181 + 0 , length : 23.14 } , % )
`
)
} )
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-05-24 20:54:42 +10:00
await u . waitForAuthSkipAppStart ( )
2024-05-24 12:32:15 -07:00
// wait for execution done
await u . openDebugPanel ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await u . closeDebugPanel ( )
2024-05-24 20:54:42 +10:00
await page . getByText ( 'xLine(26.04, %)' ) . click ( )
await page . waitForTimeout ( 100 )
await page . getByRole ( 'button' , { name : 'Edit Sketch' } ) . click ( )
await page . waitForTimeout ( 500 )
await expect ( page . getByTestId ( 'segment-overlay' ) ) . toHaveCount ( 8 )
const clickUnconstrained = _clickUnconstrained ( page )
await page . mouse . move ( 700 , 250 )
2024-06-06 16:48:54 -07:00
await page . waitForTimeout ( 100 )
2024-05-24 20:54:42 +10:00
2024-06-04 08:32:24 -04:00
let ang = 0
2024-05-24 20:54:42 +10:00
const yLineTo = await u . getBoundingBox ( ` [data-overlay-index="4"] ` )
2024-06-04 08:32:24 -04:00
ang = await u . getAngle ( ` [data-overlay-index="4"] ` )
2024-05-24 20:54:42 +10:00
console . log ( 'ylineTo1' )
await clickUnconstrained ( {
2024-06-04 08:32:24 -04:00
hoverPos : { x : yLineTo.x , y : yLineTo.y } ,
2024-05-24 20:54:42 +10:00
constraintType : 'yAbsolute' ,
2024-06-24 22:39:04 -07:00
expectBeforeUnconstrained : 'yLineTo(-10.77, %, $a)' ,
expectAfterUnconstrained : 'yLineTo(yAbs002, %, $a)' ,
expectFinal : 'yLineTo(-10.77, %, $a)' ,
2024-06-04 08:32:24 -04:00
ang : ang + 180 ,
2024-06-24 11:45:40 -04:00
locator : '[data-overlay-toolbar-index="4"]' ,
2024-05-24 20:54:42 +10:00
} )
const xLine = await u . getBoundingBox ( ` [data-overlay-index="5"] ` )
2024-06-04 08:32:24 -04:00
ang = await u . getAngle ( ` [data-overlay-index="5"] ` )
2024-05-24 20:54:42 +10:00
console . log ( 'xline' )
await clickUnconstrained ( {
2024-06-04 08:32:24 -04:00
hoverPos : { x : xLine.x , y : xLine.y } ,
2024-05-24 20:54:42 +10:00
constraintType : 'xRelative' ,
expectBeforeUnconstrained : 'xLine(26.04, %)' ,
expectAfterUnconstrained : 'xLine(xRel002, %)' ,
expectFinal : 'xLine(26.04, %)' ,
steps : 10 ,
2024-06-04 08:32:24 -04:00
ang : ang + 180 ,
2024-06-24 11:45:40 -04:00
locator : '[data-overlay-toolbar-index="5"]' ,
2024-05-24 20:54:42 +10:00
} )
} )
test ( 'for segments [yLine, angledLineOfXLength, angledLineOfYLength]' , async ( {
page ,
} ) = > {
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const part001 = startSketchOn('XZ')
| > startProfileAt ( [ 0 , 0 ] , % )
| > line ( [ 0.5 , - 14 + 0 ] , % )
| > angledLine ( { angle : 3 + 0 , length : 32 + 0 } , % )
| > lineTo ( [ 33 , 11.5 + 0 ] , % )
| > xLineTo ( 9 - 5 , % )
2024-06-24 22:39:04 -07:00
| > yLineTo ( - 10.77 , % , $a )
2024-05-24 20:54:42 +10:00
| > xLine ( 26.04 , % )
| > yLine ( 21.14 + 0 , % )
| > angledLineOfXLength ( { angle : 181 + 0 , length : 23.14 } , % )
| > angledLineOfYLength ( { angle : - 91 , length : 19 + 0 } , % )
| > angledLineToX ( { angle : 3 + 0 , to : 26 } , % )
| > angledLineToY ( { angle : 89 , to : 9.14 + 0 } , % )
| > angledLineThatIntersects ( {
angle : 4.14 ,
2024-06-24 22:39:04 -07:00
intersectTag : a ,
2024-05-24 20:54:42 +10:00
offset : 9
} , % )
| > tangentialArcTo ( [ 3.14 + 13 , 3.14 ] , % )
`
)
2024-06-24 11:45:40 -04:00
localStorage . setItem ( 'disableAxis' , 'true' )
2024-05-24 20:54:42 +10:00
} )
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-05-24 20:54:42 +10:00
await u . waitForAuthSkipAppStart ( )
2024-05-24 12:32:15 -07:00
// wait for execution done
await u . openDebugPanel ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await u . closeDebugPanel ( )
2024-06-04 08:32:24 -04:00
await page . waitForTimeout ( 500 )
2024-05-24 12:32:15 -07:00
2024-05-24 20:54:42 +10:00
await page . getByText ( 'xLineTo(9 - 5, %)' ) . click ( )
await page . waitForTimeout ( 100 )
await page . getByRole ( 'button' , { name : 'Edit Sketch' } ) . click ( )
await page . waitForTimeout ( 500 )
await expect ( page . getByTestId ( 'segment-overlay' ) ) . toHaveCount ( 13 )
const clickUnconstrained = _clickUnconstrained ( page )
const clickConstrained = _clickConstrained ( page )
2024-06-04 08:32:24 -04:00
let ang = 0
2024-05-24 20:54:42 +10:00
const yLine = await u . getBoundingBox ( ` [data-overlay-index="6"] ` )
2024-06-04 08:32:24 -04:00
ang = await u . getAngle ( ` [data-overlay-index="6"] ` )
2024-05-24 20:54:42 +10:00
console . log ( 'yline1' )
await clickConstrained ( {
2024-06-24 11:45:40 -04:00
hoverPos : { x : yLine.x , y : yLine.y } ,
2024-05-24 20:54:42 +10:00
constraintType : 'yRelative' ,
expectBeforeUnconstrained : 'yLine(21.14 + 0, %)' ,
expectAfterUnconstrained : 'yLine(21.14, %)' ,
expectFinal : 'yLine(yRel001, %)' ,
2024-06-04 08:32:24 -04:00
ang : ang + 180 ,
2024-06-24 11:45:40 -04:00
locator : '[data-overlay-toolbar-index="6"]' ,
2024-05-24 20:54:42 +10:00
} )
const angledLineOfXLength = await u . getBoundingBox (
` [data-overlay-index="7"] `
)
2024-06-04 08:32:24 -04:00
ang = await u . getAngle ( ` [data-overlay-index="7"] ` )
2024-05-24 20:54:42 +10:00
console . log ( 'angledLineOfXLength1' )
await clickConstrained ( {
2024-06-24 11:45:40 -04:00
hoverPos : { x : angledLineOfXLength.x , y : angledLineOfXLength.y } ,
2024-05-24 20:54:42 +10:00
constraintType : 'angle' ,
expectBeforeUnconstrained :
'angledLineOfXLength({ angle: 181 + 0, length: 23.14 }, %)' ,
expectAfterUnconstrained :
'angledLineOfXLength({ angle: -179, length: 23.14 }, %)' ,
expectFinal :
'angledLineOfXLength({ angle: angle001, length: 23.14 }, %)' ,
2024-06-04 08:32:24 -04:00
ang : ang + 180 ,
2024-06-24 11:45:40 -04:00
locator : '[data-overlay-toolbar-index="7"]' ,
2024-05-24 20:54:42 +10:00
} )
console . log ( 'angledLineOfXLength2' )
await clickUnconstrained ( {
2024-06-24 11:45:40 -04:00
hoverPos : { x : angledLineOfXLength.x , y : angledLineOfXLength.y } ,
2024-05-24 20:54:42 +10:00
constraintType : 'xRelative' ,
expectBeforeUnconstrained :
'angledLineOfXLength({ angle: angle001, length: 23.14 }, %)' ,
expectAfterUnconstrained :
'angledLineOfXLength({ angle: angle001, length: xRel001 }, %)' ,
expectFinal :
'angledLineOfXLength({ angle: angle001, length: 23.14 }, %)' ,
steps : 7 ,
2024-06-04 08:32:24 -04:00
ang : ang + 180 ,
2024-06-24 11:45:40 -04:00
locator : '[data-overlay-toolbar-index="7"]' ,
2024-05-24 20:54:42 +10:00
} )
const angledLineOfYLength = await u . getBoundingBox (
` [data-overlay-index="8"] `
)
2024-06-04 08:32:24 -04:00
ang = await u . getAngle ( ` [data-overlay-index="8"] ` )
2024-05-24 20:54:42 +10:00
console . log ( 'angledLineOfYLength1' )
await clickUnconstrained ( {
2024-06-24 11:45:40 -04:00
hoverPos : { x : angledLineOfYLength.x , y : angledLineOfYLength.y } ,
2024-05-24 20:54:42 +10:00
constraintType : 'angle' ,
expectBeforeUnconstrained :
'angledLineOfYLength({ angle: -91, length: 19 + 0 }, %)' ,
expectAfterUnconstrained :
'angledLineOfYLength({ angle: angle002, length: 19 + 0 }, %)' ,
expectFinal : 'angledLineOfYLength({ angle: -91, length: 19 + 0 }, %)' ,
2024-06-04 08:32:24 -04:00
ang : ang + 180 ,
2024-05-24 20:54:42 +10:00
steps : 6 ,
2024-06-24 11:45:40 -04:00
locator : '[data-overlay-toolbar-index="8"]' ,
2024-05-24 20:54:42 +10:00
} )
console . log ( 'angledLineOfYLength2' )
await clickConstrained ( {
2024-06-24 11:45:40 -04:00
hoverPos : { x : angledLineOfYLength.x , y : angledLineOfYLength.y } ,
2024-05-24 20:54:42 +10:00
constraintType : 'yRelative' ,
expectBeforeUnconstrained :
'angledLineOfYLength({ angle: -91, length: 19 + 0 }, %)' ,
expectAfterUnconstrained :
'angledLineOfYLength({ angle: -91, length: 19 }, %)' ,
expectFinal : 'angledLineOfYLength({ angle: -91, length: yRel002 }, %)' ,
2024-06-04 08:32:24 -04:00
ang : ang + 180 ,
2024-05-24 20:54:42 +10:00
steps : 7 ,
2024-06-24 11:45:40 -04:00
locator : '[data-overlay-toolbar-index="8"]' ,
2024-05-24 20:54:42 +10:00
} )
} )
test ( 'for segments [angledLineToX, angledLineToY, angledLineThatIntersects]' , async ( {
page ,
} ) = > {
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const part001 = startSketchOn('XZ')
| > startProfileAt ( [ 0 , 0 ] , % )
| > line ( [ 0.5 , - 14 + 0 ] , % )
| > angledLine ( { angle : 3 + 0 , length : 32 + 0 } , % )
| > lineTo ( [ 33 , 11.5 + 0 ] , % )
| > xLineTo ( 9 - 5 , % )
2024-06-24 22:39:04 -07:00
| > yLineTo ( - 10.77 , % , $a )
2024-05-24 20:54:42 +10:00
| > xLine ( 26.04 , % )
| > yLine ( 21.14 + 0 , % )
| > angledLineOfXLength ( { angle : 181 + 0 , length : 23.14 } , % )
| > angledLineOfYLength ( { angle : - 91 , length : 19 + 0 } , % )
| > angledLineToX ( { angle : 3 + 0 , to : 26 } , % )
| > angledLineToY ( { angle : 89 , to : 9.14 + 0 } , % )
| > angledLineThatIntersects ( {
angle : 4.14 ,
2024-06-24 22:39:04 -07:00
intersectTag : a ,
2024-05-24 20:54:42 +10:00
offset : 9
} , % )
| > tangentialArcTo ( [ 3.14 + 13 , 1.14 ] , % )
`
)
2024-06-24 11:45:40 -04:00
localStorage . setItem ( 'disableAxis' , 'true' )
2024-05-24 20:54:42 +10:00
} )
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-05-24 20:54:42 +10:00
await u . waitForAuthSkipAppStart ( )
2024-05-24 12:32:15 -07:00
// wait for execution done
await u . openDebugPanel ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await u . closeDebugPanel ( )
2024-05-24 20:54:42 +10:00
await page . getByText ( 'xLineTo(9 - 5, %)' ) . click ( )
await page . waitForTimeout ( 100 )
await page . getByRole ( 'button' , { name : 'Edit Sketch' } ) . click ( )
await page . waitForTimeout ( 500 )
await expect ( page . getByTestId ( 'segment-overlay' ) ) . toHaveCount ( 13 )
const clickUnconstrained = _clickUnconstrained ( page )
const clickConstrained = _clickConstrained ( page )
2024-06-04 08:32:24 -04:00
let ang = 0
2024-05-24 20:54:42 +10:00
const angledLineToX = await u . getBoundingBox ( ` [data-overlay-index="9"] ` )
2024-06-04 08:32:24 -04:00
ang = await u . getAngle ( ` [data-overlay-index="9"] ` )
2024-05-24 20:54:42 +10:00
console . log ( 'angledLineToX' )
await clickConstrained ( {
2024-06-04 08:32:24 -04:00
hoverPos : { x : angledLineToX.x , y : angledLineToX.y } ,
2024-05-24 20:54:42 +10:00
constraintType : 'angle' ,
expectBeforeUnconstrained : 'angledLineToX({ angle: 3 + 0, to: 26 }, %)' ,
expectAfterUnconstrained : 'angledLineToX({ angle: 3, to: 26 }, %)' ,
expectFinal : 'angledLineToX({ angle: angle001, to: 26 }, %)' ,
2024-06-04 08:32:24 -04:00
ang : ang + 180 ,
2024-06-24 11:45:40 -04:00
locator : '[data-overlay-toolbar-index="9"]' ,
2024-05-24 20:54:42 +10:00
} )
console . log ( 'angledLineToX2' )
await clickUnconstrained ( {
2024-06-24 11:45:40 -04:00
hoverPos : { x : angledLineToX.x , y : angledLineToX.y } ,
2024-05-24 20:54:42 +10:00
constraintType : 'xAbsolute' ,
expectBeforeUnconstrained :
'angledLineToX({ angle: angle001, to: 26 }, %)' ,
expectAfterUnconstrained :
'angledLineToX({ angle: angle001, to: xAbs001 }, %)' ,
expectFinal : 'angledLineToX({ angle: angle001, to: 26 }, %)' ,
2024-06-04 08:32:24 -04:00
ang : ang + 180 ,
2024-06-24 11:45:40 -04:00
locator : '[data-overlay-toolbar-index="9"]' ,
2024-05-24 20:54:42 +10:00
} )
const angledLineToY = await u . getBoundingBox ( ` [data-overlay-index="10"] ` )
2024-06-04 08:32:24 -04:00
ang = await u . getAngle ( ` [data-overlay-index="10"] ` )
2024-05-24 20:54:42 +10:00
console . log ( 'angledLineToY' )
await clickUnconstrained ( {
2024-06-04 08:32:24 -04:00
hoverPos : { x : angledLineToY.x , y : angledLineToY.y } ,
2024-05-24 20:54:42 +10:00
constraintType : 'angle' ,
expectBeforeUnconstrained :
'angledLineToY({ angle: 89, to: 9.14 + 0 }, %)' ,
expectAfterUnconstrained :
'angledLineToY({ angle: angle002, to: 9.14 + 0 }, %)' ,
expectFinal : 'angledLineToY({ angle: 89, to: 9.14 + 0 }, %)' ,
steps : process.platform === 'darwin' ? 8 : 9 ,
2024-06-04 08:32:24 -04:00
ang : ang + 180 ,
2024-06-24 11:45:40 -04:00
locator : '[data-overlay-toolbar-index="10"]' ,
2024-05-24 20:54:42 +10:00
} )
console . log ( 'angledLineToY2' )
await clickConstrained ( {
2024-06-24 11:45:40 -04:00
hoverPos : { x : angledLineToY.x , y : angledLineToY.y } ,
2024-05-24 20:54:42 +10:00
constraintType : 'yAbsolute' ,
expectBeforeUnconstrained :
'angledLineToY({ angle: 89, to: 9.14 + 0 }, %)' ,
expectAfterUnconstrained : 'angledLineToY({ angle: 89, to: 9.14 }, %)' ,
expectFinal : 'angledLineToY({ angle: 89, to: yAbs001 }, %)' ,
2024-06-04 08:32:24 -04:00
ang : ang + 180 ,
2024-06-24 11:45:40 -04:00
locator : '[data-overlay-toolbar-index="10"]' ,
2024-05-24 20:54:42 +10:00
} )
const angledLineThatIntersects = await u . getBoundingBox (
` [data-overlay-index="11"] `
)
2024-06-04 08:32:24 -04:00
ang = await u . getAngle ( ` [data-overlay-index="11"] ` )
2024-05-24 20:54:42 +10:00
console . log ( 'angledLineThatIntersects' )
await clickUnconstrained ( {
hoverPos : {
2024-06-24 11:45:40 -04:00
x : angledLineThatIntersects.x ,
2024-05-24 20:54:42 +10:00
y : angledLineThatIntersects.y ,
} ,
constraintType : 'angle' ,
expectBeforeUnconstrained : ` angledLineThatIntersects({
angle : 4.14 ,
2024-06-24 22:39:04 -07:00
intersectTag : a ,
2024-05-24 20:54:42 +10:00
offset : 9
} , % ) ` ,
expectAfterUnconstrained : ` angledLineThatIntersects({
angle : angle003 ,
2024-06-24 22:39:04 -07:00
intersectTag : a ,
2024-05-24 20:54:42 +10:00
offset : 9
} , % ) ` ,
expectFinal : ` angledLineThatIntersects({
angle : - 176 ,
offset : 9 ,
2024-06-24 22:39:04 -07:00
intersectTag : a
2024-05-24 20:54:42 +10:00
} , % ) ` ,
2024-06-04 08:32:24 -04:00
ang : ang + 180 ,
2024-06-24 11:45:40 -04:00
locator : '[data-overlay-toolbar-index="11"]' ,
2024-05-24 20:54:42 +10:00
} )
console . log ( 'angledLineThatIntersects2' )
await clickUnconstrained ( {
hoverPos : {
2024-06-24 11:45:40 -04:00
x : angledLineThatIntersects.x ,
2024-05-24 20:54:42 +10:00
y : angledLineThatIntersects.y ,
} ,
constraintType : 'intersectionOffset' ,
expectBeforeUnconstrained : ` angledLineThatIntersects({
angle : - 176 ,
offset : 9 ,
2024-06-24 22:39:04 -07:00
intersectTag : a
2024-05-24 20:54:42 +10:00
} , % ) ` ,
expectAfterUnconstrained : ` angledLineThatIntersects({
angle : - 176 ,
offset : perpDist001 ,
2024-06-24 22:39:04 -07:00
intersectTag : a
2024-05-24 20:54:42 +10:00
} , % ) ` ,
expectFinal : ` angledLineThatIntersects({
angle : - 176 ,
offset : 9 ,
2024-06-24 22:39:04 -07:00
intersectTag : a
2024-05-24 20:54:42 +10:00
} , % ) ` ,
2024-06-04 08:32:24 -04:00
ang : ang + 180 ,
2024-06-24 11:45:40 -04:00
locator : '[data-overlay-toolbar-index="11"]' ,
2024-05-24 20:54:42 +10:00
} )
} )
test ( 'for segment [tangentialArcTo]' , async ( { page } ) = > {
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const part001 = startSketchOn('XZ')
| > startProfileAt ( [ 0 , 0 ] , % )
| > line ( [ 0.5 , - 14 + 0 ] , % )
| > angledLine ( { angle : 3 + 0 , length : 32 + 0 } , % )
| > lineTo ( [ 33 , 11.5 + 0 ] , % )
| > xLineTo ( 9 - 5 , % )
2024-06-24 22:39:04 -07:00
| > yLineTo ( - 10.77 , % , $a )
2024-05-24 20:54:42 +10:00
| > xLine ( 26.04 , % )
| > yLine ( 21.14 + 0 , % )
| > angledLineOfXLength ( { angle : 181 + 0 , length : 23.14 } , % )
| > angledLineOfYLength ( { angle : - 91 , length : 19 + 0 } , % )
| > angledLineToX ( { angle : 3 + 0 , to : 26 } , % )
| > angledLineToY ( { angle : 89 , to : 9.14 + 0 } , % )
| > angledLineThatIntersects ( {
angle : 4.14 ,
2024-06-24 22:39:04 -07:00
intersectTag : a ,
2024-05-24 20:54:42 +10:00
offset : 9
} , % )
| > tangentialArcTo ( [ 3.14 + 13 , - 3.14 ] , % )
`
)
2024-06-24 11:45:40 -04:00
localStorage . setItem ( 'disableAxis' , 'true' )
2024-05-24 20:54:42 +10:00
} )
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-05-24 20:54:42 +10:00
await u . waitForAuthSkipAppStart ( )
2024-05-24 12:32:15 -07:00
// wait for execution done
await u . openDebugPanel ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await u . closeDebugPanel ( )
2024-05-24 20:54:42 +10:00
await page . getByText ( 'xLineTo(9 - 5, %)' ) . click ( )
await page . waitForTimeout ( 100 )
await page . getByRole ( 'button' , { name : 'Edit Sketch' } ) . click ( )
await page . waitForTimeout ( 500 )
await expect ( page . getByTestId ( 'segment-overlay' ) ) . toHaveCount ( 13 )
const clickUnconstrained = _clickUnconstrained ( page )
const clickConstrained = _clickConstrained ( page )
const tangentialArcTo = await u . getBoundingBox (
2024-06-24 11:45:40 -04:00
'[data-overlay-index="12"]'
2024-05-24 20:54:42 +10:00
)
2024-06-24 11:45:40 -04:00
let ang = await u . getAngle ( '[data-overlay-index="12"]' )
2024-05-24 20:54:42 +10:00
console . log ( 'tangentialArcTo' )
await clickConstrained ( {
2024-06-04 08:32:24 -04:00
hoverPos : { x : tangentialArcTo.x , y : tangentialArcTo.y } ,
2024-05-24 20:54:42 +10:00
constraintType : 'xAbsolute' ,
expectBeforeUnconstrained : 'tangentialArcTo([3.14 + 13, -3.14], %)' ,
expectAfterUnconstrained : 'tangentialArcTo([16.14, -3.14], %)' ,
expectFinal : 'tangentialArcTo([xAbs001, -3.14], %)' ,
2024-06-04 08:32:24 -04:00
ang : ang + 180 ,
2024-05-24 20:54:42 +10:00
steps : 6 ,
2024-06-24 11:45:40 -04:00
locator : '[data-overlay-toolbar-index="12"]' ,
2024-05-24 20:54:42 +10:00
} )
console . log ( 'tangentialArcTo2' )
await clickUnconstrained ( {
2024-06-04 08:32:24 -04:00
hoverPos : { x : tangentialArcTo.x , y : tangentialArcTo.y } ,
2024-05-24 20:54:42 +10:00
constraintType : 'yAbsolute' ,
expectBeforeUnconstrained : 'tangentialArcTo([xAbs001, -3.14], %)' ,
expectAfterUnconstrained : 'tangentialArcTo([xAbs001, yAbs001], %)' ,
expectFinal : 'tangentialArcTo([xAbs001, -3.14], %)' ,
2024-06-04 08:32:24 -04:00
ang : ang + 180 ,
2024-05-24 20:54:42 +10:00
steps : 10 ,
2024-06-24 11:45:40 -04:00
locator : '[data-overlay-toolbar-index="12"]' ,
2024-05-24 20:54:42 +10:00
} )
} )
} )
test . describe ( 'Testing deleting a segment' , ( ) = > {
const _deleteSegmentSequence =
( page : Page ) = >
async ( {
hoverPos ,
codeToBeDeleted ,
stdLibFnName ,
ang = 45 ,
steps = 6 ,
2024-06-24 11:45:40 -04:00
locator ,
2024-05-24 20:54:42 +10:00
} : {
hoverPos : { x : number ; y : number }
codeToBeDeleted : string
stdLibFnName : string
ang? : number
steps? : number
2024-06-24 11:45:40 -04:00
locator? : string
2024-05-24 20:54:42 +10:00
} ) = > {
await expect ( page . getByText ( 'Added variable' ) ) . not . toBeVisible ( )
2024-06-24 11:45:40 -04:00
await page . mouse . move ( 0 , 0 )
await page . waitForTimeout ( 1000 )
let x = 0 ,
y = 0
x = hoverPos . x + Math . cos ( ang * deg ) * 32
y = hoverPos . y - Math . sin ( ang * deg ) * 32
await page . mouse . move ( x , y )
await wiggleMove ( page , x , y , 20 , 30 , ang , 10 , 5 , locator )
2024-05-24 20:54:42 +10:00
await expect ( page . locator ( '.cm-content' ) ) . toContainText ( codeToBeDeleted )
await page . locator ( ` [data-stdlib-fn-name=" ${ stdLibFnName } "] ` ) . click ( )
await page . getByText ( 'Delete Segment' ) . click ( )
await expect ( page . locator ( '.cm-content' ) ) . not . toContainText (
codeToBeDeleted
)
}
test ( 'all segment types' , async ( { page } ) = > {
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const part001 = startSketchOn('XZ')
| > startProfileAt ( [ 0 , 0 ] , % )
| > line ( [ 0.5 , - 14 + 0 ] , % )
| > angledLine ( { angle : 3 + 0 , length : 32 + 0 } , % )
| > lineTo ( [ 33 , 11.5 + 0 ] , % )
| > xLineTo ( 9 - 5 , % )
2024-06-24 22:39:04 -07:00
| > yLineTo ( - 10.77 , % , $a )
2024-05-24 20:54:42 +10:00
| > xLine ( 26.04 , % )
| > yLine ( 21.14 + 0 , % )
| > angledLineOfXLength ( { angle : 181 + 0 , length : 23.14 } , % )
| > angledLineOfYLength ( { angle : - 91 , length : 19 + 0 } , % )
| > angledLineToX ( { angle : 3 + 0 , to : 26 } , % )
| > angledLineToY ( { angle : 89 , to : 9.14 + 0 } , % )
| > angledLineThatIntersects ( {
angle : 4.14 ,
2024-06-24 22:39:04 -07:00
intersectTag : a ,
2024-05-24 20:54:42 +10:00
offset : 9
} , % )
| > tangentialArcTo ( [ 3.14 + 13 , 1.14 ] , % )
`
)
2024-06-24 11:45:40 -04:00
localStorage . setItem ( 'disableAxis' , 'true' )
2024-05-24 20:54:42 +10:00
} )
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-05-24 20:54:42 +10:00
await u . waitForAuthSkipAppStart ( )
2024-05-24 12:32:15 -07:00
// wait for execution done
await u . openDebugPanel ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await u . closeDebugPanel ( )
2024-05-24 20:54:42 +10:00
await page . getByText ( 'xLineTo(9 - 5, %)' ) . click ( )
await page . waitForTimeout ( 100 )
await page . getByRole ( 'button' , { name : 'Edit Sketch' } ) . click ( )
await page . waitForTimeout ( 500 )
await expect ( page . getByTestId ( 'segment-overlay' ) ) . toHaveCount ( 13 )
const deleteSegmentSequence = _deleteSegmentSequence ( page )
let segmentToDelete
const getOverlayByIndex = ( index : number ) = >
u . getBoundingBox ( ` [data-overlay-index=" ${ index } "] ` )
segmentToDelete = await getOverlayByIndex ( 12 )
2024-06-24 11:45:40 -04:00
let ang = await u . getAngle ( ` [data-overlay-index=" ${ 12 } "] ` )
2024-05-24 20:54:42 +10:00
await deleteSegmentSequence ( {
2024-06-24 11:45:40 -04:00
hoverPos : { x : segmentToDelete.x , y : segmentToDelete.y } ,
2024-05-24 20:54:42 +10:00
codeToBeDeleted : 'tangentialArcTo([3.14 + 13, 1.14], %)' ,
stdLibFnName : 'tangentialArcTo' ,
2024-06-24 11:45:40 -04:00
ang : ang + 180 ,
2024-05-24 20:54:42 +10:00
steps : 6 ,
2024-06-24 11:45:40 -04:00
locator : '[data-overlay-toolbar-index="12"]' ,
2024-05-24 20:54:42 +10:00
} )
2024-06-04 08:32:24 -04:00
segmentToDelete = await getOverlayByIndex ( 11 )
2024-06-24 11:45:40 -04:00
ang = await u . getAngle ( ` [data-overlay-index=" ${ 11 } "] ` )
2024-05-24 20:54:42 +10:00
await deleteSegmentSequence ( {
2024-06-24 11:45:40 -04:00
hoverPos : { x : segmentToDelete.x , y : segmentToDelete.y } ,
2024-05-24 20:54:42 +10:00
codeToBeDeleted : ` angledLineThatIntersects({
angle : 4.14 ,
2024-06-24 22:39:04 -07:00
intersectTag : a ,
2024-05-24 20:54:42 +10:00
offset : 9
} , % ) ` ,
stdLibFnName : 'angledLineThatIntersects' ,
2024-06-24 11:45:40 -04:00
ang : ang + 180 ,
2024-05-24 20:54:42 +10:00
steps : 7 ,
2024-06-24 11:45:40 -04:00
locator : '[data-overlay-toolbar-index="11"]' ,
2024-05-24 20:54:42 +10:00
} )
2024-06-04 08:32:24 -04:00
segmentToDelete = await getOverlayByIndex ( 10 )
2024-06-24 11:45:40 -04:00
ang = await u . getAngle ( ` [data-overlay-index=" ${ 10 } "] ` )
2024-05-24 20:54:42 +10:00
await deleteSegmentSequence ( {
2024-06-24 11:45:40 -04:00
hoverPos : { x : segmentToDelete.x , y : segmentToDelete.y } ,
2024-05-24 20:54:42 +10:00
codeToBeDeleted : 'angledLineToY({ angle: 89, to: 9.14 + 0 }, %)' ,
stdLibFnName : 'angledLineToY' ,
2024-06-24 11:45:40 -04:00
ang : ang + 180 ,
locator : '[data-overlay-toolbar-index="10"]' ,
2024-05-24 20:54:42 +10:00
} )
2024-06-04 08:32:24 -04:00
segmentToDelete = await getOverlayByIndex ( 9 )
2024-06-24 11:45:40 -04:00
ang = await u . getAngle ( ` [data-overlay-index=" ${ 9 } "] ` )
2024-05-24 20:54:42 +10:00
await deleteSegmentSequence ( {
2024-06-24 11:45:40 -04:00
hoverPos : { x : segmentToDelete.x , y : segmentToDelete.y } ,
2024-05-24 20:54:42 +10:00
codeToBeDeleted : 'angledLineToX({ angle: 3 + 0, to: 26 }, %)' ,
stdLibFnName : 'angledLineToX' ,
2024-06-24 11:45:40 -04:00
ang : ang + 180 ,
locator : '[data-overlay-toolbar-index="9"]' ,
2024-05-24 20:54:42 +10:00
} )
2024-06-04 08:32:24 -04:00
segmentToDelete = await getOverlayByIndex ( 8 )
2024-06-24 11:45:40 -04:00
ang = await u . getAngle ( ` [data-overlay-index=" ${ 8 } "] ` )
2024-05-24 20:54:42 +10:00
await deleteSegmentSequence ( {
2024-06-24 11:45:40 -04:00
hoverPos : { x : segmentToDelete.x , y : segmentToDelete.y } ,
2024-05-24 20:54:42 +10:00
codeToBeDeleted :
'angledLineOfYLength({ angle: -91, length: 19 + 0 }, %)' ,
stdLibFnName : 'angledLineOfYLength' ,
2024-06-24 11:45:40 -04:00
ang : ang + 180 ,
locator : '[data-overlay-toolbar-index="8"]' ,
2024-05-24 20:54:42 +10:00
} )
2024-06-04 08:32:24 -04:00
segmentToDelete = await getOverlayByIndex ( 7 )
2024-06-24 11:45:40 -04:00
ang = await u . getAngle ( ` [data-overlay-index=" ${ 7 } "] ` )
2024-05-24 20:54:42 +10:00
await deleteSegmentSequence ( {
2024-06-24 11:45:40 -04:00
hoverPos : { x : segmentToDelete.x , y : segmentToDelete.y } ,
2024-05-24 20:54:42 +10:00
codeToBeDeleted :
'angledLineOfXLength({ angle: 181 + 0, length: 23.14 }, %)' ,
stdLibFnName : 'angledLineOfXLength' ,
2024-06-24 11:45:40 -04:00
ang : ang + 180 ,
locator : '[data-overlay-toolbar-index="7"]' ,
2024-05-24 20:54:42 +10:00
} )
2024-06-04 08:32:24 -04:00
segmentToDelete = await getOverlayByIndex ( 6 )
2024-06-24 11:45:40 -04:00
ang = await u . getAngle ( ` [data-overlay-index=" ${ 6 } "] ` )
2024-05-24 20:54:42 +10:00
await deleteSegmentSequence ( {
2024-06-24 11:45:40 -04:00
hoverPos : { x : segmentToDelete.x , y : segmentToDelete.y } ,
2024-05-24 20:54:42 +10:00
codeToBeDeleted : 'yLine(21.14 + 0, %)' ,
stdLibFnName : 'yLine' ,
2024-06-24 11:45:40 -04:00
ang : ang + 180 ,
locator : '[data-overlay-toolbar-index="6"]' ,
2024-05-24 20:54:42 +10:00
} )
2024-06-04 08:32:24 -04:00
segmentToDelete = await getOverlayByIndex ( 5 )
2024-06-24 11:45:40 -04:00
ang = await u . getAngle ( ` [data-overlay-index=" ${ 5 } "] ` )
2024-05-24 20:54:42 +10:00
await deleteSegmentSequence ( {
2024-06-24 11:45:40 -04:00
hoverPos : { x : segmentToDelete.x , y : segmentToDelete.y } ,
2024-05-24 20:54:42 +10:00
codeToBeDeleted : 'xLine(26.04, %)' ,
stdLibFnName : 'xLine' ,
2024-06-24 11:45:40 -04:00
ang : ang + 180 ,
locator : '[data-overlay-toolbar-index="5"]' ,
2024-05-24 20:54:42 +10:00
} )
2024-06-04 08:32:24 -04:00
segmentToDelete = await getOverlayByIndex ( 4 )
2024-06-24 11:45:40 -04:00
ang = await u . getAngle ( ` [data-overlay-index=" ${ 4 } "] ` )
2024-05-24 20:54:42 +10:00
await deleteSegmentSequence ( {
2024-06-24 11:45:40 -04:00
hoverPos : { x : segmentToDelete.x , y : segmentToDelete.y } ,
2024-06-24 22:39:04 -07:00
codeToBeDeleted : 'yLineTo(-10.77, %, $a)' ,
2024-05-24 20:54:42 +10:00
stdLibFnName : 'yLineTo' ,
2024-06-24 11:45:40 -04:00
ang : ang + 180 ,
locator : '[data-overlay-toolbar-index="4"]' ,
2024-05-24 20:54:42 +10:00
} )
2024-06-04 08:32:24 -04:00
segmentToDelete = await getOverlayByIndex ( 3 )
2024-06-24 11:45:40 -04:00
ang = await u . getAngle ( ` [data-overlay-index=" ${ 3 } "] ` )
2024-05-24 20:54:42 +10:00
await deleteSegmentSequence ( {
2024-06-24 11:45:40 -04:00
hoverPos : { x : segmentToDelete.x , y : segmentToDelete.y } ,
2024-05-24 20:54:42 +10:00
codeToBeDeleted : 'xLineTo(9 - 5, %)' ,
stdLibFnName : 'xLineTo' ,
2024-06-24 11:45:40 -04:00
ang : ang + 180 ,
locator : '[data-overlay-toolbar-index="3"]' ,
2024-05-24 20:54:42 +10:00
} )
2024-06-04 08:32:24 -04:00
segmentToDelete = await getOverlayByIndex ( 2 )
2024-06-24 11:45:40 -04:00
ang = await u . getAngle ( ` [data-overlay-index=" ${ 2 } "] ` )
2024-05-24 20:54:42 +10:00
await expect ( page . getByText ( 'Added variable' ) ) . not . toBeVisible ( )
2024-06-24 11:45:40 -04:00
const hoverPos = { x : segmentToDelete.x , y : segmentToDelete.y }
await page . mouse . move ( 0 , 0 )
await page . waitForTimeout ( 1000 )
let x = 0 ,
y = 0
x = hoverPos . x + Math . cos ( ang * deg ) * 32
y = hoverPos . y - Math . sin ( ang * deg ) * 32
await page . mouse . move ( hoverPos . x , hoverPos . y )
await wiggleMove (
page ,
hoverPos . x ,
hoverPos . y ,
20 ,
30 ,
ang ,
10 ,
5 ,
'[data-overlay-toolbar-index="2"]'
)
2024-05-24 20:54:42 +10:00
const codeToBeDeleted = 'lineTo([33, 11.5 + 0], %)'
await expect ( page . locator ( '.cm-content' ) ) . toContainText ( codeToBeDeleted )
await page . getByTestId ( 'overlay-menu' ) . click ( )
await page . getByText ( 'Delete Segment' ) . click ( )
await expect ( page . locator ( '.cm-content' ) ) . not . toContainText (
codeToBeDeleted
)
2024-06-04 08:32:24 -04:00
segmentToDelete = await getOverlayByIndex ( 1 )
2024-06-24 11:45:40 -04:00
ang = await u . getAngle ( ` [data-overlay-index=" ${ 1 } "] ` )
2024-06-04 08:32:24 -04:00
await deleteSegmentSequence ( {
2024-06-24 11:45:40 -04:00
hoverPos : { x : segmentToDelete.x , y : segmentToDelete.y } ,
2024-06-04 08:32:24 -04:00
codeToBeDeleted : 'angledLine({ angle: 3 + 0, length: 32 + 0 }, %)' ,
stdLibFnName : 'angledLine' ,
2024-06-24 11:45:40 -04:00
ang : ang + 180 ,
locator : '[data-overlay-toolbar-index="1"]' ,
2024-06-04 08:32:24 -04:00
} )
segmentToDelete = await getOverlayByIndex ( 0 )
2024-06-24 11:45:40 -04:00
ang = await u . getAngle ( ` [data-overlay-index=" ${ 0 } "] ` )
2024-06-04 08:32:24 -04:00
await deleteSegmentSequence ( {
2024-06-24 11:45:40 -04:00
hoverPos : { x : segmentToDelete.x , y : segmentToDelete.y } ,
2024-06-04 08:32:24 -04:00
codeToBeDeleted : 'line([0.5, -14 + 0], %)' ,
stdLibFnName : 'line' ,
2024-06-24 11:45:40 -04:00
ang : ang + 180 ,
2024-06-04 08:32:24 -04:00
} )
await page . waitForTimeout ( 200 )
2024-05-24 20:54:42 +10:00
} )
} )
test . describe ( 'Testing delete with dependent segments' , ( ) = > {
const cases = [
2024-06-24 22:39:04 -07:00
'line([22, 2], %, $seg01)' ,
'angledLine([5, 23.03], %, $seg01)' ,
'xLine(23, %, $seg01)' ,
'yLine(-8, %, $seg01)' ,
'xLineTo(30, %, $seg01)' ,
'yLineTo(-4, %, $seg01)' ,
'angledLineOfXLength([3, 30], %, $seg01)' ,
'angledLineOfXLength({ angle: 3, length: 30 }, %, $seg01)' ,
'angledLineOfYLength([3, 1.5], %, $seg01)' ,
'angledLineOfYLength({ angle: 3, length: 1.5 }, %, $seg01)' ,
'angledLineToX([3, 30], %, $seg01)' ,
'angledLineToX({ angle: 3, to: 30 }, %, $seg01)' ,
'angledLineToY([3, 7], %, $seg01)' ,
'angledLineToY({ angle: 3, to: 7 }, %, $seg01)' ,
2024-05-24 20:54:42 +10:00
]
for ( const doesHaveTagOutsideSketch of [ true , false ] ) {
for ( const lineOfInterest of cases ) {
const isObj = lineOfInterest . includes ( '{ angle: 3,' )
test ( ` ${ lineOfInterest . split ( '(' ) [ 0 ] } ${ isObj ? '-[obj-input]' : '' } ${
doesHaveTagOutsideSketch ? '-[tagOutsideSketch]' : ''
} ` , async ({ page }) => {
await page . addInitScript (
async ( { lineToBeDeleted , extraLine } ) = > {
localStorage . setItem (
'persistCode' ,
` const part001 = startSketchOn('XZ')
| > startProfileAt ( [ 5 , 6 ] , % )
| > $ { lineToBeDeleted }
| > line ( [ - 10 , - 15 ] , % )
2024-06-24 22:39:04 -07:00
| > angledLine ( [ - 176 , segLen ( seg01 , % ) ] , % )
$ { extraLine ? 'const myVar = segLen(seg01, part001)' : '' } `
2024-05-24 20:54:42 +10:00
)
} ,
{
lineToBeDeleted : lineOfInterest ,
extraLine : doesHaveTagOutsideSketch ,
}
)
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-05-24 20:54:42 +10:00
await u . waitForAuthSkipAppStart ( )
await page . waitForTimeout ( 300 )
await page . getByText ( lineOfInterest ) . click ( )
await page . waitForTimeout ( 100 )
await page . getByRole ( 'button' , { name : 'Edit Sketch' } ) . click ( )
await page . waitForTimeout ( 500 )
await expect ( page . getByTestId ( 'segment-overlay' ) ) . toHaveCount ( 3 )
const segmentToDelete = await u . getBoundingBox (
` [data-overlay-index="0"] `
)
const isYLine = lineOfInterest . toLowerCase ( ) . includes ( 'yline' )
const hoverPos = {
x : segmentToDelete.x + ( isYLine ? 0 : - 20 ) ,
y : segmentToDelete.y + ( isYLine ? - 20 : 0 ) ,
}
await expect ( page . getByText ( 'Added variable' ) ) . not . toBeVisible ( )
const ang = isYLine ? 45 : - 45
const [ x , y ] = [
Math . cos ( ( ang * Math . PI ) / 180 ) * 45 ,
Math . sin ( ( ang * Math . PI ) / 180 ) * 45 ,
]
await page . mouse . move ( hoverPos . x + x , hoverPos . y + y )
await page . mouse . move ( hoverPos . x , hoverPos . y , { steps : 5 } )
await expect ( page . locator ( '.cm-content' ) ) . toContainText (
lineOfInterest
)
await page . getByTestId ( 'overlay-menu' ) . click ( )
2024-06-30 06:10:54 +10:00
await page . waitForTimeout ( 100 )
2024-05-24 20:54:42 +10:00
await page . getByText ( 'Delete Segment' ) . click ( )
await page . getByText ( 'Cancel' ) . click ( )
await page . mouse . move ( hoverPos . x + x , hoverPos . y + y )
await page . mouse . move ( hoverPos . x , hoverPos . y , { steps : 5 } )
await expect ( page . locator ( '.cm-content' ) ) . toContainText (
lineOfInterest
)
await page . getByTestId ( 'overlay-menu' ) . click ( )
2024-06-30 06:10:54 +10:00
await page . waitForTimeout ( 100 )
2024-05-24 20:54:42 +10:00
await page . getByText ( 'Delete Segment' ) . click ( )
await page . getByText ( 'Continue and unconstrain' ) . last ( ) . click ( )
if ( doesHaveTagOutsideSketch ) {
// eslint-disable-next-line jest/no-conditional-expect
await expect (
page . getByText (
'Segment tag used outside of current Sketch. Could not delete.'
)
) . toBeTruthy ( )
// eslint-disable-next-line jest/no-conditional-expect
await expect ( page . locator ( '.cm-content' ) ) . toContainText (
lineOfInterest
)
} else {
// eslint-disable-next-line jest/no-conditional-expect
await expect ( page . locator ( '.cm-content' ) ) . not . toContainText (
lineOfInterest
)
// eslint-disable-next-line jest/no-conditional-expect
await expect ( page . locator ( '.cm-content' ) ) . not . toContainText ( 'seg01' )
}
} )
}
}
} )
2024-06-04 16:29:20 +10:00
test . describe ( 'Testing remove constraints segments' , ( ) = > {
const cases = [
{
2024-06-24 22:39:04 -07:00
before : ` line([22 + 0, 2 + 0], %, $ seg01) ` ,
after : ` line([22, 2], %, $ seg01) ` ,
2024-06-04 16:29:20 +10:00
} ,
{
2024-06-24 22:39:04 -07:00
before : ` angledLine([5 + 0, 23.03 + 0], %, $ seg01) ` ,
after : ` line([22.94, 2.01], %, $ seg01) ` ,
2024-06-04 16:29:20 +10:00
} ,
{
2024-06-24 22:39:04 -07:00
before : ` xLine(23 + 0, %, $ seg01) ` ,
after : ` line([23, 0], %, $ seg01) ` ,
2024-06-04 16:29:20 +10:00
} ,
{
2024-06-24 22:39:04 -07:00
before : ` yLine(-8 + 0, %, $ seg01) ` ,
after : ` line([0, -8], %, $ seg01) ` ,
2024-06-04 16:29:20 +10:00
} ,
{
2024-06-24 22:39:04 -07:00
before : ` xLineTo(30 + 0, %, $ seg01) ` ,
after : ` line([25, 0], %, $ seg01) ` ,
2024-06-04 16:29:20 +10:00
} ,
{
2024-06-24 22:39:04 -07:00
before : ` yLineTo(-4 + 0, %, $ seg01) ` ,
after : ` line([0, -10], %, $ seg01) ` ,
2024-06-04 16:29:20 +10:00
} ,
{
2024-06-24 22:39:04 -07:00
before : ` angledLineOfXLength([3 + 0, 30 + 0], %, $ seg01) ` ,
after : ` line([30, 1.57], %, $ seg01) ` ,
2024-06-04 16:29:20 +10:00
} ,
{
2024-06-24 22:39:04 -07:00
before : ` angledLineOfYLength([3 + 0, 1.5 + 0], %, $ seg01) ` ,
after : ` line([28.62, 1.5], %, $ seg01) ` ,
2024-06-04 16:29:20 +10:00
} ,
{
2024-06-24 22:39:04 -07:00
before : ` angledLineToX([3 + 0, 30 + 0], %, $ seg01) ` ,
after : ` line([25, 1.31], %, $ seg01) ` ,
2024-06-04 16:29:20 +10:00
} ,
{
2024-06-24 22:39:04 -07:00
before : ` angledLineToY([3 + 0, 7 + 0], %, $ seg01) ` ,
after : ` line([19.08, 1], %, $ seg01) ` ,
2024-06-04 16:29:20 +10:00
} ,
{
2024-06-24 22:39:04 -07:00
before : ` angledLineOfXLength({ angle: 3 + 0, length: 30 + 0 }, %, $ seg01) ` ,
after : ` line([30, 1.57], %, $ seg01) ` ,
2024-06-04 16:29:20 +10:00
} ,
{
2024-06-24 22:39:04 -07:00
before : ` angledLineOfYLength({ angle: 3 + 0, length: 1.5 + 0 }, %, $ seg01) ` ,
after : ` line([28.62, 1.5], %, $ seg01) ` ,
2024-06-04 16:29:20 +10:00
} ,
{
2024-06-24 22:39:04 -07:00
before : ` angledLineToX({ angle: 3 + 0, to: 30 + 0 }, %, $ seg01) ` ,
after : ` line([25, 1.31], %, $ seg01) ` ,
2024-06-04 16:29:20 +10:00
} ,
{
2024-06-24 22:39:04 -07:00
before : ` angledLineToY({ angle: 3 + 0, to: 7 + 0 }, %, $ seg01) ` ,
after : ` line([19.08, 1], %, $ seg01) ` ,
2024-06-04 16:29:20 +10:00
} ,
]
for ( const { before , after } of cases ) {
const isObj = before . includes ( '{ angle: 3' )
test ( ` ${ before . split ( '(' ) [ 0 ] } ${ isObj ? '-[obj-input]' : '' } ` , async ( {
page ,
} ) = > {
await page . addInitScript (
async ( { lineToBeDeleted } ) = > {
localStorage . setItem (
'persistCode' ,
` const part001 = startSketchOn('XZ')
| > startProfileAt ( [ 5 , 6 ] , % )
| > $ { lineToBeDeleted }
| > line ( [ - 10 , - 15 ] , % )
2024-06-24 22:39:04 -07:00
| > angledLine ( [ - 176 , segLen ( seg01 , % ) ] , % ) `
2024-06-04 16:29:20 +10:00
)
} ,
{
lineToBeDeleted : before ,
}
)
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-06-04 16:29:20 +10:00
await u . waitForAuthSkipAppStart ( )
await page . waitForTimeout ( 300 )
await page . getByText ( before ) . click ( )
await page . waitForTimeout ( 100 )
await page . getByRole ( 'button' , { name : 'Edit Sketch' } ) . click ( )
await page . waitForTimeout ( 500 )
await expect ( page . getByTestId ( 'segment-overlay' ) ) . toHaveCount ( 3 )
await expect ( page . getByText ( 'Added variable' ) ) . not . toBeVisible ( )
2024-06-24 11:45:40 -04:00
const hoverPos = await u . getBoundingBox ( ` [data-overlay-index="0"] ` )
let ang = await u . getAngle ( ` [data-overlay-index=" ${ 0 } "] ` )
ang += 180
await page . mouse . move ( 0 , 0 )
await page . waitForTimeout ( 1000 )
let x = 0 ,
y = 0
x = hoverPos . x + Math . cos ( ang * deg ) * 32
y = hoverPos . y - Math . sin ( ang * deg ) * 32
await page . mouse . move ( x , y )
await wiggleMove (
page ,
x ,
y ,
20 ,
30 ,
ang ,
10 ,
5 ,
'[data-overlay-toolbar-index="0"]'
)
2024-06-04 16:29:20 +10:00
2024-07-03 14:34:45 +10:00
await expect ( page . locator ( '.cm-content' ) ) . toContainText ( before )
2024-05-22 11:07:02 -04:00
2024-07-03 14:34:45 +10:00
await page . getByTestId ( 'overlay-menu' ) . click ( )
await page . waitForTimeout ( 100 )
await page . getByText ( 'Remove constraints' ) . click ( )
await expect ( page . locator ( '.cm-content' ) ) . toContainText ( after )
// check the cursor was left in the correct place after transform
await expect ( page . locator ( '.cm-activeLine' ) ) . toHaveText ( '|> ' + after )
await expect ( page . getByTestId ( 'segment-overlay' ) ) . toHaveCount ( 3 )
} )
}
} )
2024-05-22 11:07:02 -04:00
} )
2024-05-23 02:20:40 -07:00
2024-07-03 14:34:45 +10:00
test . describe ( 'Test network and connection issues' , ( ) = > {
test ( 'simulate network down and network little widget' , async ( { page } ) = > {
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-07-03 14:34:45 +10:00
await u . waitForAuthSkipAppStart ( )
2024-05-23 02:20:40 -07:00
2024-07-03 14:34:45 +10:00
// This is how we wait until the stream is online
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . not . toBeDisabled ( { timeout : 15000 } )
2024-06-04 08:32:24 -04:00
2024-07-03 14:34:45 +10:00
const networkWidget = page . locator ( '[data-testid="network-toggle"]' )
await expect ( networkWidget ) . toBeVisible ( )
await networkWidget . hover ( )
2024-05-23 02:20:40 -07:00
2024-07-03 14:34:45 +10:00
const networkPopover = page . locator ( '[data-testid="network-popover"]' )
await expect ( networkPopover ) . not . toBeVisible ( )
2024-05-23 02:20:40 -07:00
2024-07-03 14:34:45 +10:00
// (First check) Expect the network to be up
await expect ( page . getByText ( 'Network Health (Connected)' ) ) . toBeVisible ( )
2024-05-23 02:20:40 -07:00
2024-07-03 14:34:45 +10:00
// Click the network widget
await networkWidget . click ( )
2024-05-23 02:20:40 -07:00
2024-07-03 14:34:45 +10:00
// Check the modal opened.
await expect ( networkPopover ) . toBeVisible ( )
2024-05-23 02:20:40 -07:00
2024-07-03 14:34:45 +10:00
// Click off the modal.
await page . mouse . click ( 100 , 100 )
await expect ( networkPopover ) . not . toBeVisible ( )
2024-05-23 02:20:40 -07:00
2024-07-03 14:34:45 +10:00
// Turn off the network
await u . emulateNetworkConditions ( {
offline : true ,
// values of 0 remove any active throttling. crbug.com/456324#c9
latency : 0 ,
downloadThroughput : - 1 ,
uploadThroughput : - 1 ,
} )
2024-05-23 02:20:40 -07:00
2024-07-03 14:34:45 +10:00
// Expect the network to be down
await expect ( page . getByText ( 'Network Health (Offline)' ) ) . toBeVisible ( )
2024-05-23 02:20:40 -07:00
2024-07-03 14:34:45 +10:00
// Click the network widget
await networkWidget . click ( )
2024-05-23 02:20:40 -07:00
2024-07-03 14:34:45 +10:00
// Check the modal opened.
await expect ( networkPopover ) . toBeVisible ( )
2024-05-23 02:20:40 -07:00
2024-07-03 14:34:45 +10:00
// Click off the modal.
await page . mouse . click ( 0 , 0 )
await expect ( networkPopover ) . not . toBeVisible ( )
2024-05-23 02:20:40 -07:00
2024-07-03 14:34:45 +10:00
// Turn back on the network
await u . emulateNetworkConditions ( {
offline : false ,
// values of 0 remove any active throttling. crbug.com/456324#c9
latency : 0 ,
downloadThroughput : - 1 ,
uploadThroughput : - 1 ,
} )
2024-05-23 02:20:40 -07:00
2024-07-03 14:34:45 +10:00
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . not . toBeDisabled ( { timeout : 15000 } )
2024-06-04 08:32:24 -04:00
2024-07-03 14:34:45 +10:00
// (Second check) expect the network to be up
await expect ( page . getByText ( 'Network Health (Connected)' ) ) . toBeVisible ( )
} )
2024-05-24 16:11:49 -07:00
2024-07-03 14:34:45 +10:00
test ( 'Engine disconnect & reconnect in sketch mode' , async ( { page } ) = > {
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
const PUR = 400 / 37.5 //pixeltoUnitRatio
2024-06-29 18:10:07 -07:00
2024-07-03 14:34:45 +10:00
await u . waitForAuthSkipAppStart ( )
await u . openDebugPanel ( )
2024-05-24 16:11:49 -07:00
2024-07-03 14:34:45 +10:00
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . not . toBeDisabled ( { timeout : 15000 } )
2024-05-24 16:11:49 -07:00
2024-07-03 14:34:45 +10:00
// click on "Start Sketch" button
await u . clearCommandLogs ( )
await page . getByRole ( 'button' , { name : 'Start Sketch' } ) . click ( )
await page . waitForTimeout ( 100 )
2024-05-24 16:11:49 -07:00
2024-07-03 14:34:45 +10:00
// select a plane
await page . mouse . click ( 700 , 200 )
2024-05-24 16:11:49 -07:00
2024-07-03 14:34:45 +10:00
await expect ( page . locator ( '.cm-content' ) ) . toHaveText (
` const sketch001 = startSketchOn('XZ') `
)
await u . closeDebugPanel ( )
2024-05-24 16:11:49 -07:00
2024-07-03 14:34:45 +10:00
await page . waitForTimeout ( 500 ) // TODO detect animation ending, or disable animation
2024-05-24 16:11:49 -07:00
2024-07-03 14:34:45 +10:00
const startXPx = 600
await page . mouse . click ( startXPx + PUR * 10 , 500 - PUR * 10 )
await expect ( page . locator ( '.cm-content' ) )
. toHaveText ( ` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( $ { commonPoints . startAt } , % ) ` )
await page . waitForTimeout ( 100 )
2024-05-24 16:11:49 -07:00
2024-07-03 14:34:45 +10:00
await page . mouse . click ( startXPx + PUR * 20 , 500 - PUR * 10 )
await page . waitForTimeout ( 100 )
2024-05-24 16:11:49 -07:00
2024-07-03 14:34:45 +10:00
await expect ( page . locator ( '.cm-content' ) )
. toHaveText ( ` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( $ { commonPoints . startAt } , % )
| > line ( [ $ { commonPoints . num1 } , 0 ] , % ) ` )
2024-05-24 16:11:49 -07:00
2024-07-03 14:34:45 +10:00
// Expect the network to be up
await expect ( page . getByText ( 'Network Health (Connected)' ) ) . toBeVisible ( )
2024-05-24 16:11:49 -07:00
2024-07-03 14:34:45 +10:00
// simulate network down
await u . emulateNetworkConditions ( {
offline : true ,
// values of 0 remove any active throttling. crbug.com/456324#c9
latency : 0 ,
downloadThroughput : - 1 ,
uploadThroughput : - 1 ,
} )
2024-05-24 16:11:49 -07:00
2024-07-03 14:34:45 +10:00
// Expect the network to be down
await expect ( page . getByText ( 'Network Health (Offline)' ) ) . toBeVisible ( )
2024-05-24 16:11:49 -07:00
2024-07-03 14:34:45 +10:00
// Ensure we are not in sketch mode
await expect (
page . getByRole ( 'button' , { name : 'Exit Sketch' } )
) . not . toBeVisible ( )
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . toBeVisible ( )
2024-05-24 16:11:49 -07:00
2024-07-03 14:34:45 +10:00
// simulate network up
await u . emulateNetworkConditions ( {
offline : false ,
// values of 0 remove any active throttling. crbug.com/456324#c9
latency : 0 ,
downloadThroughput : - 1 ,
uploadThroughput : - 1 ,
} )
2024-05-24 16:11:49 -07:00
2024-07-03 14:34:45 +10:00
// Wait for the app to be ready for use
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . not . toBeDisabled ( { timeout : 15000 } )
2024-06-04 08:32:24 -04:00
2024-07-03 14:34:45 +10:00
// Expect the network to be up
await expect ( page . getByText ( 'Network Health (Connected)' ) ) . toBeVisible ( )
2024-05-24 16:11:49 -07:00
2024-07-03 14:34:45 +10:00
// Click off the code pane.
await page . mouse . click ( 100 , 100 )
2024-05-24 16:11:49 -07:00
2024-07-03 14:34:45 +10:00
// select a line
await page . getByText ( ` startProfileAt( ${ commonPoints . startAt } , %) ` ) . click ( )
2024-05-24 16:11:49 -07:00
2024-07-03 14:34:45 +10:00
// enter sketch again
await u . doAndWaitForCmd (
( ) = > page . getByRole ( 'button' , { name : 'Edit Sketch' } ) . click ( ) ,
'default_camera_get_settings'
)
await page . waitForTimeout ( 150 )
2024-05-24 16:11:49 -07:00
2024-07-03 14:34:45 +10:00
// Click the line tool
await page . getByRole ( 'button' , { name : 'Line' } ) . click ( )
2024-05-24 16:11:49 -07:00
2024-07-03 14:34:45 +10:00
await page . waitForTimeout ( 150 )
2024-05-24 16:11:49 -07:00
2024-07-03 14:34:45 +10:00
// Ensure we can continue sketching
await page . mouse . click ( startXPx + PUR * 20 , 500 - PUR * 20 )
await expect ( page . locator ( '.cm-content' ) )
. toHaveText ( ` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( $ { commonPoints . startAt } , % )
| > line ( [ $ { commonPoints . num1 } , 0 ] , % )
| > line ( [ - 9.16 , 8.81 ] , % ) ` )
await page . waitForTimeout ( 100 )
await page . mouse . click ( startXPx , 500 - PUR * 20 )
await expect ( page . locator ( '.cm-content' ) )
. toHaveText ( ` const sketch001 = startSketchOn('XZ')
| > startProfileAt ( $ { commonPoints . startAt } , % )
| > line ( [ $ { commonPoints . num1 } , 0 ] , % )
| > line ( [ - 9.16 , 8.81 ] , % )
| > line ( [ - 5.28 , 0 ] , % ) ` )
2024-05-24 16:11:49 -07:00
2024-07-03 14:34:45 +10:00
// Unequip line tool
await page . keyboard . press ( 'Escape' )
// Make sure we didn't pop out of sketch mode.
await expect (
page . getByRole ( 'button' , { name : 'Exit Sketch' } )
) . toBeVisible ( )
await expect (
page . getByRole ( 'button' , { name : 'Line' } )
) . not . toHaveAttribute ( 'aria-pressed' , 'true' )
2024-05-24 16:11:49 -07:00
2024-07-03 14:34:45 +10:00
// Exit sketch
await page . keyboard . press ( 'Escape' )
await expect (
page . getByRole ( 'button' , { name : 'Exit Sketch' } )
) . not . toBeVisible ( )
} )
2024-05-24 16:11:49 -07:00
} )
2024-05-29 18:04:27 -04:00
2024-06-05 14:43:12 +02:00
test . describe ( 'Testing Gizmo' , ( ) = > {
const cases = [
{
testDescription : 'top view' ,
clickPosition : { x : 951 , y : 385 } ,
expectedCameraPosition : { x : 800 , y : - 152 , z : 4886.02 } ,
expectedCameraTarget : { x : 800 , y : - 152 , z : 26 } ,
} ,
{
testDescription : 'bottom view' ,
clickPosition : { x : 951 , y : 429 } ,
expectedCameraPosition : { x : 800 , y : - 152 , z : - 4834.02 } ,
expectedCameraTarget : { x : 800 , y : - 152 , z : 26 } ,
} ,
{
2024-06-06 19:56:46 -04:00
testDescription : 'right view' ,
2024-06-05 14:43:12 +02:00
clickPosition : { x : 929 , y : 417 } ,
expectedCameraPosition : { x : 5660.02 , y : - 152 , z : 26 } ,
expectedCameraTarget : { x : 800 , y : - 152 , z : 26 } ,
} ,
{
2024-06-06 19:56:46 -04:00
testDescription : 'left view' ,
2024-06-05 14:43:12 +02:00
clickPosition : { x : 974 , y : 397 } ,
expectedCameraPosition : { x : - 4060.02 , y : - 152 , z : 26 } ,
expectedCameraTarget : { x : 800 , y : - 152 , z : 26 } ,
} ,
{
2024-06-06 19:56:46 -04:00
testDescription : 'back view' ,
2024-06-05 14:43:12 +02:00
clickPosition : { x : 967 , y : 421 } ,
expectedCameraPosition : { x : 800 , y : 4708.02 , z : 26 } ,
expectedCameraTarget : { x : 800 , y : - 152 , z : 26 } ,
} ,
{
2024-06-06 19:56:46 -04:00
testDescription : 'front view' ,
2024-06-05 14:43:12 +02:00
clickPosition : { x : 935 , y : 393 } ,
expectedCameraPosition : { x : 800 , y : - 5012.02 , z : 26 } ,
expectedCameraTarget : { x : 800 , y : - 152 , z : 26 } ,
} ,
] as const
for ( const {
clickPosition ,
expectedCameraPosition ,
expectedCameraTarget ,
testDescription ,
} of cases ) {
2024-06-06 19:56:46 -04:00
test ( ` check ${ testDescription } ` , async ( { page , browserName } ) = > {
2024-06-05 14:43:12 +02:00
const u = await getUtils ( page )
2024-06-06 19:56:46 -04:00
await page . addInitScript ( ( TEST_CODE_GIZMO ) = > {
localStorage . setItem ( 'persistCode' , TEST_CODE_GIZMO )
} , TEST_CODE_GIZMO )
2024-06-05 14:43:12 +02:00
await page . setViewportSize ( { width : 1000 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-06-05 14:43:12 +02:00
await u . waitForAuthSkipAppStart ( )
await page . waitForTimeout ( 100 )
// wait for execution done
await u . openDebugPanel ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_look_at' ,
vantage : {
x : 3000 ,
y : 3000 ,
z : 3000 ,
} ,
center : {
x : 800 ,
y : - 152 ,
z : 26 ,
} ,
up : { x : 0 , y : 0 , z : 1 } ,
} ,
} )
await page . waitForTimeout ( 100 )
await u . clearCommandLogs ( )
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_get_settings' ,
} ,
} )
await u . waitForCmdReceive ( 'default_camera_get_settings' )
2024-06-06 19:56:46 -04:00
await u . clearCommandLogs ( )
2024-06-05 14:43:12 +02:00
await page . mouse . move ( clickPosition . x , clickPosition . y )
await page . waitForTimeout ( 100 )
await page . mouse . click ( clickPosition . x , clickPosition . y )
2024-06-06 19:56:46 -04:00
await page . mouse . move ( 0 , 0 )
2024-06-05 14:43:12 +02:00
await u . waitForCmdReceive ( 'default_camera_look_at' )
await u . clearCommandLogs ( )
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_get_settings' ,
} ,
} )
await u . waitForCmdReceive ( 'default_camera_get_settings' )
await Promise . all ( [
// position
expect ( page . getByTestId ( 'cam-x-position' ) ) . toHaveValue (
expectedCameraPosition . x . toString ( )
) ,
expect ( page . getByTestId ( 'cam-y-position' ) ) . toHaveValue (
expectedCameraPosition . y . toString ( )
) ,
expect ( page . getByTestId ( 'cam-z-position' ) ) . toHaveValue (
expectedCameraPosition . z . toString ( )
) ,
// target
expect ( page . getByTestId ( 'cam-x-target' ) ) . toHaveValue (
expectedCameraTarget . x . toString ( )
) ,
expect ( page . getByTestId ( 'cam-y-target' ) ) . toHaveValue (
expectedCameraTarget . y . toString ( )
) ,
expect ( page . getByTestId ( 'cam-z-target' ) ) . toHaveValue (
expectedCameraTarget . z . toString ( )
) ,
] )
} )
}
2024-06-06 19:56:46 -04:00
test ( 'Context menu' , async ( { page } ) = > {
const testCase = {
testDescription : 'Right view' ,
expectedCameraPosition : { x : 5660.02 , y : - 152 , z : 26 } ,
expectedCameraTarget : { x : 800 , y : - 152 , z : 26 } ,
}
// Test prelude taken from the above test
const u = await getUtils ( page )
await page . addInitScript ( ( TEST_CODE_GIZMO ) = > {
localStorage . setItem ( 'persistCode' , TEST_CODE_GIZMO )
} , TEST_CODE_GIZMO )
await page . setViewportSize ( { width : 1000 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-06-06 19:56:46 -04:00
await u . waitForAuthSkipAppStart ( )
await page . waitForTimeout ( 100 )
// wait for execution done
await u . openDebugPanel ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_look_at' ,
vantage : {
x : 3000 ,
y : 3000 ,
z : 3000 ,
} ,
center : {
x : 800 ,
y : - 152 ,
z : 26 ,
} ,
up : { x : 0 , y : 0 , z : 1 } ,
} ,
} )
await page . waitForTimeout ( 100 )
await u . clearCommandLogs ( )
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_get_settings' ,
} ,
} )
await u . waitForCmdReceive ( 'default_camera_get_settings' )
// Now find and select the correct
// view from the context menu
await u . clearCommandLogs ( )
const gizmo = page . locator ( '[aria-label*=gizmo]' )
await gizmo . click ( { button : 'right' } )
const buttonToTest = page . getByRole ( 'button' , {
name : testCase.testDescription ,
} )
await expect ( buttonToTest ) . toBeVisible ( )
await buttonToTest . click ( )
// Now assert we've moved to the correct view
// Taken from the above test
await u . waitForCmdReceive ( 'default_camera_look_at' )
await u . sendCustomCmd ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'default_camera_get_settings' ,
} ,
} )
await u . waitForCmdReceive ( 'default_camera_get_settings' )
await page . waitForTimeout ( 400 )
await Promise . all ( [
// position
expect ( page . getByTestId ( 'cam-x-position' ) ) . toHaveValue (
testCase . expectedCameraPosition . x . toString ( )
) ,
expect ( page . getByTestId ( 'cam-y-position' ) ) . toHaveValue (
testCase . expectedCameraPosition . y . toString ( )
) ,
expect ( page . getByTestId ( 'cam-z-position' ) ) . toHaveValue (
testCase . expectedCameraPosition . z . toString ( )
) ,
// target
expect ( page . getByTestId ( 'cam-x-target' ) ) . toHaveValue (
testCase . expectedCameraTarget . x . toString ( )
) ,
expect ( page . getByTestId ( 'cam-y-target' ) ) . toHaveValue (
testCase . expectedCameraTarget . y . toString ( )
) ,
expect ( page . getByTestId ( 'cam-z-target' ) ) . toHaveValue (
testCase . expectedCameraTarget . z . toString ( )
) ,
] )
} )
2024-06-05 14:43:12 +02:00
} )
2024-07-05 18:40:43 -04:00
test ( 'Units menu' , async ( { page } ) = > {
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
await page . goto ( '/' )
await page . waitForURL ( '**/file/**' , { waitUntil : 'domcontentloaded' } )
await u . waitForAuthSkipAppStart ( )
const unitsMenuButton = page . getByRole ( 'button' , {
name : 'Current Units' ,
exact : false ,
} )
await expect ( unitsMenuButton ) . toBeVisible ( )
await expect ( unitsMenuButton ) . toContainText ( 'in' )
await unitsMenuButton . click ( )
const millimetersButton = page . getByRole ( 'button' , { name : 'Millimeters' } )
await expect ( millimetersButton ) . toBeVisible ( )
await millimetersButton . click ( )
// Look out for the toast message
const toastMessage = page . getByText (
` Set default unit to "mm" for this project `
)
await expect ( toastMessage ) . toBeVisible ( )
// Verify that the popover has closed
await expect ( millimetersButton ) . not . toBeAttached ( )
// Verify that the button label has updated
await expect ( unitsMenuButton ) . toContainText ( 'mm' )
} )
2024-05-29 18:04:27 -04:00
test ( 'Successful export shows a success toast' , async ( { page } ) = > {
// FYI this test doesn't work with only engine running locally
// And you will need to have the KittyCAD CLI installed
const u = await getUtils ( page )
await page . addInitScript ( async ( ) = > {
; ( window as any ) . playwrightSkipFilePicker = true
localStorage . setItem (
'persistCode' ,
` const topAng = 25
const bottomAng = 35
const baseLen = 3.5
const baseHeight = 1
const totalHeightHalf = 2
const armThick = 0.5
const totalLen = 9.5
const part001 = startSketchOn ( '-XZ' )
| > startProfileAt ( [ 0 , 0 ] , % )
| > yLine ( baseHeight , % )
| > xLine ( baseLen , % )
| > angledLineToY ( {
angle : topAng ,
to : totalHeightHalf ,
2024-06-24 22:39:04 -07:00
} , % , $seg04 )
| > xLineTo ( totalLen , % , $seg03 )
| > yLine ( - armThick , % , $seg01 )
2024-05-29 18:04:27 -04:00
| > angledLineThatIntersects ( {
angle : HALF_TURN ,
offset : - armThick ,
2024-06-24 22:39:04 -07:00
intersectTag : seg04
2024-05-29 18:04:27 -04:00
} , % )
2024-06-24 22:39:04 -07:00
| > angledLineToY ( [ segAng ( seg04 , % ) + 180 , ZERO ] , % )
2024-05-29 18:04:27 -04:00
| > angledLineToY ( {
angle : - bottomAng ,
to : - totalHeightHalf - armThick ,
2024-06-24 22:39:04 -07:00
} , % , $seg02 )
| > xLineTo ( segEndX ( seg03 , % ) + 0 , % )
| > yLine ( - segLen ( seg01 , % ) , % )
2024-05-29 18:04:27 -04:00
| > angledLineThatIntersects ( {
angle : HALF_TURN ,
offset : - armThick ,
2024-06-24 22:39:04 -07:00
intersectTag : seg02
2024-05-29 18:04:27 -04:00
} , % )
2024-06-24 22:39:04 -07:00
| > angledLineToY ( [ segAng ( seg02 , % ) + 180 , - baseHeight ] , % )
2024-05-29 18:04:27 -04:00
| > xLineTo ( ZERO , % )
| > close ( % )
| > extrude ( 4 , % ) `
)
} )
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
2024-05-29 18:04:27 -04:00
await u . waitForAuthSkipAppStart ( )
await u . openDebugPanel ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await u . waitForCmdReceive ( 'extrude' )
await page . waitForTimeout ( 1000 )
await u . clearAndCloseDebugPanel ( )
await doExport (
{
type : 'gltf' ,
storage : 'embedded' ,
presentation : 'pretty' ,
} ,
page
)
// This is the main thing we're testing,
// We test the export functionality across all
// file types in snapshot-tests.spec.ts
await expect ( page . getByText ( 'Exported successfully' ) ) . toBeVisible ( )
} )
2024-06-04 14:36:34 -04:00
test ( 'Paste should not work unless an input is focused' , async ( {
page ,
browserName ,
} ) = > {
// To run this test locally, uncomment Firefox in playwright.config.ts
test . skip (
browserName !== 'firefox' ,
"This bug is really Firefox-only, which we don't run in CI."
)
2024-06-29 18:10:07 -07:00
const u = await getUtils ( page )
2024-06-04 14:36:34 -04:00
await page . setViewportSize ( { width : 1200 , height : 500 } )
2024-06-29 18:10:07 -07:00
await u . waitForAuthSkipAppStart ( )
2024-06-04 14:36:34 -04:00
await page
. getByRole ( 'button' , { name : 'Start Sketch' } )
. waitFor ( { state : 'visible' } )
const codeEditorText = page . locator ( '.cm-content' )
const pasteContent = ` // was this pasted? `
const typeContent = ` // this should be typed `
// Load text into the clipboard
await page . evaluate ( ( t ) = > navigator . clipboard . writeText ( t ) , pasteContent )
// Focus the text editor
await codeEditorText . focus ( )
// Show that we can type into it
await page . keyboard . type ( typeContent )
await page . keyboard . press ( 'Enter' )
// Paste without the code pane focused
await codeEditorText . blur ( )
await page . keyboard . press ( ` ${ metaModifier } +KeyV ` )
// Show that the paste didn't work but typing did
await expect ( codeEditorText ) . not . toContainText ( pasteContent )
await expect ( codeEditorText ) . toContainText ( typeContent )
// Paste with the code editor focused
// Following this guidance: https://github.com/microsoft/playwright/issues/8114
await codeEditorText . focus ( )
await page . keyboard . press ( ` ${ metaModifier } +KeyV ` )
await expect (
await page . evaluate (
( ) = > document . querySelector ( '.cm-content' ) ? . textContent
)
) . toContain ( pasteContent )
} )
2024-06-30 18:26:16 -07:00
2024-07-03 14:34:45 +10:00
test ( 'Keyboard shortcuts can be viewed through the help menu' , async ( {
page ,
} ) = > {
const u = await getUtils ( page )
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
await page . waitForURL ( '**/file/**' , { waitUntil : 'domcontentloaded' } )
await page
. getByRole ( 'button' , { name : 'Start Sketch' } )
. waitFor ( { state : 'visible' } )
// Open the help menu
await page . getByRole ( 'button' , { name : 'Help' , exact : false } ) . click ( )
// Open the keyboard shortcuts
await page . getByRole ( 'button' , { name : 'Keyboard Shortcuts' } ) . click ( )
// Verify the URL and that you can see a list of shortcuts
await expect ( page . url ( ) ) . toContain ( '?tab=keybindings' )
await expect (
page . getByRole ( 'heading' , { name : 'Enter Sketch Mode' } )
) . toBeAttached ( )
} )
test ( 'First escape in tool pops you out of tool, second exits sketch mode' , async ( {
page ,
} ) = > {
// Wait for the app to be ready for use
2024-07-01 20:55:28 -07:00
const u = await getUtils ( page )
2024-07-03 14:34:45 +10:00
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
await u . openDebugPanel ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await u . closeDebugPanel ( )
const lineButton = page . getByRole ( 'button' , { name : 'Line' } )
const arcButton = page . getByRole ( 'button' , { name : 'Tangential Arc' } )
// Test these hotkeys perform actions when
// focus is on the canvas
await page . mouse . move ( 600 , 250 )
await page . mouse . click ( 600 , 250 )
// Start a sketch
await page . keyboard . press ( 's' )
await page . mouse . move ( 800 , 300 )
await page . mouse . click ( 800 , 300 )
await page . waitForTimeout ( 1000 )
await expect ( lineButton ) . toHaveAttribute ( 'aria-pressed' , 'true' )
// Draw a line
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 )
// Unequip line tool
await page . keyboard . press ( 'Escape' )
// Make sure we didn't pop out of sketch mode.
await expect ( page . getByRole ( 'button' , { name : 'Exit Sketch' } ) ) . toBeVisible ( )
await expect ( lineButton ) . not . toHaveAttribute ( 'aria-pressed' , 'true' )
// Equip arc tool
await page . keyboard . press ( 'a' )
await expect ( arcButton ) . toHaveAttribute ( 'aria-pressed' , 'true' )
await page . mouse . move ( 1000 , 100 , { steps : 5 } )
await page . mouse . click ( 1000 , 100 )
await page . keyboard . press ( 'Escape' )
await page . keyboard . press ( 'l' )
await expect ( lineButton ) . toHaveAttribute ( 'aria-pressed' , 'true' )
// Do not close the sketch.
// On close it will exit sketch mode.
// Unequip line tool
await page . keyboard . press ( 'Escape' )
await expect ( lineButton ) . toHaveAttribute ( 'aria-pressed' , 'false' )
await expect ( arcButton ) . toHaveAttribute ( 'aria-pressed' , 'false' )
// Make sure we didn't pop out of sketch mode.
await expect ( page . getByRole ( 'button' , { name : 'Exit Sketch' } ) ) . toBeVisible ( )
// Exit sketch
await page . keyboard . press ( 'Escape' )
await expect (
page . getByRole ( 'button' , { name : 'Exit Sketch' } )
) . not . toBeVisible ( )
} )
test ( 'Basic default modeling and sketch hotkeys work' , async ( { page } ) = > {
// This test can run long if it takes a little too long to load
// the engine.
test . setTimeout ( 90000 )
// This test has a weird bug on ubuntu
test . skip (
process . platform === 'linux' ,
'weird playwright bug on ubuntu https://github.com/KittyCAD/modeling-app/issues/2444'
)
// Load the app with the code pane open
2024-07-01 20:55:28 -07:00
await page . addInitScript ( async ( ) = > {
2024-07-03 14:34:45 +10:00
localStorage . setItem (
'store' ,
JSON . stringify ( {
state : {
openPanes : [ 'code' ] ,
} ,
version : 0 ,
} )
2024-07-01 20:55:28 -07:00
)
} )
2024-07-03 14:34:45 +10:00
// Wait for the app to be ready for use
const u = await getUtils ( page )
2024-07-01 20:55:28 -07:00
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
2024-07-03 14:34:45 +10:00
await u . openDebugPanel ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await u . closeDebugPanel ( )
2024-07-01 20:55:28 -07:00
2024-07-03 14:34:45 +10:00
const codePane = page . getByRole ( 'textbox' ) . locator ( 'div' )
const codePaneButton = page . getByRole ( 'tab' , { name : 'KCL Code' } )
const lineButton = page . getByRole ( 'button' , { name : 'Line' } )
const arcButton = page . getByRole ( 'button' , { name : 'Tangential Arc' } )
const extrudeButton = page . getByRole ( 'button' , { name : 'Extrude' } )
2024-07-01 20:55:28 -07:00
2024-07-03 14:34:45 +10:00
// Test that the hotkeys do nothing when
// focus is on the code pane
await codePane . click ( )
await page . keyboard . press ( '/' )
await page . keyboard . press ( '/' )
await page . keyboard . press ( 's' )
await page . keyboard . press ( 'l' )
await page . keyboard . press ( 'a' )
await page . keyboard . press ( 'e' )
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( '//slae' )
await page . keyboard . press ( 'Meta+/' )
await page . waitForTimeout ( 2000 )
// Test these hotkeys perform actions when
// focus is on the canvas
await page . mouse . move ( 600 , 250 )
await page . mouse . click ( 600 , 250 )
// Start a sketch
await page . keyboard . press ( 's' )
await page . waitForTimeout ( 2000 )
await page . mouse . move ( 800 , 300 , { steps : 5 } )
await page . mouse . click ( 800 , 300 )
await page . waitForTimeout ( 2000 )
await expect ( lineButton ) . toHaveAttribute ( 'aria-pressed' , 'true' , {
timeout : 15_000 ,
} )
/ * *
* 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 codePaneButton . click ( )
await expect ( u . codeLocator ) . not . toBeVisible ( )
await page . waitForTimeout ( 300 )
2024-07-01 20:55:28 -07:00
2024-07-03 14:34:45 +10:00
// Draw a line
await page . mouse . move ( 700 , 200 , { steps : 5 } )
await page . mouse . click ( 700 , 200 )
await page . waitForTimeout ( 300 )
await page . mouse . move ( 800 , 250 , { steps : 5 } )
await page . mouse . click ( 800 , 250 )
// Unequip line tool
await page . keyboard . press ( 'l' )
await expect ( lineButton ) . not . toHaveAttribute ( 'aria-pressed' , 'true' )
// Equip arc tool
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 page . keyboard . press ( 'Escape' )
await page . keyboard . press ( 'l' )
await expect ( lineButton ) . toHaveAttribute ( 'aria-pressed' , 'true' )
// Close profile
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' )
// Exit sketch
await page . keyboard . press ( 'Escape' )
await expect (
page . getByRole ( 'button' , { name : 'Exit Sketch' } )
) . not . toBeVisible ( )
await page . waitForTimeout ( 400 )
2024-07-01 20:55:28 -07:00
2024-07-03 14:34:45 +10:00
// Extrude
await page . mouse . click ( 750 , 150 )
await expect ( extrudeButton ) . not . toBeDisabled ( )
await page . keyboard . press ( 'e' )
2024-07-01 20:55:28 -07:00
await page . waitForTimeout ( 100 )
2024-07-03 14:34:45 +10:00
await page . mouse . move ( 800 , 200 , { steps : 5 } )
await page . mouse . click ( 800 , 200 )
await page . waitForTimeout ( 300 )
await expect ( page . getByRole ( 'button' , { name : 'Continue' } ) ) . toBeVisible ( )
await page . getByRole ( 'button' , { name : 'Continue' } ) . click ( )
await page . waitForTimeout ( 300 )
await expect (
page . getByRole ( 'button' , { name : 'Submit command' } )
) . toBeVisible ( )
await page . getByRole ( 'button' , { name : 'Submit command' } ) . click ( )
2024-07-01 20:55:28 -07:00
2024-07-03 14:34:45 +10:00
await codePaneButton . click ( )
await expect ( page . locator ( '.cm-content' ) ) . toContainText ( 'extrude(' )
2024-07-01 20:55:28 -07:00
} )
2024-07-03 14:34:45 +10:00
test ( 'Sketch on face' , async ( { page } ) = > {
test . setTimeout ( 90 _000 )
2024-07-01 20:55:28 -07:00
const u = await getUtils ( page )
await page . addInitScript ( async ( ) = > {
localStorage . setItem (
'persistCode' ,
` const sketch001 = startSketchOn('XZ')
2024-07-03 14:34:45 +10:00
| > startProfileAt ( [ 3.29 , 7.86 ] , % )
| > line ( [ 2.48 , 2.44 ] , % )
| > line ( [ 2.66 , 1.17 ] , % )
| > line ( [ 3.75 , 0.46 ] , % )
| > line ( [ 4.99 , - 0.46 ] , % )
| > line ( [ 3.3 , - 2.12 ] , % )
| > line ( [ 2.16 , - 3.33 ] , % )
| > line ( [ 0.85 , - 3.08 ] , % )
| > line ( [ - 0.18 , - 3.36 ] , % )
| > line ( [ - 3.86 , - 2.73 ] , % )
| > line ( [ - 17.67 , 0.85 ] , % )
2024-07-01 20:55:28 -07:00
| > close ( % )
2024-07-03 14:34:45 +10:00
const extrude001 = extrude ( 5 + 7 , sketch001 ) `
2024-07-01 20:55:28 -07:00
)
} )
await page . setViewportSize ( { width : 1200 , height : 500 } )
await u . waitForAuthSkipAppStart ( )
2024-07-03 14:34:45 +10:00
// wait for execution done
await u . openDebugPanel ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
await u . closeDebugPanel ( )
2024-07-01 20:55:28 -07:00
await expect (
page . getByRole ( 'button' , { name : 'Start Sketch' } )
) . not . toBeDisabled ( )
2024-07-03 14:34:45 +10:00
await page . getByRole ( 'button' , { name : 'Start Sketch' } ) . click ( )
await page . waitForTimeout ( 300 )
let previousCodeContent = await page . locator ( '.cm-content' ) . innerText ( )
2024-07-01 20:55:28 -07:00
await u . openAndClearDebugPanel ( )
2024-07-03 14:34:45 +10:00
await u . doAndWaitForCmd (
( ) = > page . mouse . click ( 625 , 133 ) ,
'default_camera_get_settings' ,
true
)
await page . waitForTimeout ( 150 )
await u . closeDebugPanel ( )
const firstClickPosition = [ 612 , 238 ]
const secondClickPosition = [ 661 , 242 ]
const thirdClickPosition = [ 609 , 267 ]
await page . mouse . click ( firstClickPosition [ 0 ] , firstClickPosition [ 1 ] )
await expect ( page . locator ( '.cm-content' ) ) . not . toHaveText ( previousCodeContent )
previousCodeContent = await page . locator ( '.cm-content' ) . innerText ( )
2024-07-01 20:55:28 -07:00
await page . waitForTimeout ( 100 )
2024-07-03 14:34:45 +10:00
await page . mouse . click ( secondClickPosition [ 0 ] , secondClickPosition [ 1 ] )
await expect ( page . locator ( '.cm-content' ) ) . not . toHaveText ( previousCodeContent )
previousCodeContent = await page . locator ( '.cm-content' ) . innerText ( )
await page . waitForTimeout ( 100 )
await page . mouse . click ( thirdClickPosition [ 0 ] , thirdClickPosition [ 1 ] )
await expect ( page . locator ( '.cm-content' ) ) . not . toHaveText ( previousCodeContent )
previousCodeContent = await page . locator ( '.cm-content' ) . innerText ( )
2024-07-01 20:55:28 -07:00
await page . waitForTimeout ( 100 )
2024-07-03 14:34:45 +10:00
await page . mouse . click ( firstClickPosition [ 0 ] , firstClickPosition [ 1 ] )
await expect ( page . locator ( '.cm-content' ) ) . not . toHaveText ( previousCodeContent )
previousCodeContent = await page . locator ( '.cm-content' ) . innerText ( )
await expect ( page . locator ( '.cm-content' ) )
. toContainText ( ` const sketch002 = startSketchOn(extrude001, seg01)
| > startProfileAt ( [ - 12.94 , 6.6 ] , % )
| > line ( [ 2.45 , - 0.2 ] , % )
| > line ( [ - 2.6 , - 1.25 ] , % )
| > lineTo ( [ profileStartX ( % ) , profileStartY ( % ) ] , % )
| > close ( % ) ` )
2024-07-01 20:55:28 -07:00
2024-07-03 14:34:45 +10:00
await u . openAndClearDebugPanel ( )
await page . getByRole ( 'button' , { name : 'Exit Sketch' } ) . click ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
2024-07-01 20:55:28 -07:00
2024-07-03 14:34:45 +10:00
await u . updateCamPosition ( [ 1049 , 239 , 686 ] )
await u . closeDebugPanel ( )
2024-07-01 20:55:28 -07:00
2024-07-03 14:34:45 +10:00
await page . getByText ( 'startProfileAt([-12.94, 6.6], %)' ) . click ( )
2024-07-01 20:55:28 -07:00
await expect ( page . getByRole ( 'button' , { name : 'Edit Sketch' } ) ) . toBeVisible ( )
await page . getByRole ( 'button' , { name : 'Edit Sketch' } ) . click ( )
await page . waitForTimeout ( 400 )
2024-07-03 14:34:45 +10:00
await page . waitForTimeout ( 150 )
await page . setViewportSize ( { width : 1200 , height : 1200 } )
await u . openAndClearDebugPanel ( )
await u . updateCamPosition ( [ 452 , - 152 , 1166 ] )
await u . closeDebugPanel ( )
await page . waitForTimeout ( 200 )
2024-07-01 20:55:28 -07:00
2024-07-03 14:34:45 +10:00
const pointToDragFirst = [ 787 , 565 ]
await page . mouse . move ( pointToDragFirst [ 0 ] , pointToDragFirst [ 1 ] )
await page . mouse . down ( )
await page . mouse . move ( pointToDragFirst [ 0 ] - 20 , pointToDragFirst [ 1 ] , {
steps : 5 ,
2024-07-01 20:55:28 -07:00
} )
2024-07-03 14:34:45 +10:00
await page . mouse . up ( )
2024-07-01 20:55:28 -07:00
await page . waitForTimeout ( 100 )
2024-07-03 14:34:45 +10:00
await expect ( page . locator ( '.cm-content' ) ) . not . toHaveText ( previousCodeContent )
previousCodeContent = await page . locator ( '.cm-content' ) . innerText ( )
2024-07-01 20:55:28 -07:00
2024-07-03 14:34:45 +10:00
const result = makeTemplate ` const sketch002 = startSketchOn(extrude001, seg01)
| > startProfileAt ( [ - 12.83 , 6.7 ] , % )
| > line ( [ $ { [ 2.28 , 2.35 ] } , - $ { 0.07 } ] , % )
| > line ( [ - 3.05 , - 1.47 ] , % )
| > lineTo ( [ profileStartX ( % ) , profileStartY ( % ) ] , % )
| > close ( % ) `
2024-07-01 20:55:28 -07:00
2024-07-03 14:34:45 +10:00
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( result . regExp )
2024-07-01 20:55:28 -07:00
2024-07-03 14:34:45 +10:00
// exit sketch
await u . openAndClearDebugPanel ( )
await page . getByRole ( 'button' , { name : 'Exit Sketch' } ) . click ( )
await u . expectCmdLog ( '[data-message-type="execution-done"]' )
2024-07-01 20:55:28 -07:00
2024-07-03 14:34:45 +10:00
await page . getByText ( 'startProfileAt([-12.94, 6.6], %)' ) . click ( )
2024-07-01 20:55:28 -07:00
2024-07-03 14:34:45 +10:00
await expect ( page . getByRole ( 'button' , { name : 'Extrude' } ) ) . not . toBeDisabled ( )
await page . waitForTimeout ( 100 )
await page . getByRole ( 'button' , { name : 'Extrude' } ) . click ( )
2024-07-01 20:55:28 -07:00
2024-07-03 14:34:45 +10:00
await expect ( page . getByTestId ( 'command-bar' ) ) . toBeVisible ( )
await page . waitForTimeout ( 100 )
2024-07-01 20:55:28 -07:00
2024-07-03 14:34:45 +10:00
await page . keyboard . press ( 'Enter' )
2024-07-01 20:55:28 -07:00
await page . waitForTimeout ( 100 )
2024-07-03 14:34:45 +10:00
await expect ( page . getByText ( 'Confirm Extrude' ) ) . toBeVisible ( )
await page . keyboard . press ( 'Enter' )
2024-07-01 20:55:28 -07:00
2024-07-03 14:34:45 +10:00
const result2 = result . genNext `
const sketch002 = extrude ( $ { [ 5 , 5 ] } + 7 , sketch002 ) `
await expect ( page . locator ( '.cm-content' ) ) . toHaveText ( result2 . regExp )
} )