Nadro/adhoc/e2e improvements (#4013)
* chore: saving off package.json progress unit tests fail in main
* fix: implementing a one liner for unit tests
* fix: renaming test:unit:local
* chore: adding playwright tests
* fix: making package.json not destructive to keep same pipeline commands for now
* fix: reordering
* fix: added tags for OS tests, moved kill-port to dev depen
* fix: OS skipping at tag level
* fix: lint, fmt, tsc, etc...
* Look at this (photo)Graph *in the voice of Nickelback*
* fix: new formatting
* fix: removing the ci copy, do not like it
* Look at this (photo)Graph *in the voice of Nickelback*
* chore: updating readme with explanation on the commands for CI CD simulation locally
* fix: package.json command for unit test, removing cached breaking cache in unit tests
* fix: fixing copy and typos in README.md for CI CD section
* fix: adding a duplicate command for a better name. CI CD will use it in a future PR
* fix: this is wrong... removing it
* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)
* Revert "A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)"
This reverts commit f767dd46d4
.
* fix: typos in README.md
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Kurt Hutten Irev-Dev <k.hutten@protonmail.ch>
This commit is contained in:
64
README.md
64
README.md
@ -322,6 +322,70 @@ cd src/wasm-lib
|
||||
cargo test
|
||||
```
|
||||
|
||||
### Mapping CI CD jobs to local commands
|
||||
|
||||
When you see the CI CD fail on jobs you may wonder three things
|
||||
- Do I have a bug in my code?
|
||||
- Is the test flaky?
|
||||
- Is there a bug in `main`?
|
||||
|
||||
To answer these questions the following commands will give you confidence to locate the issue.
|
||||
|
||||
#### Static Analysis
|
||||
|
||||
Part of the CI CD pipeline performs static analysis on the code. Use the following commands to mimic the CI CD jobs.
|
||||
|
||||
The following set of commands should get us closer to one and done commands to instantly retest issues.
|
||||
|
||||
```
|
||||
yarn test-setup
|
||||
```
|
||||
|
||||
> Gotcha, are packages up to date and is the wasm built?
|
||||
|
||||
|
||||
```
|
||||
yarn tsc
|
||||
yarn fmt-check
|
||||
yarn lint
|
||||
yarn xstate:typegen
|
||||
yarn test:unit:local
|
||||
```
|
||||
|
||||
> Gotcha: Our unit tests have integration tests in them. You need to run a localhost server to run the unit tests.
|
||||
|
||||
#### E2E Tests
|
||||
|
||||
**Playwright Browser**
|
||||
|
||||
These E2E tests run in a browser (without electron).
|
||||
There are tests that are skipped if they are ran in a windows OS or Linux OS. We can use playwright tags to implement test skipping.
|
||||
|
||||
Breaking down the command `yarn test:playwright:browser:chrome:windows`
|
||||
- The application is `playwright`
|
||||
- The runtime is a `browser`
|
||||
- The specific `browser` is `chrome`
|
||||
- The test should run in a `windows` environment. It will skip tests that are broken or flaky in the windows OS.
|
||||
|
||||
```
|
||||
yarn test:playwright:browser:chrome
|
||||
yarn test:playwright:browser:chrome:windows
|
||||
yarn test:playwright:browser:chrome:ubuntu
|
||||
```
|
||||
|
||||
**Playwright Electron**
|
||||
|
||||
These E2E tests run in electron. There are tests that are skipped if they are ran in a windows, linux, or macos environment. We can use playwright tags to implement test skipping.
|
||||
|
||||
```
|
||||
yarn test:playwright:electron:local
|
||||
yarn test:playwright:electron:windows:local
|
||||
yarn test:playwright:electron:macos:local
|
||||
yarn test:playwright:electron:ubuntu:local
|
||||
```
|
||||
|
||||
> Why does it say local? The CI CD commands that run in the pipeline cannot be ran locally. A single command will not properly setup the testing environment locally.
|
||||
|
||||
#### Some notes on CI
|
||||
|
||||
The tests are broken into snapshot tests and non-snapshot tests, and they run in that order, they automatically commit new snap shots, so if you see an image commit check it was an intended change. If we have non-determinism in the snapshots such that they are always committing new images, hopefully this annoyance makes us fix them asap, if you notice this happening let Kurt know. But for the odd occasion `git reset --hard HEAD~ && git push -f` is your friend.
|
||||
|
@ -154,7 +154,7 @@ async function doBasicSketch(page: Page, openPanes: string[]) {
|
||||
}
|
||||
|
||||
test.describe('Basic sketch', () => {
|
||||
test('code pane open at start', async ({ page }) => {
|
||||
test('code pane open at start', { tag: ['@skipWin'] }, async ({ page }) => {
|
||||
// Skip on windows it is being weird.
|
||||
test.skip(process.platform === 'win32', 'Skip on windows')
|
||||
await doBasicSketch(page, ['code'])
|
||||
|
@ -5,71 +5,69 @@ import { ToolbarFixture } from './fixtures/toolbarFixture'
|
||||
|
||||
// test file is for testing point an click code gen functionality that's not sketch mode related
|
||||
|
||||
test('verify extruding circle works', async ({
|
||||
app,
|
||||
cmdBar,
|
||||
editor,
|
||||
toolbar,
|
||||
scene,
|
||||
}) => {
|
||||
test.skip(
|
||||
process.platform === 'win32',
|
||||
'Fails on windows in CI, can not be replicated locally on windows.'
|
||||
)
|
||||
const file = await app.getInputFile('test-circle-extrude.kcl')
|
||||
await app.initialise(file)
|
||||
const [clickCircle, moveToCircle] = scene.makeMouseHelpers(582, 217)
|
||||
test(
|
||||
'verify extruding circle works',
|
||||
{ tag: ['@skipWin'] },
|
||||
async ({ app, cmdBar, editor, toolbar, scene }) => {
|
||||
test.skip(
|
||||
process.platform === 'win32',
|
||||
'Fails on windows in CI, can not be replicated locally on windows.'
|
||||
)
|
||||
const file = await app.getInputFile('test-circle-extrude.kcl')
|
||||
await app.initialise(file)
|
||||
const [clickCircle, moveToCircle] = scene.makeMouseHelpers(582, 217)
|
||||
|
||||
await test.step('because there is sweepable geometry, verify extrude is enable when nothing is selected', async () => {
|
||||
await scene.clickNoWhere()
|
||||
await expect(toolbar.extrudeButton).toBeEnabled()
|
||||
})
|
||||
|
||||
await test.step('check code model connection works and that button is still enable once circle is selected ', async () => {
|
||||
await moveToCircle()
|
||||
const circleSnippet =
|
||||
'circle({ center: [318.33, 168.1], radius: 182.8 }, %)'
|
||||
await editor.expectState({
|
||||
activeLines: [],
|
||||
highlightedCode: circleSnippet,
|
||||
diagnostics: [],
|
||||
await test.step('because there is sweepable geometry, verify extrude is enable when nothing is selected', async () => {
|
||||
await scene.clickNoWhere()
|
||||
await expect(toolbar.extrudeButton).toBeEnabled()
|
||||
})
|
||||
|
||||
await clickCircle()
|
||||
await editor.expectState({
|
||||
activeLines: [circleSnippet.slice(-5)],
|
||||
highlightedCode: circleSnippet,
|
||||
diagnostics: [],
|
||||
await test.step('check code model connection works and that button is still enable once circle is selected ', async () => {
|
||||
await moveToCircle()
|
||||
const circleSnippet =
|
||||
'circle({ center: [318.33, 168.1], radius: 182.8 }, %)'
|
||||
await editor.expectState({
|
||||
activeLines: [],
|
||||
highlightedCode: circleSnippet,
|
||||
diagnostics: [],
|
||||
})
|
||||
|
||||
await clickCircle()
|
||||
await editor.expectState({
|
||||
activeLines: [circleSnippet.slice(-5)],
|
||||
highlightedCode: circleSnippet,
|
||||
diagnostics: [],
|
||||
})
|
||||
await expect(toolbar.extrudeButton).toBeEnabled()
|
||||
})
|
||||
await expect(toolbar.extrudeButton).toBeEnabled()
|
||||
})
|
||||
|
||||
await test.step('do extrude flow and check extrude code is added to editor', async () => {
|
||||
await toolbar.extrudeButton.click()
|
||||
await test.step('do extrude flow and check extrude code is added to editor', async () => {
|
||||
await toolbar.extrudeButton.click()
|
||||
|
||||
await cmdBar.expectState({
|
||||
stage: 'arguments',
|
||||
currentArgKey: 'distance',
|
||||
currentArgValue: '5',
|
||||
headerArguments: { Selection: '1 face', Distance: '' },
|
||||
highlightedHeaderArg: 'distance',
|
||||
commandName: 'Extrude',
|
||||
await cmdBar.expectState({
|
||||
stage: 'arguments',
|
||||
currentArgKey: 'distance',
|
||||
currentArgValue: '5',
|
||||
headerArguments: { Selection: '1 face', Distance: '' },
|
||||
highlightedHeaderArg: 'distance',
|
||||
commandName: 'Extrude',
|
||||
})
|
||||
await cmdBar.progressCmdBar()
|
||||
|
||||
const expectString = 'const extrude001 = extrude(5, sketch001)'
|
||||
await editor.expectEditor.not.toContain(expectString)
|
||||
|
||||
await cmdBar.expectState({
|
||||
stage: 'review',
|
||||
headerArguments: { Selection: '1 face', Distance: '5' },
|
||||
commandName: 'Extrude',
|
||||
})
|
||||
await cmdBar.progressCmdBar()
|
||||
|
||||
await editor.expectEditor.toContain(expectString)
|
||||
})
|
||||
await cmdBar.progressCmdBar()
|
||||
|
||||
const expectString = 'const extrude001 = extrude(5, sketch001)'
|
||||
await editor.expectEditor.not.toContain(expectString)
|
||||
|
||||
await cmdBar.expectState({
|
||||
stage: 'review',
|
||||
headerArguments: { Selection: '1 face', Distance: '5' },
|
||||
commandName: 'Extrude',
|
||||
})
|
||||
await cmdBar.progressCmdBar()
|
||||
|
||||
await editor.expectEditor.toContain(expectString)
|
||||
})
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
test.describe('verify sketch on chamfer works', () => {
|
||||
const _sketchOnAChamfer =
|
||||
@ -152,36 +150,34 @@ test.describe('verify sketch on chamfer works', () => {
|
||||
})
|
||||
})
|
||||
}
|
||||
test('works on all edge selections and can break up multi edges in a chamfer array', async ({
|
||||
app,
|
||||
editor,
|
||||
toolbar,
|
||||
scene,
|
||||
}) => {
|
||||
test.skip(
|
||||
process.platform === 'win32',
|
||||
'Fails on windows in CI, can not be replicated locally on windows.'
|
||||
)
|
||||
const file = await app.getInputFile('e2e-can-sketch-on-chamfer.kcl')
|
||||
await app.initialise(file)
|
||||
test(
|
||||
'works on all edge selections and can break up multi edges in a chamfer array',
|
||||
{ tag: ['@skipWin'] },
|
||||
async ({ app, editor, toolbar, scene }) => {
|
||||
test.skip(
|
||||
process.platform === 'win32',
|
||||
'Fails on windows in CI, can not be replicated locally on windows.'
|
||||
)
|
||||
const file = await app.getInputFile('e2e-can-sketch-on-chamfer.kcl')
|
||||
await app.initialise(file)
|
||||
|
||||
const sketchOnAChamfer = _sketchOnAChamfer(app, editor, toolbar, scene)
|
||||
const sketchOnAChamfer = _sketchOnAChamfer(app, editor, toolbar, scene)
|
||||
|
||||
await sketchOnAChamfer({
|
||||
clickCoords: { x: 570, y: 220 },
|
||||
cameraPos: { x: 16020, y: -2000, z: 10500 },
|
||||
cameraTarget: { x: -150, y: -4500, z: -80 },
|
||||
beforeChamferSnippet: `angledLine([segAng(rectangleSegmentA001)-90,217.26],%,$seg01)
|
||||
await sketchOnAChamfer({
|
||||
clickCoords: { x: 570, y: 220 },
|
||||
cameraPos: { x: 16020, y: -2000, z: 10500 },
|
||||
cameraTarget: { x: -150, y: -4500, z: -80 },
|
||||
beforeChamferSnippet: `angledLine([segAng(rectangleSegmentA001)-90,217.26],%,$seg01)
|
||||
chamfer({length:30,tags:[
|
||||
seg01,
|
||||
getNextAdjacentEdge(yo),
|
||||
getNextAdjacentEdge(seg02),
|
||||
getOppositeEdge(seg01)
|
||||
]}, %)`,
|
||||
afterChamferSelectSnippet:
|
||||
'const sketch002 = startSketchOn(extrude001, seg03)',
|
||||
afterRectangle1stClickSnippet: 'startProfileAt([205.96, 254.59], %)',
|
||||
afterRectangle2ndClickSnippet: `angledLine([0, 11.39], %, $rectangleSegmentA002)
|
||||
afterChamferSelectSnippet:
|
||||
'const sketch002 = startSketchOn(extrude001, seg03)',
|
||||
afterRectangle1stClickSnippet: 'startProfileAt([205.96, 254.59], %)',
|
||||
afterRectangle2ndClickSnippet: `angledLine([0, 11.39], %, $rectangleSegmentA002)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA002) - 90,
|
||||
105.26
|
||||
@ -192,13 +188,13 @@ test.describe('verify sketch on chamfer works', () => {
|
||||
], %, $rectangleSegmentC001)
|
||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||
|> close(%)`,
|
||||
})
|
||||
})
|
||||
|
||||
await sketchOnAChamfer({
|
||||
clickCoords: { x: 690, y: 250 },
|
||||
cameraPos: { x: 16020, y: -2000, z: 10500 },
|
||||
cameraTarget: { x: -150, y: -4500, z: -80 },
|
||||
beforeChamferSnippet: `angledLine([
|
||||
await sketchOnAChamfer({
|
||||
clickCoords: { x: 690, y: 250 },
|
||||
cameraPos: { x: 16020, y: -2000, z: 10500 },
|
||||
cameraTarget: { x: -150, y: -4500, z: -80 },
|
||||
beforeChamferSnippet: `angledLine([
|
||||
segAng(rectangleSegmentA001) - 90,
|
||||
217.26
|
||||
], %, $seg01)chamfer({
|
||||
@ -209,10 +205,10 @@ test.describe('verify sketch on chamfer works', () => {
|
||||
getNextAdjacentEdge(seg02)
|
||||
]
|
||||
}, %)`,
|
||||
afterChamferSelectSnippet:
|
||||
'const sketch003 = startSketchOn(extrude001, seg04)',
|
||||
afterRectangle1stClickSnippet: 'startProfileAt([-209.64, 255.28], %)',
|
||||
afterRectangle2ndClickSnippet: `angledLine([0, 11.56], %, $rectangleSegmentA003)
|
||||
afterChamferSelectSnippet:
|
||||
'const sketch003 = startSketchOn(extrude001, seg04)',
|
||||
afterRectangle1stClickSnippet: 'startProfileAt([-209.64, 255.28], %)',
|
||||
afterRectangle2ndClickSnippet: `angledLine([0, 11.56], %, $rectangleSegmentA003)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA003) - 90,
|
||||
106.84
|
||||
@ -223,22 +219,22 @@ test.describe('verify sketch on chamfer works', () => {
|
||||
], %, $rectangleSegmentC002)
|
||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||
|> close(%)`,
|
||||
})
|
||||
await sketchOnAChamfer({
|
||||
clickCoords: { x: 677, y: 87 },
|
||||
cameraPos: { x: -6200, y: 1500, z: 6200 },
|
||||
cameraTarget: { x: 8300, y: 1100, z: 4800 },
|
||||
beforeChamferSnippet: `angledLine([0, 268.43], %, $rectangleSegmentA001)chamfer({
|
||||
})
|
||||
await sketchOnAChamfer({
|
||||
clickCoords: { x: 677, y: 87 },
|
||||
cameraPos: { x: -6200, y: 1500, z: 6200 },
|
||||
cameraTarget: { x: 8300, y: 1100, z: 4800 },
|
||||
beforeChamferSnippet: `angledLine([0, 268.43], %, $rectangleSegmentA001)chamfer({
|
||||
length: 30,
|
||||
tags: [
|
||||
getNextAdjacentEdge(yo),
|
||||
getNextAdjacentEdge(seg02)
|
||||
]
|
||||
}, %)`,
|
||||
afterChamferSelectSnippet:
|
||||
'const sketch003 = startSketchOn(extrude001, seg04)',
|
||||
afterRectangle1stClickSnippet: 'startProfileAt([-209.64, 255.28], %)',
|
||||
afterRectangle2ndClickSnippet: `angledLine([0, 11.56], %, $rectangleSegmentA003)
|
||||
afterChamferSelectSnippet:
|
||||
'const sketch003 = startSketchOn(extrude001, seg04)',
|
||||
afterRectangle1stClickSnippet: 'startProfileAt([-209.64, 255.28], %)',
|
||||
afterRectangle2ndClickSnippet: `angledLine([0, 11.56], %, $rectangleSegmentA003)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA003) - 90,
|
||||
106.84
|
||||
@ -249,20 +245,20 @@ test.describe('verify sketch on chamfer works', () => {
|
||||
], %, $rectangleSegmentC002)
|
||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||
|> close(%)`,
|
||||
})
|
||||
/// last one
|
||||
await sketchOnAChamfer({
|
||||
clickCoords: { x: 620, y: 300 },
|
||||
cameraPos: { x: -1100, y: -7700, z: 1600 },
|
||||
cameraTarget: { x: 1450, y: 670, z: 4000 },
|
||||
beforeChamferSnippet: `chamfer({
|
||||
})
|
||||
/// last one
|
||||
await sketchOnAChamfer({
|
||||
clickCoords: { x: 620, y: 300 },
|
||||
cameraPos: { x: -1100, y: -7700, z: 1600 },
|
||||
cameraTarget: { x: 1450, y: 670, z: 4000 },
|
||||
beforeChamferSnippet: `chamfer({
|
||||
length: 30,
|
||||
tags: [getNextAdjacentEdge(yo)]
|
||||
}, %)`,
|
||||
afterChamferSelectSnippet:
|
||||
'const sketch005 = startSketchOn(extrude001, seg06)',
|
||||
afterRectangle1stClickSnippet: 'startProfileAt([-23.43, 19.69], %)',
|
||||
afterRectangle2ndClickSnippet: `angledLine([0, 9.1], %, $rectangleSegmentA005)
|
||||
afterChamferSelectSnippet:
|
||||
'const sketch005 = startSketchOn(extrude001, seg06)',
|
||||
afterRectangle1stClickSnippet: 'startProfileAt([-23.43, 19.69], %)',
|
||||
afterRectangle2ndClickSnippet: `angledLine([0, 9.1], %, $rectangleSegmentA005)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA005) - 90,
|
||||
84.07
|
||||
@ -273,11 +269,11 @@ test.describe('verify sketch on chamfer works', () => {
|
||||
], %, $rectangleSegmentC004)
|
||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||
|> close(%)`,
|
||||
})
|
||||
})
|
||||
|
||||
await test.step('verify at the end of the test that final code is what is expected', async () => {
|
||||
await editor.expectEditor.toContain(
|
||||
`const sketch001 = startSketchOn('XZ')
|
||||
await test.step('verify at the end of the test that final code is what is expected', async () => {
|
||||
await editor.expectEditor.toContain(
|
||||
`const sketch001 = startSketchOn('XZ')
|
||||
|> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag]
|
||||
|> angledLine([0, 268.43], %, $rectangleSegmentA001)
|
||||
|> angledLine([
|
||||
@ -357,44 +353,43 @@ test.describe('verify sketch on chamfer works', () => {
|
||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||
|> close(%)
|
||||
`,
|
||||
{ shouldNormalise: true }
|
||||
{ shouldNormalise: true }
|
||||
)
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
test(
|
||||
'Works on chamfers that are non in a pipeExpression can break up multi edges in a chamfer array',
|
||||
{ tag: ['@skipWin'] },
|
||||
async ({ app, editor, toolbar, scene }) => {
|
||||
test.skip(
|
||||
process.platform === 'win32',
|
||||
'Fails on windows in CI, can not be replicated locally on windows.'
|
||||
)
|
||||
})
|
||||
})
|
||||
const file = await app.getInputFile(
|
||||
'e2e-can-sketch-on-chamfer-no-pipeExpr.kcl'
|
||||
)
|
||||
await app.initialise(file)
|
||||
|
||||
test('Works on chamfers that are non in a pipeExpression can break up multi edges in a chamfer array', async ({
|
||||
app,
|
||||
editor,
|
||||
toolbar,
|
||||
scene,
|
||||
}) => {
|
||||
test.skip(
|
||||
process.platform === 'win32',
|
||||
'Fails on windows in CI, can not be replicated locally on windows.'
|
||||
)
|
||||
const file = await app.getInputFile(
|
||||
'e2e-can-sketch-on-chamfer-no-pipeExpr.kcl'
|
||||
)
|
||||
await app.initialise(file)
|
||||
const sketchOnAChamfer = _sketchOnAChamfer(app, editor, toolbar, scene)
|
||||
|
||||
const sketchOnAChamfer = _sketchOnAChamfer(app, editor, toolbar, scene)
|
||||
|
||||
await sketchOnAChamfer({
|
||||
clickCoords: { x: 570, y: 220 },
|
||||
cameraPos: { x: 16020, y: -2000, z: 10500 },
|
||||
cameraTarget: { x: -150, y: -4500, z: -80 },
|
||||
beforeChamferSnippet: `angledLine([segAng(rectangleSegmentA001)-90,217.26],%,$seg01)
|
||||
await sketchOnAChamfer({
|
||||
clickCoords: { x: 570, y: 220 },
|
||||
cameraPos: { x: 16020, y: -2000, z: 10500 },
|
||||
cameraTarget: { x: -150, y: -4500, z: -80 },
|
||||
beforeChamferSnippet: `angledLine([segAng(rectangleSegmentA001)-90,217.26],%,$seg01)
|
||||
chamfer({length:30,tags:[
|
||||
seg01,
|
||||
getNextAdjacentEdge(yo),
|
||||
getNextAdjacentEdge(seg02),
|
||||
getOppositeEdge(seg01)
|
||||
]}, extrude001)`,
|
||||
beforeChamferSnippetEnd: '}, extrude001)',
|
||||
afterChamferSelectSnippet:
|
||||
'const sketch002 = startSketchOn(extrude001, seg03)',
|
||||
afterRectangle1stClickSnippet: 'startProfileAt([205.96, 254.59], %)',
|
||||
afterRectangle2ndClickSnippet: `angledLine([0, 11.39], %, $rectangleSegmentA002)
|
||||
beforeChamferSnippetEnd: '}, extrude001)',
|
||||
afterChamferSelectSnippet:
|
||||
'const sketch002 = startSketchOn(extrude001, seg03)',
|
||||
afterRectangle1stClickSnippet: 'startProfileAt([205.96, 254.59], %)',
|
||||
afterRectangle2ndClickSnippet: `angledLine([0, 11.39], %, $rectangleSegmentA002)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA002) - 90,
|
||||
105.26
|
||||
@ -405,9 +400,9 @@ test.describe('verify sketch on chamfer works', () => {
|
||||
], %, $rectangleSegmentC001)
|
||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||
|> close(%)`,
|
||||
})
|
||||
await editor.expectEditor.toContain(
|
||||
`const sketch001 = startSketchOn('XZ')
|
||||
})
|
||||
await editor.expectEditor.toContain(
|
||||
`const sketch001 = startSketchOn('XZ')
|
||||
|> startProfileAt([75.8, 317.2], %)
|
||||
|> angledLine([0, 268.43], %, $rectangleSegmentA001)
|
||||
|> angledLine([
|
||||
@ -447,7 +442,8 @@ const sketch002 = startSketchOn(extrude001, seg03)
|
||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||
|> close(%)
|
||||
`,
|
||||
{ shouldNormalise: true }
|
||||
)
|
||||
})
|
||||
{ shouldNormalise: true }
|
||||
)
|
||||
}
|
||||
)
|
||||
})
|
||||
|
@ -221,20 +221,23 @@ const sketch001 = startSketchAt([-0, -0])
|
||||
// Make sure it's not a link
|
||||
await expect(zooLogo).not.toHaveAttribute('href')
|
||||
})
|
||||
test('Position _ Is Out Of Range... regression test', async ({ page }) => {
|
||||
// SKip on windows, its being weird.
|
||||
test.skip(
|
||||
process.platform === 'win32',
|
||||
'This test is being weird on windows'
|
||||
)
|
||||
test(
|
||||
'Position _ Is Out Of Range... regression test',
|
||||
{ tag: ['@skipWin'] },
|
||||
async ({ page }) => {
|
||||
// SKip on windows, its being weird.
|
||||
test.skip(
|
||||
process.platform === 'win32',
|
||||
'This test is being weird on windows'
|
||||
)
|
||||
|
||||
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")
|
||||
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")
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> angledLine({ angle: 50, length: 45 }, %)
|
||||
|> yLineTo(0, %)
|
||||
@ -243,53 +246,53 @@ const sketch001 = startSketchAt([-0, -0])
|
||||
|
||||
const example = extrude(5, exampleSketch)
|
||||
shell({ faces: ['end'], thickness: 0.25 }, exampleSketch)`
|
||||
)
|
||||
})
|
||||
|
||||
await expect(async () => {
|
||||
await page.goto('/')
|
||||
await u.waitForPageLoad()
|
||||
// error in guter
|
||||
await expect(page.locator('.cm-lint-marker-error')).toBeVisible({
|
||||
timeout: 1_000,
|
||||
)
|
||||
})
|
||||
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: 1_000,
|
||||
})
|
||||
}).toPass({ timeout: 40_000, intervals: [1_000] })
|
||||
|
||||
// error text on hover
|
||||
await page.hover('.cm-lint-marker-error')
|
||||
await expect(page.getByText('Unexpected token: |').first()).toBeVisible()
|
||||
await expect(async () => {
|
||||
await page.goto('/')
|
||||
await u.waitForPageLoad()
|
||||
// error in guter
|
||||
await expect(page.locator('.cm-lint-marker-error')).toBeVisible({
|
||||
timeout: 1_000,
|
||||
})
|
||||
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: 1_000,
|
||||
})
|
||||
}).toPass({ timeout: 40_000, intervals: [1_000] })
|
||||
|
||||
// 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')
|
||||
await page.keyboard.press('End')
|
||||
await page.keyboard.up('Shift')
|
||||
await page.keyboard.press('Backspace')
|
||||
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
|
||||
// error text on hover
|
||||
await page.hover('.cm-lint-marker-error')
|
||||
await expect(page.getByText('Unexpected token: |').first()).toBeVisible()
|
||||
|
||||
await page.keyboard.press('Enter')
|
||||
await page.keyboard.press('Enter')
|
||||
await page.keyboard.type('thing: "blah"', { delay: 100 })
|
||||
await page.keyboard.press('Enter')
|
||||
await page.keyboard.press('ArrowLeft')
|
||||
// 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')
|
||||
await page.keyboard.press('End')
|
||||
await page.keyboard.up('Shift')
|
||||
await page.keyboard.press('Backspace')
|
||||
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
|
||||
|
||||
await expect(page.locator('.cm-content'))
|
||||
.toContainText(`const exampleSketch = startSketchOn("XZ")
|
||||
await page.keyboard.press('Enter')
|
||||
await page.keyboard.press('Enter')
|
||||
await page.keyboard.type('thing: "blah"', { delay: 100 })
|
||||
await page.keyboard.press('Enter')
|
||||
await page.keyboard.press('ArrowLeft')
|
||||
|
||||
await expect(page.locator('.cm-content'))
|
||||
.toContainText(`const exampleSketch = startSketchOn("XZ")
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> angledLine({ angle: 50, length: 45 }, %)
|
||||
|> yLineTo(0, %)
|
||||
@ -297,8 +300,9 @@ const sketch001 = startSketchAt([-0, -0])
|
||||
|
||||
thing: "blah"`)
|
||||
|
||||
await expect(page.locator('.cm-lint-marker-error')).toBeVisible()
|
||||
})
|
||||
await expect(page.locator('.cm-lint-marker-error')).toBeVisible()
|
||||
}
|
||||
)
|
||||
|
||||
test('when engine fails export we handle the failure and alert the user', async ({
|
||||
page,
|
||||
@ -401,95 +405,97 @@ const sketch001 = startSketchAt([-0, -0])
|
||||
const successToastMessage = page.getByText(`Exported successfully`)
|
||||
await expect(successToastMessage).toBeVisible()
|
||||
})
|
||||
test('ensure you can not export while an export is already going', async ({
|
||||
page,
|
||||
}) => {
|
||||
// This is being weird on ubuntu and windows.
|
||||
test.skip(
|
||||
// eslint-disable-next-line jest/valid-title
|
||||
process.platform === 'linux' || process.platform === 'win32',
|
||||
'This test is being weird on ubuntu'
|
||||
)
|
||||
|
||||
const u = await getUtils(page)
|
||||
await test.step('Set up the code and durations', async () => {
|
||||
await page.addInitScript(
|
||||
async ({ code }) => {
|
||||
localStorage.setItem('persistCode', code)
|
||||
;(window as any).playwrightSkipFilePicker = true
|
||||
},
|
||||
{
|
||||
code: bracket,
|
||||
}
|
||||
test(
|
||||
'ensure you can not export while an export is already going',
|
||||
{ tag: ['@skipLinux', '@skipWin'] },
|
||||
async ({ page }) => {
|
||||
// This is being weird on ubuntu and windows.
|
||||
test.skip(
|
||||
// eslint-disable-next-line jest/valid-title
|
||||
process.platform === 'linux' || process.platform === 'win32',
|
||||
'This test is being weird on ubuntu'
|
||||
)
|
||||
|
||||
await page.setViewportSize({ width: 1000, height: 500 })
|
||||
const u = await getUtils(page)
|
||||
await test.step('Set up the code and durations', async () => {
|
||||
await page.addInitScript(
|
||||
async ({ code }) => {
|
||||
localStorage.setItem('persistCode', code)
|
||||
;(window as any).playwrightSkipFilePicker = true
|
||||
},
|
||||
{
|
||||
code: bracket,
|
||||
}
|
||||
)
|
||||
|
||||
await u.waitForAuthSkipAppStart()
|
||||
await page.setViewportSize({ width: 1000, height: 500 })
|
||||
|
||||
// wait for execution done
|
||||
await u.openDebugPanel()
|
||||
await u.expectCmdLog('[data-message-type="execution-done"]')
|
||||
await u.closeDebugPanel()
|
||||
await u.waitForAuthSkipAppStart()
|
||||
|
||||
// expect zero errors in guter
|
||||
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
|
||||
})
|
||||
// wait for execution done
|
||||
await u.openDebugPanel()
|
||||
await u.expectCmdLog('[data-message-type="execution-done"]')
|
||||
await u.closeDebugPanel()
|
||||
|
||||
const errorToastMessage = page.getByText(`Error while exporting`)
|
||||
const exportingToastMessage = page.getByText(`Exporting...`)
|
||||
const engineErrorToastMessage = page.getByText(`Nothing to export`)
|
||||
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
|
||||
const successToastMessage = page.getByText(`Exported successfully`)
|
||||
// expect zero errors in guter
|
||||
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
|
||||
})
|
||||
|
||||
await test.step('Blocked second export', async () => {
|
||||
await clickExportButton(page)
|
||||
const errorToastMessage = page.getByText(`Error while exporting`)
|
||||
const exportingToastMessage = page.getByText(`Exporting...`)
|
||||
const engineErrorToastMessage = page.getByText(`Nothing to export`)
|
||||
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
|
||||
const successToastMessage = page.getByText(`Exported successfully`)
|
||||
|
||||
await expect(exportingToastMessage).toBeVisible()
|
||||
await test.step('Blocked second export', async () => {
|
||||
await clickExportButton(page)
|
||||
|
||||
await clickExportButton(page)
|
||||
await expect(exportingToastMessage).toBeVisible()
|
||||
|
||||
await clickExportButton(page)
|
||||
|
||||
await test.step('The second export is blocked', async () => {
|
||||
// Find the toast.
|
||||
// Look out for the toast message
|
||||
await Promise.all([
|
||||
expect(exportingToastMessage.first()).toBeVisible(),
|
||||
expect(alreadyExportingToastMessage).toBeVisible(),
|
||||
])
|
||||
})
|
||||
|
||||
await test.step('The first export still succeeds', async () => {
|
||||
await Promise.all([
|
||||
expect(exportingToastMessage).not.toBeVisible({ timeout: 15_000 }),
|
||||
expect(errorToastMessage).not.toBeVisible(),
|
||||
expect(engineErrorToastMessage).not.toBeVisible(),
|
||||
expect(successToastMessage).toBeVisible({ timeout: 15_000 }),
|
||||
expect(alreadyExportingToastMessage).not.toBeVisible({
|
||||
timeout: 15_000,
|
||||
}),
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
await test.step('Successful, unblocked export', async () => {
|
||||
// Try exporting again.
|
||||
await clickExportButton(page)
|
||||
|
||||
await test.step('The second export is blocked', async () => {
|
||||
// Find the toast.
|
||||
// Look out for the toast message
|
||||
await Promise.all([
|
||||
expect(exportingToastMessage.first()).toBeVisible(),
|
||||
expect(alreadyExportingToastMessage).toBeVisible(),
|
||||
])
|
||||
})
|
||||
await expect(exportingToastMessage).toBeVisible()
|
||||
|
||||
await test.step('The first export still succeeds', async () => {
|
||||
// Expect it to succeed.
|
||||
await Promise.all([
|
||||
expect(exportingToastMessage).not.toBeVisible({ timeout: 15_000 }),
|
||||
expect(exportingToastMessage).not.toBeVisible(),
|
||||
expect(errorToastMessage).not.toBeVisible(),
|
||||
expect(engineErrorToastMessage).not.toBeVisible(),
|
||||
expect(successToastMessage).toBeVisible({ timeout: 15_000 }),
|
||||
expect(alreadyExportingToastMessage).not.toBeVisible({
|
||||
timeout: 15_000,
|
||||
}),
|
||||
expect(alreadyExportingToastMessage).not.toBeVisible(),
|
||||
])
|
||||
|
||||
await expect(successToastMessage).toBeVisible()
|
||||
})
|
||||
})
|
||||
|
||||
await test.step('Successful, unblocked export', async () => {
|
||||
// Try exporting again.
|
||||
await clickExportButton(page)
|
||||
|
||||
// Find the toast.
|
||||
// Look out for the toast message
|
||||
await expect(exportingToastMessage).toBeVisible()
|
||||
|
||||
// Expect it to succeed.
|
||||
await Promise.all([
|
||||
expect(exportingToastMessage).not.toBeVisible(),
|
||||
expect(errorToastMessage).not.toBeVisible(),
|
||||
expect(engineErrorToastMessage).not.toBeVisible(),
|
||||
expect(alreadyExportingToastMessage).not.toBeVisible(),
|
||||
])
|
||||
|
||||
await expect(successToastMessage).toBeVisible()
|
||||
})
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
test(
|
||||
`Network health indicator only appears in modeling view`,
|
||||
|
@ -49,7 +49,7 @@ test.setTimeout(60_000)
|
||||
|
||||
test(
|
||||
'exports of each format should work',
|
||||
{ tag: '@snapshot' },
|
||||
{ tag: ['@snapshot', '@skipWin', '@skipMacos'] },
|
||||
async ({ page, context }) => {
|
||||
// skip on macos and windows.
|
||||
test.skip(
|
||||
|
@ -15,234 +15,240 @@ test.afterEach(async ({ page }, testInfo) => {
|
||||
|
||||
test.describe('Testing selections', () => {
|
||||
test.setTimeout(90_000)
|
||||
test('Selections work on fresh and edited sketch', async ({ page }) => {
|
||||
// Skip on windows its being weird.
|
||||
test.skip(process.platform === 'win32', 'Skip on windows')
|
||||
test(
|
||||
'Selections work on fresh and edited sketch',
|
||||
{ tag: ['@skipWin'] },
|
||||
async ({ page }) => {
|
||||
// Skip on windows its being weird.
|
||||
test.skip(process.platform === 'win32', 'Skip on windows')
|
||||
|
||||
// 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 })
|
||||
// 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 })
|
||||
|
||||
await u.waitForAuthSkipAppStart()
|
||||
await u.openDebugPanel()
|
||||
await u.waitForAuthSkipAppStart()
|
||||
await u.openDebugPanel()
|
||||
|
||||
const xAxisClick = () =>
|
||||
page.mouse.click(700, 253).then(() => page.waitForTimeout(100))
|
||||
const xAxisClickAfterExitingSketch = () =>
|
||||
page.mouse.click(639, 278).then(() => page.waitForTimeout(100))
|
||||
const emptySpaceHover = () =>
|
||||
test.step('Hover over empty space', async () => {
|
||||
await page.mouse.move(700, 143, { steps: 5 })
|
||||
await expect(page.locator('.hover-highlight')).not.toBeVisible()
|
||||
})
|
||||
const emptySpaceClick = () =>
|
||||
test.step(`Click in empty space`, async () => {
|
||||
await page.mouse.click(700, 143)
|
||||
await expect(page.locator('.cm-line').last()).toHaveClass(
|
||||
/cm-activeLine/
|
||||
)
|
||||
})
|
||||
const topHorzSegmentClick = () =>
|
||||
page.mouse
|
||||
.click(startXPx, 500 - PUR * 20)
|
||||
.then(() => page.waitForTimeout(100))
|
||||
const bottomHorzSegmentClick = () =>
|
||||
page.mouse
|
||||
.click(startXPx + PUR * 10, 500 - PUR * 10)
|
||||
.then(() => page.waitForTimeout(100))
|
||||
const xAxisClick = () =>
|
||||
page.mouse.click(700, 253).then(() => page.waitForTimeout(100))
|
||||
const xAxisClickAfterExitingSketch = () =>
|
||||
page.mouse.click(639, 278).then(() => page.waitForTimeout(100))
|
||||
const emptySpaceHover = () =>
|
||||
test.step('Hover over empty space', async () => {
|
||||
await page.mouse.move(700, 143, { steps: 5 })
|
||||
await expect(page.locator('.hover-highlight')).not.toBeVisible()
|
||||
})
|
||||
const emptySpaceClick = () =>
|
||||
test.step(`Click in empty space`, async () => {
|
||||
await page.mouse.click(700, 143)
|
||||
await expect(page.locator('.cm-line').last()).toHaveClass(
|
||||
/cm-activeLine/
|
||||
)
|
||||
})
|
||||
const topHorzSegmentClick = () =>
|
||||
page.mouse
|
||||
.click(startXPx, 500 - PUR * 20)
|
||||
.then(() => page.waitForTimeout(100))
|
||||
const bottomHorzSegmentClick = () =>
|
||||
page.mouse
|
||||
.click(startXPx + PUR * 10, 500 - PUR * 10)
|
||||
.then(() => page.waitForTimeout(100))
|
||||
|
||||
await u.clearCommandLogs()
|
||||
await expect(
|
||||
page.getByRole('button', { name: 'Start Sketch' })
|
||||
).not.toBeDisabled()
|
||||
await page.getByRole('button', { name: 'Start Sketch' }).click()
|
||||
await u.clearCommandLogs()
|
||||
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
|
||||
// select a plane
|
||||
await page.mouse.click(700, 200)
|
||||
await page.waitForTimeout(700) // wait for animation
|
||||
|
||||
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')
|
||||
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}, %)`)
|
||||
|
||||
await page.waitForTimeout(100)
|
||||
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10)
|
||||
await page.waitForTimeout(100)
|
||||
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10)
|
||||
|
||||
await expect(page.locator('.cm-content'))
|
||||
.toHaveText(`const sketch001 = startSketchOn('XZ')
|
||||
await expect(page.locator('.cm-content'))
|
||||
.toHaveText(`const sketch001 = startSketchOn('XZ')
|
||||
|> startProfileAt(${commonPoints.startAt}, %)
|
||||
|> line([${commonPoints.num1}, 0], %)`)
|
||||
|
||||
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')
|
||||
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], %)
|
||||
|> line([0, ${commonPoints.num1 + 0.01}], %)`)
|
||||
await page.waitForTimeout(100)
|
||||
await page.mouse.click(startXPx, 500 - PUR * 20)
|
||||
await expect(page.locator('.cm-content'))
|
||||
.toHaveText(`const sketch001 = startSketchOn('XZ')
|
||||
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([0, ${commonPoints.num1 + 0.01}], %)
|
||||
|> line([-${commonPoints.num2}, 0], %)`)
|
||||
|
||||
// deselect line tool
|
||||
await page.getByRole('button', { name: 'line Line', exact: true }).click()
|
||||
// deselect line tool
|
||||
await page.getByRole('button', { name: 'line Line', exact: true }).click()
|
||||
|
||||
await u.closeDebugPanel()
|
||||
const selectionSequence = async () => {
|
||||
await expect(page.getByTestId('hover-highlight')).not.toBeVisible()
|
||||
await u.closeDebugPanel()
|
||||
const selectionSequence = async () => {
|
||||
await expect(page.getByTestId('hover-highlight')).not.toBeVisible()
|
||||
|
||||
await page.waitForTimeout(100)
|
||||
await page.mouse.move(startXPx + PUR * 15, 500 - PUR * 10)
|
||||
await page.waitForTimeout(100)
|
||||
await page.mouse.move(startXPx + PUR * 15, 500 - PUR * 10)
|
||||
|
||||
await expect(page.getByTestId('hover-highlight').first()).toBeVisible()
|
||||
// bg-yellow-300/70 is more brittle than hover-highlight, but is closer to the user experience
|
||||
// and will be an easy fix if it breaks because we change the colour
|
||||
await expect(page.locator('.bg-yellow-300\\/70')).toBeVisible()
|
||||
// check mousing off, than mousing onto another line
|
||||
await page.mouse.move(startXPx + PUR * 10, 500 - PUR * 15) // mouse off
|
||||
await expect(page.getByTestId('hover-highlight')).not.toBeVisible()
|
||||
await page.mouse.move(startXPx + PUR * 10, 500 - PUR * 20) // mouse onto another line
|
||||
await expect(page.getByTestId('hover-highlight').first()).toBeVisible()
|
||||
await expect(page.getByTestId('hover-highlight').first()).toBeVisible()
|
||||
// bg-yellow-300/70 is more brittle than hover-highlight, but is closer to the user experience
|
||||
// and will be an easy fix if it breaks because we change the colour
|
||||
await expect(page.locator('.bg-yellow-300\\/70')).toBeVisible()
|
||||
// check mousing off, than mousing onto another line
|
||||
await page.mouse.move(startXPx + PUR * 10, 500 - PUR * 15) // mouse off
|
||||
await expect(page.getByTestId('hover-highlight')).not.toBeVisible()
|
||||
await page.mouse.move(startXPx + PUR * 10, 500 - PUR * 20) // mouse onto another line
|
||||
await expect(page.getByTestId('hover-highlight').first()).toBeVisible()
|
||||
|
||||
// now check clicking works including axis
|
||||
// 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')
|
||||
const constrainButton = page.getByRole('button', {
|
||||
name: 'Length: open menu',
|
||||
// click a segment hold shift and click an axis, see that a relevant constraint is enabled
|
||||
await topHorzSegmentClick()
|
||||
await page.keyboard.down('Shift')
|
||||
const constrainButton = page.getByRole('button', {
|
||||
name: 'Length: open menu',
|
||||
})
|
||||
const absYButton = page.getByRole('button', { name: 'Absolute 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()
|
||||
|
||||
// clear selection by clicking on nothing
|
||||
await emptySpaceClick()
|
||||
|
||||
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)
|
||||
|
||||
await page.keyboard.up('Shift')
|
||||
await constrainButton.click()
|
||||
await expect(absYButton).not.toBeDisabled()
|
||||
|
||||
// clear selection by clicking on nothing
|
||||
await emptySpaceClick()
|
||||
|
||||
// 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()
|
||||
|
||||
// clear selection by clicking on nothing
|
||||
await emptySpaceClick()
|
||||
|
||||
// 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()
|
||||
|
||||
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 test.step(`Test hovering and selecting on fresh sketch`, async () => {
|
||||
await selectionSequence()
|
||||
})
|
||||
const absYButton = page.getByRole('button', { name: 'Absolute 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()
|
||||
|
||||
// clear selection by clicking on nothing
|
||||
await emptySpaceClick()
|
||||
// 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 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 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()
|
||||
await xAxisClickAfterExitingSketch()
|
||||
await page.waitForTimeout(100)
|
||||
await emptySpaceHover()
|
||||
|
||||
await page.keyboard.up('Shift')
|
||||
await constrainButton.click()
|
||||
await expect(absYButton).not.toBeDisabled()
|
||||
|
||||
// clear selection by clicking on nothing
|
||||
await emptySpaceClick()
|
||||
|
||||
// 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()
|
||||
|
||||
// clear selection by clicking on nothing
|
||||
await emptySpaceClick()
|
||||
|
||||
// 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()
|
||||
|
||||
await expect(page.locator('.cm-cursor')).toHaveCount(1)
|
||||
|
||||
await page.keyboard.down(
|
||||
process.platform === 'linux' ? 'Control' : 'Meta'
|
||||
// enter sketch again
|
||||
await u.doAndWaitForCmd(
|
||||
() => page.getByRole('button', { name: 'Edit Sketch' }).click(),
|
||||
'default_camera_get_settings'
|
||||
)
|
||||
|
||||
await page.waitForTimeout(450) // wait for animation
|
||||
|
||||
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 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 u.closeDebugPanel()
|
||||
|
||||
await test.step(`Test hovering and selecting on edited sketch`, async () => {
|
||||
await selectionSequence()
|
||||
})
|
||||
}
|
||||
|
||||
await test.step(`Test hovering and selecting on fresh sketch`, async () => {
|
||||
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()
|
||||
await xAxisClickAfterExitingSketch()
|
||||
await page.waitForTimeout(100)
|
||||
await emptySpaceHover()
|
||||
|
||||
// enter sketch again
|
||||
await u.doAndWaitForCmd(
|
||||
() => page.getByRole('button', { name: 'Edit Sketch' }).click(),
|
||||
'default_camera_get_settings'
|
||||
)
|
||||
|
||||
await page.waitForTimeout(450) // wait for animation
|
||||
|
||||
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()
|
||||
|
||||
await test.step(`Test hovering and selecting on edited sketch`, async () => {
|
||||
await selectionSequence()
|
||||
})
|
||||
})
|
||||
)
|
||||
|
||||
test('Solids should be select and deletable', async ({ page }) => {
|
||||
test.setTimeout(90_000)
|
||||
|
@ -258,7 +258,7 @@ test.describe('Testing settings', () => {
|
||||
|
||||
test(
|
||||
`Project settings override user settings on desktop`,
|
||||
{ tag: '@electron' },
|
||||
{ tag: ['@electron', '@skipWin'] },
|
||||
async ({ browser: _ }, testInfo) => {
|
||||
test.skip(
|
||||
process.platform === 'win32',
|
||||
|
@ -447,125 +447,127 @@ test.describe('Text-to-CAD tests', () => {
|
||||
await expect(page.getByText(promptWithNewline)).toBeVisible()
|
||||
})
|
||||
|
||||
test('can do many at once and get many prompts back, and interact with many', async ({
|
||||
page,
|
||||
}) => {
|
||||
// Let this test run longer since we've seen it timeout.
|
||||
test.setTimeout(180_000)
|
||||
// skip on windows
|
||||
test.skip(
|
||||
process.platform === 'win32',
|
||||
'This test is flaky, skipping for now'
|
||||
)
|
||||
test(
|
||||
'can do many at once and get many prompts back, and interact with many',
|
||||
{ tag: ['@skipWin'] },
|
||||
async ({ page }) => {
|
||||
// Let this test run longer since we've seen it timeout.
|
||||
test.setTimeout(180_000)
|
||||
// skip on windows
|
||||
test.skip(
|
||||
process.platform === 'win32',
|
||||
'This test is flaky, skipping for now'
|
||||
)
|
||||
|
||||
const u = await getUtils(page)
|
||||
const u = await getUtils(page)
|
||||
|
||||
await page.setViewportSize({ width: 1000, height: 500 })
|
||||
await page.setViewportSize({ width: 1000, height: 500 })
|
||||
|
||||
await u.waitForAuthSkipAppStart()
|
||||
await u.waitForAuthSkipAppStart()
|
||||
|
||||
await sendPromptFromCommandBar(page, 'a 2x4 lego')
|
||||
await sendPromptFromCommandBar(page, 'a 2x4 lego')
|
||||
|
||||
await sendPromptFromCommandBar(page, 'a 2x8 lego')
|
||||
await sendPromptFromCommandBar(page, 'a 2x8 lego')
|
||||
|
||||
await sendPromptFromCommandBar(page, 'a 2x10 lego')
|
||||
await sendPromptFromCommandBar(page, 'a 2x10 lego')
|
||||
|
||||
// Find the toast.
|
||||
// Look out for the toast message
|
||||
const submittingToastMessage = page.getByText(
|
||||
`Submitting to Text-to-CAD API...`
|
||||
)
|
||||
await expect(submittingToastMessage.first()).toBeVisible()
|
||||
// Find the toast.
|
||||
// Look out for the toast message
|
||||
const submittingToastMessage = page.getByText(
|
||||
`Submitting to Text-to-CAD API...`
|
||||
)
|
||||
await expect(submittingToastMessage.first()).toBeVisible()
|
||||
|
||||
const generatingToastMessage = page.getByText(
|
||||
`Generating parametric model...`
|
||||
)
|
||||
await expect(generatingToastMessage.first()).toBeVisible({
|
||||
timeout: 10_000,
|
||||
})
|
||||
const generatingToastMessage = page.getByText(
|
||||
`Generating parametric model...`
|
||||
)
|
||||
await expect(generatingToastMessage.first()).toBeVisible({
|
||||
timeout: 10_000,
|
||||
})
|
||||
|
||||
const successToastMessage = page.getByText(`Text-to-CAD successful`)
|
||||
// We should have three success toasts.
|
||||
await expect(successToastMessage).toHaveCount(3, { timeout: 25_000 })
|
||||
const successToastMessage = page.getByText(`Text-to-CAD successful`)
|
||||
// We should have three success toasts.
|
||||
await expect(successToastMessage).toHaveCount(3, { timeout: 25_000 })
|
||||
|
||||
await expect(page.getByText('Copied')).not.toBeVisible()
|
||||
await expect(page.getByText('Copied')).not.toBeVisible()
|
||||
|
||||
await expect(page.getByText(`a 2x4 lego`)).toBeVisible()
|
||||
await expect(page.getByText(`a 2x8 lego`)).toBeVisible()
|
||||
await expect(page.getByText(`a 2x10 lego`)).toBeVisible()
|
||||
await expect(page.getByText(`a 2x4 lego`)).toBeVisible()
|
||||
await expect(page.getByText(`a 2x8 lego`)).toBeVisible()
|
||||
await expect(page.getByText(`a 2x10 lego`)).toBeVisible()
|
||||
|
||||
// Ensure if you reject one, the others stay.
|
||||
const rejectButton = page.getByRole('button', { name: 'Reject' })
|
||||
await expect(rejectButton.first()).toBeVisible()
|
||||
// Click the reject button on the first toast.
|
||||
await rejectButton.first().click()
|
||||
// Ensure if you reject one, the others stay.
|
||||
const rejectButton = page.getByRole('button', { name: 'Reject' })
|
||||
await expect(rejectButton.first()).toBeVisible()
|
||||
// Click the reject button on the first toast.
|
||||
await rejectButton.first().click()
|
||||
|
||||
// The first toast should disappear, but not the others.
|
||||
await expect(page.getByText(`a 2x10 lego`)).not.toBeVisible()
|
||||
await expect(page.getByText(`a 2x8 lego`)).toBeVisible()
|
||||
await expect(page.getByText(`a 2x4 lego`)).toBeVisible()
|
||||
// The first toast should disappear, but not the others.
|
||||
await expect(page.getByText(`a 2x10 lego`)).not.toBeVisible()
|
||||
await expect(page.getByText(`a 2x8 lego`)).toBeVisible()
|
||||
await expect(page.getByText(`a 2x4 lego`)).toBeVisible()
|
||||
|
||||
// Ensure you can copy the code for one of the models remaining.
|
||||
const copyToClipboardButton = page.getByRole('button', {
|
||||
name: 'Copy to clipboard',
|
||||
})
|
||||
await expect(copyToClipboardButton.first()).toBeVisible()
|
||||
// Click the button.
|
||||
await copyToClipboardButton.first().click()
|
||||
// Ensure you can copy the code for one of the models remaining.
|
||||
const copyToClipboardButton = page.getByRole('button', {
|
||||
name: 'Copy to clipboard',
|
||||
})
|
||||
await expect(copyToClipboardButton.first()).toBeVisible()
|
||||
// Click the button.
|
||||
await copyToClipboardButton.first().click()
|
||||
|
||||
// Expect the code to be copied.
|
||||
await expect(page.getByText('Copied')).toBeVisible()
|
||||
// Expect the code to be copied.
|
||||
await expect(page.getByText('Copied')).toBeVisible()
|
||||
|
||||
// Click in the code editor.
|
||||
await page.locator('.cm-content').click({ position: { x: 10, y: 10 } })
|
||||
// Click in the code editor.
|
||||
await page.locator('.cm-content').click({ position: { x: 10, y: 10 } })
|
||||
|
||||
// Paste the code.
|
||||
await page.keyboard.down('ControlOrMeta')
|
||||
await page.keyboard.press('KeyV')
|
||||
await page.keyboard.up('ControlOrMeta')
|
||||
// Paste the code.
|
||||
await page.keyboard.down('ControlOrMeta')
|
||||
await page.keyboard.press('KeyV')
|
||||
await page.keyboard.up('ControlOrMeta')
|
||||
|
||||
// Expect the code to be pasted.
|
||||
await expect(page.locator('.cm-content')).toContainText(`2x8`)
|
||||
// Expect the code to be pasted.
|
||||
await expect(page.locator('.cm-content')).toContainText(`2x8`)
|
||||
|
||||
// Find the toast close button.
|
||||
const closeButton = page.locator('[data-negative-button="close"]').first()
|
||||
await expect(closeButton).toBeVisible()
|
||||
await closeButton.click()
|
||||
// Find the toast close button.
|
||||
const closeButton = page.locator('[data-negative-button="close"]').first()
|
||||
await expect(closeButton).toBeVisible()
|
||||
await closeButton.click()
|
||||
|
||||
// Ensure the final toast remains.
|
||||
await expect(page.getByText(`a 2x10 lego`)).not.toBeVisible()
|
||||
await expect(page.getByText(`Prompt: "a 2x8 lego`)).not.toBeVisible()
|
||||
await expect(page.getByText(`a 2x4 lego`)).toBeVisible()
|
||||
// Ensure the final toast remains.
|
||||
await expect(page.getByText(`a 2x10 lego`)).not.toBeVisible()
|
||||
await expect(page.getByText(`Prompt: "a 2x8 lego`)).not.toBeVisible()
|
||||
await expect(page.getByText(`a 2x4 lego`)).toBeVisible()
|
||||
|
||||
// Ensure you can copy the code for the final model.
|
||||
await expect(copyToClipboardButton).toBeVisible()
|
||||
// Click the button.
|
||||
await copyToClipboardButton.click()
|
||||
// Ensure you can copy the code for the final model.
|
||||
await expect(copyToClipboardButton).toBeVisible()
|
||||
// Click the button.
|
||||
await copyToClipboardButton.click()
|
||||
|
||||
// Expect the code to be copied.
|
||||
await expect(page.getByText('Copied')).toBeVisible()
|
||||
// Expect the code to be copied.
|
||||
await expect(page.getByText('Copied')).toBeVisible()
|
||||
|
||||
// Click in the code editor.
|
||||
await page.locator('.cm-content').click({ position: { x: 10, y: 10 } })
|
||||
// Click in the code editor.
|
||||
await page.locator('.cm-content').click({ position: { x: 10, y: 10 } })
|
||||
|
||||
// Paste the code.
|
||||
await page.keyboard.down('ControlOrMeta')
|
||||
await page.keyboard.press('KeyA')
|
||||
await page.keyboard.up('ControlOrMeta')
|
||||
await page.keyboard.press('Backspace')
|
||||
await page.keyboard.down('ControlOrMeta')
|
||||
await page.keyboard.press('KeyV')
|
||||
await page.keyboard.up('ControlOrMeta')
|
||||
// Paste the code.
|
||||
await page.keyboard.down('ControlOrMeta')
|
||||
await page.keyboard.press('KeyA')
|
||||
await page.keyboard.up('ControlOrMeta')
|
||||
await page.keyboard.press('Backspace')
|
||||
await page.keyboard.down('ControlOrMeta')
|
||||
await page.keyboard.press('KeyV')
|
||||
await page.keyboard.up('ControlOrMeta')
|
||||
|
||||
// Expect the code to be pasted.
|
||||
await expect(page.locator('.cm-content')).toContainText(`2x4`)
|
||||
// Expect the code to be pasted.
|
||||
await expect(page.locator('.cm-content')).toContainText(`2x4`)
|
||||
|
||||
// Expect the toast to disappear.
|
||||
// Find the toast close button.
|
||||
await expect(closeButton).toBeVisible()
|
||||
await closeButton.click()
|
||||
await expect(successToastMessage).not.toBeVisible()
|
||||
})
|
||||
// Expect the toast to disappear.
|
||||
// Find the toast close button.
|
||||
await expect(closeButton).toBeVisible()
|
||||
await closeButton.click()
|
||||
await expect(successToastMessage).not.toBeVisible()
|
||||
}
|
||||
)
|
||||
|
||||
test('can do many at once with errors, clicking dismiss error does not dismiss all', async ({
|
||||
page,
|
||||
|
25
package.json
25
package.json
@ -75,11 +75,10 @@
|
||||
"build:both": "vite build",
|
||||
"build:both:local": "yarn build:wasm && vite build",
|
||||
"pretest": "yarn remove-importmeta",
|
||||
"test": "vitest --mode development",
|
||||
"test:nowatch": "vitest run --mode development",
|
||||
"test:rust": "(cd src/wasm-lib && cargo test --all && cargo clippy --all --tests --benches)",
|
||||
"simpleserver": "yarn pretest && http-server ./public --cors -p 3000",
|
||||
"simpleserver:ci": "yarn pretest && http-server ./public --cors -p 3000 &",
|
||||
"simpleserver:bg": "yarn pretest && http-server ./public --cors -p 3000 &",
|
||||
"fmt": "prettier --write ./src *.ts *.json *.js ./e2e ./packages",
|
||||
"fmt-check": "prettier --check ./src *.ts *.json *.js ./e2e ./packages",
|
||||
"fetch:wasm": "./get-latest-wasm-bundle.sh",
|
||||
@ -89,7 +88,8 @@
|
||||
"build:wasm": "yarn wasm-prep && cd src/wasm-lib && wasm-pack build --release --target web --out-dir pkg && cargo test -p kcl-lib export_bindings && cd ../.. && yarn isomorphic-copy-wasm && yarn fmt",
|
||||
"remove-importmeta": "sed -i 's/import.meta.url/window.location.origin/g' \"./src/wasm-lib/pkg/wasm_lib.js\"; sed -i '' 's/import.meta.url/window.location.origin/g' \"./src/wasm-lib/pkg/wasm_lib.js\" || echo \"sed for both mac and linux\"",
|
||||
"wasm-prep": "rimraf src/wasm-lib/pkg && mkdirp src/wasm-lib/pkg && rimraf src/wasm-lib/kcl/bindings",
|
||||
"lint": "eslint --fix src e2e packages/codemirror-lsp-client",
|
||||
"lint-fix": "eslint --fix src e2e packages/codemirror-lsp-client",
|
||||
"lint": "eslint --max-warnings 0 src e2e packages/codemirror-lsp-client",
|
||||
"bump-jsons": "echo \"$(jq --arg v \"$VERSION\" '.version=$v' package.json --indent 2)\" > package.json",
|
||||
"postinstall": "yarn fetch:samples && yarn xstate:typegen && ./node_modules/.bin/electron-rebuild",
|
||||
"xstate:typegen": "yarn xstate typegen \"src/**/*.ts?(x)\"",
|
||||
@ -101,7 +101,23 @@
|
||||
"tron:publish": "electron-forge publish",
|
||||
"tron:test": "NODE_ENV=development yarn playwright test --config=playwright.electron.config.ts --grep=@electron",
|
||||
"tronb:vite": "vite build -c vite.main.config.ts && vite build -c vite.preload.config.ts && vite build -c vite.renderer.config.ts",
|
||||
"tronb:package": "electron-builder --config electron-builder.yml"
|
||||
"tronb:package": "electron-builder --config electron-builder.yml",
|
||||
"test-setup": "yarn install && yarn build:wasm",
|
||||
"test": "vitest --mode development",
|
||||
"test:nowatch": "vitest run --mode development",
|
||||
"test:unit": "vitest run --mode development",
|
||||
"test:playwright:browser:chrome": "playwright test '--project=Google Chrome' --config=playwright.ci.config.ts '--grep-invert=@snapshot|@electron'",
|
||||
"test:playwright:browser:chrome:windows": "playwright test '--project=Google Chrome' --config=playwright.ci.config.ts '--grep-invert=@snapshot|@electron|@skipWin'",
|
||||
"test:playwright:browser:chrome:ubuntu": "playwright test '--project=Google Chrome' --config=playwright.ci.config.ts '--grep-invert=@snapshot|@electron|@skipLinux'",
|
||||
"test:playwright:electron": "playwright test --config=playwright.electron.config.ts --grep=@electron",
|
||||
"test:playwright:electron:windows": "playwright test --config=playwright.electron.config.ts --grep=@electron --grep-invert=@skipWin",
|
||||
"test:playwright:electron:macos": "playwright test --config=playwright.electron.config.ts --grep=@electron --grep-invert=@skipMacos",
|
||||
"test:playwright:electron:ubuntu": "playwright test --config=playwright.electron.config.ts --grep=@electron --grep-invert=@skipLinux",
|
||||
"test:playwright:electron:local": "yarn tron:package && NODE_ENV=development playwright test --config=playwright.electron.config.ts --grep=@electron",
|
||||
"test:playwright:electron:windows:local": "yarn tron:package && NODE_ENV=development playwright test --config=playwright.electron.config.ts --grep=@electron --grep-invert=@skipWin",
|
||||
"test:playwright:electron:macos:local": "yarn tron:package && NODE_ENV=development playwright test --config=playwright.electron.config.ts --grep=@electron --grep-invert=@skipMacos",
|
||||
"test:playwright:electron:ubuntu:local": "yarn tron:package && NODE_ENV=development playwright test --config=playwright.electron.config.ts --grep=@electron --grep-invert=@skipLinux",
|
||||
"test:unit:local": "yarn simpleserver:bg && yarn test:unit; kill-port 3000"
|
||||
},
|
||||
"prettier": {
|
||||
"trailingComma": "es5",
|
||||
@ -174,6 +190,7 @@
|
||||
"happy-dom": "^14.3.10",
|
||||
"http-server": "^14.1.1",
|
||||
"husky": "^9.1.5",
|
||||
"kill-port": "^2.0.1",
|
||||
"node-fetch": "^3.3.2",
|
||||
"pixelmatch": "^5.3.0",
|
||||
"pngjs": "^7.0.0",
|
||||
|
@ -14,7 +14,7 @@ import {
|
||||
} from './artifactGraph'
|
||||
import { err } from 'lib/trap'
|
||||
import { engineCommandManager, kclManager } from 'lib/singletons'
|
||||
import { CI, VITE_KC_DEV_TOKEN } from 'env'
|
||||
import { VITE_KC_DEV_TOKEN } from 'env'
|
||||
import fsp from 'fs/promises'
|
||||
import fs from 'fs'
|
||||
import { chromium } from 'playwright'
|
||||
@ -97,21 +97,6 @@ type CacheShape = {
|
||||
beforeAll(async () => {
|
||||
await initPromise
|
||||
|
||||
let parsed
|
||||
try {
|
||||
const file = await fsp.readFile(fullPath, 'utf-8')
|
||||
parsed = JSON.parse(file)
|
||||
} catch (e) {
|
||||
parsed = false
|
||||
}
|
||||
|
||||
if (!CI && parsed) {
|
||||
// caching the results of the websocket commands makes testing this locally much faster
|
||||
// real calls to the engine are needed to test the artifact map
|
||||
// bust the cache with: `rm -rf src/lang/std/artifactGraphCache`
|
||||
return
|
||||
}
|
||||
|
||||
// THESE TEST WILL FAIL without VITE_KC_DEV_TOKEN set in .env.development.local
|
||||
await new Promise((resolve) => {
|
||||
engineCommandManager.start({
|
||||
|
18
yarn.lock
18
yarn.lock
@ -5695,6 +5695,11 @@ get-symbol-description@^1.0.2:
|
||||
es-errors "^1.3.0"
|
||||
get-intrinsic "^1.2.4"
|
||||
|
||||
get-them-args@1.3.2:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/get-them-args/-/get-them-args-1.3.2.tgz#74a20ba8a4abece5ae199ad03f2bcc68fdfc9ba5"
|
||||
integrity sha512-LRn8Jlk+DwZE4GTlDbT3Hikd1wSHgLMme/+7ddlqKd7ldwR6LjJgTVWzBnR01wnYGe4KgrXjg287RaI22UHmAw==
|
||||
|
||||
glob-parent@^5.1.2, glob-parent@~5.1.2:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
|
||||
@ -6645,6 +6650,14 @@ keyv@^4.0.0, keyv@^4.5.3:
|
||||
dependencies:
|
||||
json-buffer "3.0.1"
|
||||
|
||||
kill-port@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/kill-port/-/kill-port-2.0.1.tgz#e5e18e2706b13d54320938be42cb7d40609b15cf"
|
||||
integrity sha512-e0SVOV5jFo0mx8r7bS29maVWp17qGqLBZ5ricNSajON6//kmb7qqqNnml4twNE8Dtj97UQD+gNFOaipS/q1zzQ==
|
||||
dependencies:
|
||||
get-them-args "1.3.2"
|
||||
shell-exec "1.0.2"
|
||||
|
||||
klaw@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/klaw/-/klaw-4.1.0.tgz#5df608067d8cb62bbfb24374f8e5d956323338f3"
|
||||
@ -8579,6 +8592,11 @@ shebang-regex@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
|
||||
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
|
||||
|
||||
shell-exec@1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/shell-exec/-/shell-exec-1.0.2.tgz#2e9361b0fde1d73f476c4b6671fa17785f696756"
|
||||
integrity sha512-jyVd+kU2X+mWKMmGhx4fpWbPsjvD53k9ivqetutVW/BQ+WIZoDoP4d8vUMGezV6saZsiNoW2f9GIhg9Dondohg==
|
||||
|
||||
side-channel@^1.0.4, side-channel@^1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2"
|
||||
|
Reference in New Issue
Block a user