Compare commits

..

55 Commits

Author SHA1 Message Date
2342d04fe2 Add back old window detection heuristic 2025-04-04 18:05:29 -04:00
ddac107dc1 Test attempt number 15345203, action! 2025-04-04 16:43:49 -04:00
313a21e82a Try again 2025-04-04 14:58:06 -04:00
b9875bb8cf Fix camera failure 2025-04-04 14:28:04 -04:00
8940f9b214 tsc lint 2025-04-04 14:24:27 -04:00
0af99af15e Fix native menu tests more 2025-04-04 13:51:44 -04:00
7f18aef49b Add app console.log 2025-04-04 12:43:04 -04:00
062495c02d Hopefully fix snapshots at least 2025-04-04 12:40:14 -04:00
767fde869c Use scene.connectionEstablished 2025-04-04 11:46:04 -04:00
49fcbdddba Try something 2025-04-04 11:39:22 -04:00
e06f76a6bb Qualify fail function 2025-04-04 11:38:05 -04:00
e98a957553 Remove a test race - poll window info. 2025-04-04 11:37:20 -04:00
25af691911 Fix cache count numbers in editor test 2025-04-04 11:37:20 -04:00
cdc0fa4ed9 Fix zoom to fit at the right moments... 2025-04-04 11:37:20 -04:00
4d06a917f2 Fix the bad reload repeat issue kevin started on 2025-04-04 11:37:19 -04:00
682fa50c1a Remove NetworkHealthIndicator test that was shit 2025-04-04 11:36:27 -04:00
496522e27d a new list of circular deps 2025-04-04 11:36:27 -04:00
4c57cea22d Fix zoom to fit being frigged 2025-04-04 11:36:27 -04:00
70f9c8edf1 fmt tsc 2025-04-04 11:36:27 -04:00
9de37879e5 fmt 2025-04-04 11:36:27 -04:00
91b5549a06 Fix another cyclic mfer! 2025-04-04 11:36:27 -04:00
3471f73479 Get rid of 1 cyclic dependency 2025-04-04 11:36:27 -04:00
277c489e38 Fix up new changes 2025-04-04 11:36:26 -04:00
00122aae5e yarn fmt lint tsc 2025-04-04 11:35:44 -04:00
65adfd4497 Fix up named-views tests 2025-04-04 11:34:59 -04:00
8d0343c946 Fix 2 more 2025-04-04 11:34:59 -04:00
4c564bf332 Fix more tests 2025-04-04 11:34:59 -04:00
ed1e2aedfd Fixup after rebase 2025-04-04 11:34:59 -04:00
992fec6afb wip 2025-04-04 11:34:58 -04:00
62a18dd2b3 less flaky point and click 2025-04-04 11:34:31 -04:00
2c673fba82 wip 2025-04-04 11:34:30 -04:00
635314bb8d Fix tsc after rebase 2025-04-04 11:33:39 -04:00
c75aafa60d yarn tsc 2025-04-04 11:33:39 -04:00
fb192ee213 yarn lint 2025-04-04 11:33:39 -04:00
9e19d131eb yarn fmt 2025-04-04 11:33:39 -04:00
81f70251e1 Fix the rest of the mfing tests 2025-04-04 11:33:39 -04:00
74f9afb2ca Deflake revolve some revolve tests 2025-04-04 11:33:39 -04:00
d03343d97d More e2e fixes 2025-04-04 11:33:39 -04:00
6c8a525762 Rework initial root projects dir + deflake many projects tests 2025-04-04 11:33:39 -04:00
c8177564e1 wip 2025-04-04 11:33:39 -04:00
12bf41ab7e Clear diagnostics when unmounting code editor! 2025-04-04 11:33:39 -04:00
fbefff490c Massive extinction event for waitForExecutionDone; try to stop projects view switching from crashing 2025-04-04 11:33:38 -04:00
4c9851efbf yarn fmt 2025-04-04 11:33:20 -04:00
2cca1376e2 Fix streamIdleMode checkbox being wonky 2025-04-04 11:33:20 -04:00
c32a3edb39 wip 2025-04-04 11:33:20 -04:00
955a2ffaf9 Add back better ping indicator 2025-04-04 11:33:20 -04:00
6bc8e45aa7 Use pause/play iconology 2025-04-04 11:33:20 -04:00
be0fdc53b5 Remove camera sync 2025-04-04 11:33:20 -04:00
cfbe805e14 Fix up everything after bumping kittycad/lib 2025-04-04 11:33:20 -04:00
2a60efc5ab Move engineStreamMachine as a global actor; tons of more work 2025-04-04 11:33:20 -04:00
deb83cf62c tsc lint fmt 2025-04-04 11:33:20 -04:00
e3705bf7df cargo fmt 2025-04-04 11:33:20 -04:00
ff887af540 Correct serialization; only expose at user level 2025-04-04 11:33:20 -04:00
1e4b6ce701 Shut up codespell 2025-04-04 11:33:20 -04:00
e642731529 Add back stream idle mode 2025-04-04 11:33:20 -04:00
451 changed files with 72945 additions and 87831 deletions

View File

@ -370,8 +370,8 @@ jobs:
with:
shell: bash
command: .github/ci-cd-scripts/playwright-electron.sh ${{matrix.shardIndex}} ${{matrix.shardTotal}} ${{ env.OS_NAME }}
timeout_minutes: 30
max_attempts: 9
timeout_minutes: 45
max_attempts: 15
env:
FAIL_ON_CONSOLE_ERRORS: true
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}

View File

@ -36,9 +36,9 @@ myAngle = -120
sketch001 = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> line(end = [8, 0])
|> angledLine(angle = abs(myAngle), length = 5)
|> angledLine({ angle = abs(myAngle), length = 5 }, %)
|> line(end = [-5, 0])
|> angledLine(angle = myAngle, length = 5)
|> angledLine({ angle = myAngle, length = 5 }, %)
|> close()
baseExtrusion = extrude(sketch001, length = 5)

View File

@ -33,7 +33,10 @@ acos(num: number): number
```js
sketch001 = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> angledLine(angle = toDegrees(acos(0.5)), length = 10)
|> angledLine({
angle = toDegrees(acos(0.5)),
length = 10
}, %)
|> line(end = [5, 0])
|> line(endAbsolute = [12, 0])
|> close()

View File

@ -36,7 +36,7 @@ angleToMatchLengthX(
sketch001 = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> line(end = [2, 5], tag = $seg01)
|> angledLine(angle = -angleToMatchLengthX(seg01, 7, %), endAbsoluteX = 10)
|> angledLineToX([-angleToMatchLengthX(seg01, 7, %), 10], %)
|> close()
extrusion = extrude(sketch001, length = 5)

View File

@ -36,7 +36,10 @@ angleToMatchLengthY(
sketch001 = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> line(end = [1, 2], tag = $seg01)
|> angledLine(angle = angleToMatchLengthY(seg01, 15, %), length = 5)
|> angledLine({
angle = angleToMatchLengthY(seg01, 15, %),
length = 5
}, %)
|> yLine(endAbsolute = 0)
|> close()

View File

@ -10,13 +10,8 @@ Draw a line segment relative to the current origin using the polar measure of so
```js
angledLine(
data: AngledLineData,
sketch: Sketch,
angle: number,
length?: number,
lengthX?: number,
lengthY?: number,
endAbsoluteX?: number,
endAbsoluteY?: number,
tag?: TagDeclarator,
): Sketch
```
@ -26,14 +21,9 @@ angledLine(
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | Which sketch should this path be added to? | Yes |
| `angle` | [`number`](/docs/kcl/types/number) | Which angle should the line be drawn at? | Yes |
| `length` | [`number`](/docs/kcl/types/number) | Draw the line this distance along the given angle. Only one of `length`, `lengthX`, `lengthY`, `lengthAbsoluteEndX`, `lengthAbsoluteEndY` can be given. | No |
| `lengthX` | [`number`](/docs/kcl/types/number) | Draw the line this distance along the X axis. Only one of `length`, `lengthX`, `lengthY`, `lengthAbsoluteEndX`, `lengthAbsoluteEndY` can be given. | No |
| `lengthY` | [`number`](/docs/kcl/types/number) | Draw the line this distance along the Y axis. Only one of `length`, `lengthX`, `lengthY`, `lengthAbsoluteEndX`, `lengthAbsoluteEndY` can be given. | No |
| `endAbsoluteX` | [`number`](/docs/kcl/types/number) | Draw the line along the given angle until it reaches this point along the X axis. Only one of `length`, `lengthX`, `lengthY`, `lengthAbsoluteEndX`, `lengthAbsoluteEndY` can be given. | No |
| `endAbsoluteY` | [`number`](/docs/kcl/types/number) | Draw the line along the given angle until it reaches this point along the Y axis. Only one of `length`, `lengthX`, `lengthY`, `lengthAbsoluteEndX`, `lengthAbsoluteEndY` can be given. | No |
| [`tag`](/docs/kcl/types/tag) | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | Create a new tag which refers to this line | No |
| `data` | [`AngledLineData`](/docs/kcl/types/AngledLineData) | Data to draw an angled line. | Yes |
| `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | | Yes |
| [`tag`](/docs/kcl/types/tag) | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | | No |
### Returns
@ -46,7 +36,7 @@ angledLine(
exampleSketch = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> yLine(endAbsolute = 15)
|> angledLine(angle = 30, length = 15)
|> angledLine({ angle = 30, length = 15 }, %)
|> line(end = [8, -10])
|> yLine(endAbsolute = 0)
|> close()

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

48
docs/kcl/angledLineToX.md Normal file

File diff suppressed because one or more lines are too long

48
docs/kcl/angledLineToY.md Normal file

File diff suppressed because one or more lines are too long

View File

@ -33,7 +33,10 @@ asin(num: number): number
```js
sketch001 = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> angledLine(angle = toDegrees(asin(0.5)), length = 20)
|> angledLine({
angle = toDegrees(asin(0.5)),
length = 20
}, %)
|> yLine(endAbsolute = 0)
|> close()

View File

@ -33,7 +33,10 @@ atan(num: number): number
```js
sketch001 = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> angledLine(angle = toDegrees(atan(1.25)), length = 20)
|> angledLine({
angle = toDegrees(atan(1.25)),
length = 20
}, %)
|> yLine(endAbsolute = 0)
|> close()

View File

@ -37,7 +37,10 @@ atan2(
```js
sketch001 = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> angledLine(angle = toDegrees(atan2(1.25, 2)), length = 20)
|> angledLine({
angle = toDegrees(atan2(1.25, 2)),
length = 20
}, %)
|> yLine(endAbsolute = 0)
|> close()

View File

@ -17,10 +17,10 @@ std::math::E: number = 2.71828182845904523536028747135266250_
```js
exampleSketch = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> angledLine(
|> angledLine({
angle = 30,
length = 2 * E ^ 2,
)
}, %)
|> yLine(endAbsolute = 0)
|> close()

View File

@ -17,10 +17,10 @@ std::math::TAU: number = 6.28318530717958647692528676655900577_
```js
exampleSketch = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> angledLine(
|> angledLine({
angle = 50,
length = 10 * TAU,
)
}, %)
|> yLine(endAbsolute = 0)
|> close()

View File

@ -30,7 +30,7 @@ e(): number
```js
exampleSketch = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> angledLine(angle = 30, length = 2 * e() ^ 2)
|> angledLine({ angle = 30, length = 2 * e() ^ 2 }, %)
|> yLine(endAbsolute = 0)
|> close()

View File

@ -43,7 +43,11 @@ layout: manual
* [`angleToMatchLengthX`](kcl/angleToMatchLengthX)
* [`angleToMatchLengthY`](kcl/angleToMatchLengthY)
* [`angledLine`](kcl/angledLine)
* [`angledLineOfXLength`](kcl/angledLineOfXLength)
* [`angledLineOfYLength`](kcl/angledLineOfYLength)
* [`angledLineThatIntersects`](kcl/angledLineThatIntersects)
* [`angledLineToX`](kcl/angledLineToX)
* [`angledLineToY`](kcl/angledLineToY)
* [`appearance`](kcl/appearance)
* [`arc`](kcl/arc)
* [`arcTo`](kcl/arcTo)

View File

@ -33,7 +33,10 @@ max(args: [number]): number
```js
exampleSketch = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> angledLine(angle = 70, length = max(15, 31, 4, 13, 22))
|> angledLine({
angle = 70,
length = max(15, 31, 4, 13, 22)
}, %)
|> line(end = [20, 0])
|> close()

View File

@ -33,7 +33,10 @@ min(args: [number]): number
```js
exampleSketch = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> angledLine(angle = 70, length = min(15, 31, 4, 13, 22))
|> angledLine({
angle = 70,
length = min(15, 31, 4, 13, 22)
}, %)
|> line(end = [20, 0])
|> close()

View File

@ -37,7 +37,7 @@ pow(
```js
exampleSketch = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> angledLine(angle = 50, length = pow(5, 2))
|> angledLine({ angle = 50, length = pow(5, 2) }, %)
|> yLine(endAbsolute = 0)
|> close()

View File

@ -29,8 +29,11 @@ profileStart(sketch: Sketch): [number]
```js
sketch001 = startSketchOn(XY)
|> startProfileAt([5, 2], %)
|> angledLine(angle = 120, length = 50, tag = $seg01)
|> angledLine(angle = segAng(seg01) + 120, length = 50)
|> angledLine({ angle = 120, length = 50 }, %, $seg01)
|> angledLine({
angle = segAng(seg01) + 120,
length = 50
}, %)
|> line(end = profileStart(%))
|> close()
|> extrude(length = 20)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -151,9 +151,15 @@ cube
sketch001 = startSketchOn(XY)
rectangleSketch = startProfileAt([-200, 23.86], sketch001)
|> angledLine(angle = 0, length = 73.47, tag = $rectangleSegmentA001)
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 50.61)
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001))
|> angledLine([0, 73.47], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001) - 90,
50.61
], %)
|> angledLine([
segAng(rectangleSegmentA001),
-segLen(rectangleSegmentA001)
], %)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()

View File

@ -85,9 +85,15 @@ cube
sketch001 = startSketchOn(XY)
rectangleSketch = startProfileAt([-200, 23.86], sketch001)
|> angledLine(angle = 0, length = 73.47, tag = $rectangleSegmentA001)
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 50.61)
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001))
|> angledLine([0, 73.47], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001) - 90,
50.61
], %)
|> angledLine([
segAng(rectangleSegmentA001),
-segLen(rectangleSegmentA001)
], %)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()

View File

@ -32,9 +32,9 @@ exampleSketch = startSketchOn(XZ)
|> line(end = [10, 0])
|> line(end = [5, 10], tag = $seg01)
|> line(end = [-10, 0])
|> angledLine(angle = segAng(seg01), length = 10)
|> angledLine([segAng(seg01), 10], %)
|> line(end = [-10, 0])
|> angledLine(angle = segAng(seg01), length = -15)
|> angledLine([segAng(seg01), -15], %)
|> close()
example = extrude(exampleSketch, length = 4)

View File

@ -29,9 +29,9 @@ segLen(tag: TagIdentifier): number
```js
exampleSketch = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> angledLine(angle = 60, length = 10, tag = $thing)
|> angledLine({ angle = 60, length = 10 }, %, $thing)
|> tangentialArc({ offset = -120, radius = 5 }, %)
|> angledLine(angle = -60, length = segLen(thing))
|> angledLine({ angle = -60, length = segLen(thing) }, %)
|> close()
example = extrude(exampleSketch, length = 5)

View File

@ -33,7 +33,7 @@ sqrt(num: number): number
```js
exampleSketch = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> angledLine(angle = 50, length = sqrt(2500))
|> angledLine({ angle = 50, length = sqrt(2500) }, %)
|> yLine(endAbsolute = 0)
|> close()

View File

@ -29,10 +29,10 @@ cos(@num: number(rad)): number(_)
```js
exampleSketch = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> angledLine(
|> angledLine({
angle = 30,
length = 3 / cos(toRadians(30)),
)
}, %)
|> yLine(endAbsolute = 0)
|> close()

View File

@ -29,10 +29,10 @@ sin(@num: number(rad)): number(_)
```js
exampleSketch = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> angledLine(
|> angledLine({
angle = 50,
length = 15 / sin(toDegrees(135)),
)
}, %)
|> yLine(endAbsolute = 0)
|> close()

View File

@ -29,10 +29,10 @@ tan(@num: number(rad)): number(_)
```js
exampleSketch = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> angledLine(
|> angledLine({
angle = 50,
length = 50 * tan(1/2),
)
}, %)
|> yLine(endAbsolute = 0)
|> close()

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -91,9 +91,15 @@ springSketch = startSketchOn(YZ)
sketch001 = startSketchOn(XY)
rectangleSketch = startProfileAt([-200, 23.86], sketch001)
|> angledLine(angle = 0, length = 73.47, tag = $rectangleSegmentA001)
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 50.61)
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001))
|> angledLine([0, 73.47], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001) - 90,
50.61
], %)
|> angledLine([
segAng(rectangleSegmentA001),
-segLen(rectangleSegmentA001)
], %)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()

View File

@ -32,7 +32,10 @@ pillSketch = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> line(end = [20, 0])
|> tangentialArcToRelative([0, 10], %, $arc1)
|> angledLine(angle = tangentToEnd(arc1), length = 20)
|> angledLine({
angle = tangentToEnd(arc1),
length = 20
}, %)
|> tangentialArcToRelative([0, -10], %)
|> close()
@ -47,7 +50,10 @@ pillSketch = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> line(end = [0, 20])
|> tangentialArcTo([10, 20], %, $arc1)
|> angledLine(angle = tangentToEnd(arc1), length = 20)
|> angledLine({
angle = tangentToEnd(arc1),
length = 20
}, %)
|> tangentialArcToRelative([-10, 0], %)
|> close()
@ -60,7 +66,10 @@ pillExtrude = extrude(pillSketch, length = 10)
rectangleSketch = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> line(end = [10, 0], tag = $seg1)
|> angledLine(angle = tangentToEnd(seg1), length = 10)
|> angledLine({
angle = tangentToEnd(seg1),
length = 10
}, %)
|> line(end = [0, 10])
|> line(end = [-20, 0])
|> close()
@ -74,7 +83,7 @@ rectangleExtrude = extrude(rectangleSketch, length = 10)
bottom = startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> arcTo({ end = [10, 10], interior = [5, 1] }, %, $arc1)
|> angledLine(angle = tangentToEnd(arc1), length = 20)
|> angledLine([tangentToEnd(arc1), 20], %)
|> close()
```
@ -86,7 +95,7 @@ circSketch = startSketchOn(XY)
triangleSketch = startSketchOn(XY)
|> startProfileAt([-5, 0], %)
|> angledLine(angle = tangentToEnd(circ), length = 10)
|> angledLine([tangentToEnd(circ), 10], %)
|> line(end = [-15, 0])
|> close()
```

View File

@ -35,9 +35,9 @@ tangentialArc(
```js
exampleSketch = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> angledLine(angle = 60, length = 10)
|> angledLine({ angle = 60, length = 10 }, %)
|> tangentialArc({ radius = 10, offset = -120 }, %)
|> angledLine(angle = -60, length = 10)
|> angledLine({ angle = -60, length = 10 }, %)
|> close()
example = extrude(exampleSketch, length = 10)

View File

@ -35,7 +35,7 @@ tangentialArcTo(
```js
exampleSketch = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> angledLine(angle = 60, length = 10)
|> angledLine({ angle = 60, length = 10 }, %)
|> tangentialArcTo([15, 15], %)
|> line(end = [10, -15])
|> close()

View File

@ -35,7 +35,7 @@ tangentialArcToRelative(
```js
exampleSketch = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> angledLine(angle = 45, length = 10)
|> angledLine({ angle = 45, length = 10 }, %)
|> tangentialArcToRelative([0, -10], %)
|> line(end = [-10, 0])
|> close()

View File

@ -30,7 +30,7 @@ tau(): number
```js
exampleSketch = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> angledLine(angle = 50, length = 10 * tau())
|> angledLine({ angle = 50, length = 10 * tau() }, %)
|> yLine(endAbsolute = 0)
|> close()

View File

@ -33,7 +33,10 @@ toDegrees(num: number): number
```js
exampleSketch = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> angledLine(angle = 50, length = 70 * cos(toDegrees(pi() / 4)))
|> angledLine({
angle = 50,
length = 70 * cos(toDegrees(pi() / 4))
}, %)
|> yLine(endAbsolute = 0)
|> close()

View File

@ -33,7 +33,10 @@ toRadians(num: number): number
```js
exampleSketch = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> angledLine(angle = 50, length = 70 * cos(toRadians(45)))
|> angledLine({
angle = 50,
length = 70 * cos(toRadians(45))
}, %)
|> yLine(endAbsolute = 0)
|> close()

View File

@ -86,9 +86,15 @@ cube
sketch001 = startSketchOn(XY)
rectangleSketch = startProfileAt([-200, 23.86], sketch001)
|> angledLine(angle = 0, length = 73.47, tag = $rectangleSegmentA001)
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 50.61)
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001))
|> angledLine([0, 73.47], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001) - 90,
50.61
], %)
|> angledLine([
segAng(rectangleSegmentA001),
-segLen(rectangleSegmentA001)
], %)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()

View File

@ -184,17 +184,15 @@ way:
```norun
startSketchOn('XZ')
|> startProfileAt(origin, %)
|> angledLine(angle = 0, length = 191.26, tag = $rectangleSegmentA001)
|> angledLine(
|> angledLine({angle = 0, length = 191.26}, %, $rectangleSegmentA001)
|> angledLine({
angle = segAng(rectangleSegmentA001) - 90,
length = 196.99,
tag = $rectangleSegmentB001,
)
|> angledLine(
}, %, $rectangleSegmentB001)
|> angledLine({
angle = segAng(rectangleSegmentA001),
length = -segLen(rectangleSegmentA001),
tag = $rectangleSegmentC001,
)
}, %, $rectangleSegmentC001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
```
@ -219,17 +217,15 @@ However if the code was written like this:
fn rect(origin) {
return startSketchOn('XZ')
|> startProfileAt(origin, %)
|> angledLine(angle = 0, length = 191.26, tag = $rectangleSegmentA001)
|> angledLine(
|> angledLine({angle = 0, length = 191.26}, %, $rectangleSegmentA001)
|> angledLine({
angle = segAng(rectangleSegmentA001) - 90,
length = 196.99,
tag = $rectangleSegmentB001,
)
|> angledLine(
length = 196.99
}, %, $rectangleSegmentB001)
|> angledLine({
angle = segAng(rectangleSegmentA001),
length = -segLen(rectangleSegmentA001)
tag = $rectangleSegmentC001,
)
}, %, $rectangleSegmentC001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
}
@ -249,17 +245,15 @@ For example the following code works.
fn rect(origin) {
return startSketchOn('XZ')
|> startProfileAt(origin, %)
|> angledLine(angle = 0, length = 191.26, tag = $rectangleSegmentA001)
|> angledLine(
|> angledLine({angle = 0, length = 191.26}, %, $rectangleSegmentA001)
|> angledLine({
angle = segAng(rectangleSegmentA001) - 90,
length = 196.99,
tag = $rectangleSegmentB001,
)
|> angledLine(
length = 196.99
}, %, $rectangleSegmentB001)
|> angledLine({
angle = segAng(rectangleSegmentA001),
length = -segLen(rectangleSegmentA001)
tag = $rectangleSegmentC001,
)
}, %, $rectangleSegmentC001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
}

View File

@ -14,17 +14,15 @@ way:
```js
startSketchOn('XZ')
|> startProfileAt(origin, %)
|> angledLine(angle = 0, length = 191.26, tag = $rectangleSegmentA001)
|> angledLine(
|> angledLine({angle = 0, length = 191.26}, %, $rectangleSegmentA001)
|> angledLine({
angle = segAng(rectangleSegmentA001) - 90,
length = 196.99,
tag = $rectangleSegmentB001,
)
|> angledLine(
}, %, $rectangleSegmentB001)
|> angledLine({
angle = segAng(rectangleSegmentA001),
length = -segLen(rectangleSegmentA001),
tag = $rectangleSegmentC001,
)
}, %, $rectangleSegmentC001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
```
@ -48,16 +46,15 @@ However if the code was written like this:
fn rect(origin) {
return startSketchOn('XZ')
|> startProfileAt(origin, %)
|> angledLine(angle = 0, length = 191.26, tag = $rectangleSegmentA001)
|> angledLine(
|> angledLine({angle = 0, length = 191.26}, %, $rectangleSegmentA001)
|> angledLine({
angle = segAng(rectangleSegmentA001) - 90,
length = 196.99,
tag = $rectangleSegmentB001)
|> angledLine(
length = 196.99
}, %, $rectangleSegmentB001)
|> angledLine({
angle = segAng(rectangleSegmentA001),
length = -segLen(rectangleSegmentA001),
tag = $rectangleSegmentC001
)
length = -segLen(rectangleSegmentA001)
}, %, $rectangleSegmentC001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
}
@ -77,15 +74,15 @@ For example the following code works.
fn rect(origin) {
return startSketchOn('XZ')
|> startProfileAt(origin, %)
|> angledLine(angle = 0, length = 191.26, tag = $rectangleSegmentA001)
|> angledLine(
|> angledLine({angle = 0, length = 191.26}, %, $rectangleSegmentA001)
|> angledLine({
angle = segAng(rectangleSegmentA001) - 90,
length = 196.99
, %, $rectangleSegmentB001)
|> angledLine(
}, %, $rectangleSegmentB001)
|> angledLine({
angle = segAng(rectangleSegmentA001),
length = -segLen(rectangleSegmentA001)
, %, $rectangleSegmentC001)
}, %, $rectangleSegmentC001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
}

View File

@ -38,10 +38,10 @@ xLine(
exampleSketch = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> xLine(length = 15)
|> angledLine(angle = 80, length = 15)
|> angledLine({ angle = 80, length = 15 }, %)
|> line(end = [8, -10])
|> xLine(length = 10)
|> angledLine(angle = 120, length = 30)
|> angledLine({ angle = 120, length = 30 }, %)
|> xLine(length = -15)
|> close()

View File

@ -38,7 +38,7 @@ yLine(
exampleSketch = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> yLine(length = 15)
|> angledLine(angle = 30, length = 15)
|> angledLine({ angle = 30, length = 15 }, %)
|> line(end = [8, -10])
|> yLine(length = -5)
|> close()

View File

@ -46,8 +46,6 @@ test.describe('Point and click for boolean workflows', () => {
localStorage.setItem('persistCode', file)
}, file)
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// Test coordinates for selection - these might need adjustment based on actual scene layout
@ -77,6 +75,7 @@ test.describe('Point and click for boolean workflows', () => {
// Select first object in the scene, expect there to be a pixel diff from the selection color change
await clickFirstObject({ pixelDiff: 50 })
await page.waitForTimeout(1000)
// For subtract, we need to proceed to the next step before selecting the second object
if (operationName !== 'subtract') {
@ -87,6 +86,8 @@ test.describe('Point and click for boolean workflows', () => {
// Select second object
await clickSecondObject({ pixelDiff: 50 })
await page.waitForTimeout(1000)
// Confirm the operation in the command bar
await cmdBar.progressCmdBar()

View File

@ -4,6 +4,7 @@ import { uuidv4 } from '@src/lib/utils'
import type { HomePageFixture } from '@e2e/playwright/fixtures/homePageFixture'
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
import type { ToolbarFixture } from '@e2e/playwright/fixtures/toolbarFixture'
import { getUtils } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
@ -15,6 +16,7 @@ test.describe(
page: Page,
homePage: HomePageFixture,
scene: SceneFixture,
toolbar: ToolbarFixture,
plane: string,
clickCoords: { x: number; y: number }
) => {
@ -59,9 +61,12 @@ test.describe(
await u.sendCustomCmd(updateCamCommand)
await u.closeDebugPanel()
await page.mouse.click(clickCoords.x, clickCoords.y)
await page.waitForTimeout(600) // wait for animation
await toolbar.waitUntilSketchingReady()
await expect(
page.getByRole('button', { name: 'line Line', exact: true })
).toBeVisible()
@ -117,11 +122,12 @@ test.describe(
]
for (const config of planeConfigs) {
test(config.plane, async ({ page, homePage, scene }) => {
test(config.plane, async ({ page, homePage, scene, toolbar }) => {
await sketchOnPlaneAndBackSideTest(
page,
homePage,
scene,
toolbar,
config.plane,
config.coords
)

View File

@ -15,6 +15,7 @@ test.describe('Code pane and errors', { tag: ['@skipWin'] }, () => {
page,
homePage,
scene,
cmdBar,
}) => {
const u = await getUtils(page)
@ -36,7 +37,7 @@ extrude001 = extrude(sketch001, length = 5)`
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// Ensure no badge is present
const codePaneButtonHolder = page.locator('#code-button-holder')
@ -171,6 +172,8 @@ extrude001 = extrude(sketch001, length = 5)`
context,
page,
homePage,
scene,
cmdBar,
}) => {
// Load the app with the working starter code
await context.addInitScript((code) => {
@ -180,9 +183,7 @@ extrude001 = extrude(sketch001, length = 5)`
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
// FIXME: await scene.waitForExecutionDone() does not work. It still fails.
// I needed to increase this timeout to get this to pass.
await page.waitForTimeout(10000)
await scene.settled(cmdBar)
// Ensure badge is present
const codePaneButtonHolder = page.locator('#code-button-holder')

View File

@ -317,9 +317,13 @@ test.describe('Command bar tests', { tag: ['@skipWin'] }, () => {
test('Can switch between sketch tools via command bar', async ({
page,
homePage,
scene,
cmdBar,
toolbar,
}) => {
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await scene.settled(cmdBar)
const sketchButton = page.getByRole('button', { name: 'Start Sketch' })
const cmdBarButton = page.getByRole('button', { name: 'Commands' })
@ -343,7 +347,9 @@ test.describe('Command bar tests', { tag: ['@skipWin'] }, () => {
// Start a sketch
await sketchButton.click()
await page.mouse.click(700, 200)
await toolbar.waitUntilSketchingReady()
// Switch between sketch tools via the command bar
await expect(lineToolButton).toHaveAttribute('aria-pressed', 'true')

View File

@ -11,7 +11,7 @@ import { expect, test } from '@e2e/playwright/zoo-test'
test(
'export works on the first try',
{ tag: ['@electron', '@skipLocalEngine'] },
async ({ page, context, scene, tronApp }, testInfo) => {
async ({ page, context, scene, tronApp, cmdBar }, testInfo) => {
if (!tronApp) {
fail()
}
@ -47,7 +47,8 @@ test(
const exportButton = page.getByTestId('export-pane-button')
await expect(exportButton).toBeVisible()
await scene.waitForExecutionDone()
// Wait for the model to finish loading
await scene.settled(cmdBar)
const gltfOption = page.getByText('glTF')
const submitButton = page.getByText('Confirm Export')
@ -120,8 +121,7 @@ test(
// Close the file pane
await u.closeFilePanel()
// FIXME: await scene.waitForExecutionDone() does not work. The modeling indicator stays in -receive-reliable and not execution done
await page.waitForTimeout(10000)
await scene.settled(cmdBar)
// expect zero errors in guter
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()

View File

@ -78,12 +78,14 @@ sketch001 = startSketchOn(XY)
// Ensure we execute the first time.
await u.openDebugPanel()
await expect(
page.locator('[data-receive-command-type="scene_clear_all"]')
).toHaveCount(1)
await expect(
page.locator('[data-message-type="execution-done"]')
).toHaveCount(2)
await expect
.poll(() =>
page.locator('[data-receive-command-type="scene_clear_all"]').count()
)
.toBe(1)
await expect
.poll(() => page.locator('[data-message-type="execution-done"]').count())
.toBe(2)
// Add whitespace to the end of the code.
await u.codeLocator.click()
@ -110,12 +112,14 @@ sketch001 = startSketchOn(XY)
test('ensure we use the cache, and do not clear on append', async ({
homePage,
page,
scene,
cmdBar,
}) => {
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.settled(cmdBar)
await u.codeLocator.click()
await page.keyboard.type(`sketch001 = startSketchOn(XY)
@ -499,7 +503,7 @@ sketch_001 = startSketchOn(XY)
await page.keyboard.press('ArrowLeft')
await page.keyboard.press('ArrowRight')
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// error in guter
await expect(page.locator('.cm-lint-marker-info').first()).toBeVisible()

View File

@ -19,7 +19,7 @@ length001 = timesFive(1) * 5
sketch001 = startSketchOn(XZ)
|> startProfileAt([20, 10], %)
|> line(end = [10, 10])
|> angledLine(angle = -45, length = length001)
|> angledLine([-45, length001], %)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
revolve001 = revolve(sketch001, axis = X)
@ -38,7 +38,7 @@ extrude001 = extrude(sketch002, length = 10)
const FEATURE_TREE_SKETCH_CODE = `sketch001 = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> angledLine(angle = 0, length = 4, tag = $rectangleSegmentA001)
|> angledLine([0, 4], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001) - 90,
2
@ -64,7 +64,7 @@ test.describe('Feature Tree pane', () => {
test(
'User can go to definition and go to function definition',
{ tag: '@electron' },
async ({ context, homePage, scene, editor, toolbar }) => {
async ({ context, homePage, scene, editor, toolbar, cmdBar, page }) => {
await context.folderSetupFn(async (dir) => {
const bracketDir = join(dir, 'test-sample')
await fsp.mkdir(bracketDir, { recursive: true })
@ -86,9 +86,13 @@ test.describe('Feature Tree pane', () => {
sortBy: 'last-modified-desc',
})
await homePage.openProject('test-sample')
await scene.waitForExecutionDone()
await editor.closePane()
await scene.connectionEstablished()
await scene.settled(cmdBar)
await toolbar.openFeatureTreePane()
await expect
.poll(() => page.getByText('Feature tree').count())
.toBeGreaterThan(1)
})
async function testViewSource({
@ -254,7 +258,7 @@ test.describe('Feature Tree pane', () => {
sortBy: 'last-modified-desc',
})
await homePage.openProject('test-sample')
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
await toolbar.openFeatureTreePane()
})
@ -339,7 +343,7 @@ test.describe('Feature Tree pane', () => {
sortBy: 'last-modified-desc',
})
await homePage.openProject('test-sample')
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
await toolbar.openFeatureTreePane()
})
@ -414,8 +418,7 @@ profile003 = startProfileAt([0, -4.93], sketch001)
const planeColor: [number, number, number] = [74, 74, 74]
await homePage.openProject('test-sample')
// FIXME: @lf94 has a better way to verify execution completion, in a PR rn
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
await test.step(`Verify we see the sketch`, async () => {
await scene.expectPixelColor(sketchColor, testPoint, 10)

View File

@ -47,6 +47,7 @@ test.describe('integrations tests', () => {
await scene.connectionEstablished()
await scene.settled(cmdBar)
await clickObj()
await page.waitForTimeout(1000)
await scene.moveNoWhere()
await editor.expectState({
activeLines: [
@ -72,11 +73,11 @@ test.describe('integrations tests', () => {
})
await test.step('setup for next assertion', async () => {
await toolbar.openFile('main.kcl')
await scene.settled(cmdBar)
await page.waitForTimeout(1000)
await clickObj()
await page.waitForTimeout(1000)
await scene.moveNoWhere()
await page.waitForTimeout(1000)
await editor.expectState({
activeLines: [
'|>startProfileAt([75.8,317.2],%)//[$startCapTag,$EndCapTag]',
@ -89,7 +90,7 @@ test.describe('integrations tests', () => {
await toolbar.expectFileTreeState(['main.kcl', fileName])
})
await test.step('check sketch mode is exited when opening a different file', async () => {
await toolbar.openFile(fileName, { wait: false })
await toolbar.openFile(fileName)
// check we're out of sketch mode
await expect(toolbar.exitSketchBtn).not.toBeVisible()

View File

@ -112,22 +112,16 @@ export class CmdBarFixture {
* and assumes we are past the `pickCommand` step.
*/
progressCmdBar = async (shouldFuzzProgressMethod = true) => {
// FIXME: Progressing the command bar is a race condition. We have an async useEffect that reports the final state via useCalculateKclExpression. If this does not run quickly enough, it will not "fail" the continue because you can press continue if the state is not ready. E2E tests do not know this.
// Wait 1250ms to assume the await executeAst of the KCL input field is finished
await this.page.waitForTimeout(1250)
if (shouldFuzzProgressMethod || Math.random() > 0.5) {
const arrowButton = this.page.getByRole('button', {
name: 'arrow right Continue',
})
if (await arrowButton.isVisible()) {
await arrowButton.click()
} else {
await this.page
.getByRole('button', { name: 'checkmark Submit command' })
.click()
}
await this.page.waitForTimeout(2000)
const arrowButton = this.page.getByRole('button', {
name: 'arrow right Continue',
})
if (await arrowButton.isVisible()) {
await arrowButton.click()
} else {
await this.page.keyboard.press('Enter')
await this.page
.getByRole('button', { name: 'checkmark Submit command' })
.click()
}
}

View File

@ -39,7 +39,8 @@ export class AuthenticatedApp {
}
async initialise(code = '') {
await setup(this.context, this.page, this.testInfo)
const testDir = this.testInfo.outputPath('electron-test-projects-dir')
await setup(this.context, this.page, testDir, this.testInfo)
const u = await getUtils(this.page)
await this.page.addInitScript(async (code) => {
@ -102,11 +103,11 @@ export class ElectronZoo {
return resolve(undefined)
}
if (Date.now() - timeA > 10000) {
if (Date.now() - timeA > 3000) {
return resolve(undefined)
}
setTimeout(checkDisconnected, 0)
setTimeout(checkDisconnected, 1)
}
checkDisconnected()
})
@ -128,11 +129,9 @@ export class ElectronZoo {
const that = this
const options = {
timeout: 120000,
args: ['.', '--no-sandbox'],
env: {
...process.env,
TEST_SETTINGS_FILE_KEY: this.projectDirName,
IS_PLAYWRIGHT: 'true',
},
...(process.env.ELECTRON_OVERRIDE_DIST_PATH
@ -155,6 +154,7 @@ export class ElectronZoo {
if (!this.electron) {
this.electron = await electron.launch(options)
this.page = await this.electron.firstWindow()
// Mac takes quite a long time to create the first window in CI.
// Turns out we can't trust firstWindow() either. So loop.
let timeoutId: ReturnType<typeof setTimeout>
@ -200,7 +200,14 @@ export class ElectronZoo {
await this.context.tracing.startChunk()
await setup(this.context, this.page, testInfo)
// THIS IS ABSOLUTELY NECESSARY TO CHANGE THE PROJECT DIRECTORY BETWEEN
// TESTS BECAUSE OF THE ELECTRON INSTANCE REUSE.
await this.electron?.evaluate(({ app }, projectDirName) => {
// @ts-ignore can't declaration merge see main.ts
app.testProperty['TEST_SETTINGS_FILE_KEY'] = projectDirName
}, this.projectDirName)
await setup(this.context, this.page, this.projectDirName, testInfo)
await this.cleanProjectDir()
@ -250,11 +257,6 @@ export class ElectronZoo {
// return app.reuseWindowForTest();
// });
await this.electron?.evaluate(({ app }, projectDirName) => {
// @ts-ignore can't declaration merge see main.ts
app.testProperty['TEST_SETTINGS_FILE_KEY'] = projectDirName
}, this.projectDirName)
// Always start at the root view
await this.page.goto(this.firstUrl)
@ -278,8 +280,9 @@ export class ElectronZoo {
// Not a problem if it already exists.
}
const tempSettingsFilePath = path.join(
const tempSettingsFilePath = path.resolve(
this.projectDirName,
'..',
SETTINGS_FILE_NAME
)

View File

@ -43,21 +43,13 @@ type DragFromHandler = (
export class SceneFixture {
public page: Page
public streamWrapper!: Locator
public loadingIndicator!: Locator
public networkToggleConnected!: Locator
public startEditSketchBtn!: Locator
get exeIndicator() {
return this.page
.getByTestId('model-state-indicator-execution-done')
.or(this.page.getByTestId('model-state-indicator-receive-reliable'))
}
constructor(page: Page) {
this.page = page
this.streamWrapper = page.getByTestId('stream')
this.networkToggleConnected = page.getByTestId('network-toggle-ok')
this.loadingIndicator = this.streamWrapper.getByTestId('loading')
this.startEditSketchBtn = page
.getByRole('button', { name: 'Start Sketch' })
.or(page.getByRole('button', { name: 'Edit Sketch' }))
@ -231,10 +223,6 @@ export class SceneFixture {
}
}
waitForExecutionDone = async () => {
await expect(this.exeIndicator).toBeVisible({ timeout: 30000 })
}
connectionEstablished = async () => {
const timeout = 30000
await expect(this.networkToggleConnected).toBeVisible({ timeout })
@ -243,6 +231,9 @@ export class SceneFixture {
settled = async (cmdBar: CmdBarFixture) => {
const u = await getUtils(this.page)
await expect(this.startEditSketchBtn).not.toBeDisabled()
await expect(this.startEditSketchBtn).toBeVisible()
await cmdBar.openCmdBar()
await cmdBar.chooseCommand('Settings · app · show debug panel')
await cmdBar.selectOption({ name: 'on' }).click()
@ -250,10 +241,6 @@ export class SceneFixture {
await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel()
await this.waitForExecutionDone()
await expect(this.startEditSketchBtn).not.toBeDisabled()
await expect(this.startEditSketchBtn).toBeVisible()
}
expectPixelColor = async (

View File

@ -84,12 +84,6 @@ export class ToolbarFixture {
return this.page.getByTestId('app-logo')
}
get exeIndicator() {
return this.page
.getByTestId('model-state-indicator-receive-reliable')
.or(this.page.getByTestId('model-state-indicator-execution-done'))
}
startSketchPlaneSelection = async () =>
doAndWaitForImageDiff(this.page, () => this.startSketchBtn.click(), 500)
@ -165,16 +159,10 @@ export class ToolbarFixture {
}
}
/**
* Opens file by it's name and waits for execution to finish
* Opens file by it's name
*/
openFile = async (
fileName: string,
{ wait }: { wait?: boolean } = { wait: true }
) => {
openFile = async (fileName: string) => {
await this.filePane.getByText(fileName).click()
if (wait) {
await expect(this.exeIndicator).toBeVisible({ timeout: 15_000 })
}
}
selectCenterRectangle = async () => {
await this.page

View File

@ -10,6 +10,7 @@ test.describe('Import UI tests', () => {
toolbar,
scene,
editor,
cmdBar,
}) => {
await context.folderSetupFn(async (dir) => {
const projectDir = path.join(dir, 'import-test')
@ -61,7 +62,7 @@ sketch002 = startSketchOn(extrude001, seg01)`
})
await homePage.openProject('import-test')
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
await scene.moveCameraTo(
{

View File

@ -7,7 +7,7 @@ import { expect, test } from '@e2e/playwright/zoo-test'
test(
'When machine-api server not found butt is disabled and shows the reason',
{ tag: '@electron' },
async ({ context, page }, testInfo) => {
async ({ context, page, scene, cmdBar }, testInfo) => {
await context.folderSetupFn(async (dir) => {
const bracketDir = join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true })
@ -23,10 +23,7 @@ test(
await page.getByText('bracket').click()
await expect(page.getByTestId('loading')).toBeAttached()
await expect(page.getByTestId('loading')).not.toBeAttached({
timeout: 20_000,
})
await scene.settled(cmdBar)
const notFoundText = 'Machine API server was not discovered'
await expect(page.getByText(notFoundText).first()).not.toBeVisible()
@ -47,7 +44,7 @@ test(
test(
'When machine-api server not found home screen & project status shows the reason',
{ tag: '@electron' },
async ({ context, page }, testInfo) => {
async ({ context, page, scene, cmdBar }, testInfo) => {
await context.folderSetupFn(async (dir) => {
const bracketDir = join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true })
@ -71,10 +68,7 @@ test(
await page.getByText('bracket').click()
await expect(page.getByTestId('loading')).toBeAttached()
await expect(page.getByTestId('loading')).not.toBeAttached({
timeout: 20_000,
})
await scene.settled(cmdBar)
await expect(page.getByText(notFoundText).nth(1)).not.toBeVisible()

View File

@ -88,7 +88,7 @@ test.describe('Named view tests', () => {
// Create and load project
await createProject({ name: projectName, page })
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// Create named view
const projectDirName = testInfo.outputPath('electron-test-projects-dir')
@ -110,14 +110,17 @@ test.describe('Named view tests', () => {
expect(exists).toBe(true)
}).toPass()
// Read project.toml into memory
let tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
await expect(async () => {
// Read project.toml into memory
let tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
// Write the entire tomlString to a snapshot.
// There are many key/value pairs to check this is a safer match.
expect(tomlString).toMatchSnapshot('verify-named-view-gets-created')
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
// Write the entire tomlString to a snapshot.
// There are many key/value pairs to check this is a safer match.
expect(tomlString).toMatchSnapshot('verify-named-view-gets-created')
}).toPass()
})
test('Verify named view gets deleted', async ({
cmdBar,
@ -130,7 +133,7 @@ test.describe('Named view tests', () => {
// Create project and go into the project
await createProject({ name: projectName, page })
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// Create a new named view
await cmdBar.openCmdBar()
@ -152,14 +155,16 @@ test.describe('Named view tests', () => {
expect(exists).toBe(true)
}).toPass()
// Read project.toml into memory
let tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
await expect(async () => {
// Read project.toml into memory
let tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
// Write the entire tomlString to a snapshot.
// There are many key/value pairs to check this is a safer match.
expect(tomlString).toMatchSnapshot('verify-named-view-gets-created')
// Write the entire tomlString to a snapshot.
// There are many key/value pairs to check this is a safer match.
expect(tomlString).toMatchSnapshot('verify-named-view-gets-created')
}).toPass()
// Delete a named view
await cmdBar.openCmdBar()
@ -167,14 +172,16 @@ test.describe('Named view tests', () => {
cmdBar.selectOption({ name: myNamedView2 })
await cmdBar.progressCmdBar(false)
// Read project.toml into memory again since we deleted a named view
tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
await expect(async () => {
// Read project.toml into memory again since we deleted a named view
let tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
// // Write the entire tomlString to a snapshot.
// // There are many key/value pairs to check this is a safer match.
expect(tomlString).toMatchSnapshot('verify-named-view-gets-deleted')
// // Write the entire tomlString to a snapshot.
// // There are many key/value pairs to check this is a safer match.
expect(tomlString).toMatchSnapshot('verify-named-view-gets-deleted')
}).toPass()
})
test('Verify named view gets loaded', async ({
cmdBar,
@ -186,7 +193,7 @@ test.describe('Named view tests', () => {
// Create project and go into the project
await createProject({ name: projectName, page })
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// Create a new named view
await cmdBar.openCmdBar()
@ -208,14 +215,16 @@ test.describe('Named view tests', () => {
expect(exists).toBe(true)
}).toPass()
// Read project.toml into memory
let tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
await expect(async () => {
// Read project.toml into memory
let tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
// Write the entire tomlString to a snapshot.
// There are many key/value pairs to check this is a safer match.
expect(tomlString).toMatchSnapshot('verify-named-view-gets-created')
// Write the entire tomlString to a snapshot.
// There are many key/value pairs to check this is a safer match.
expect(tomlString).toMatchSnapshot('verify-named-view-gets-created')
}).toPass()
// Create a load a named view
await cmdBar.openCmdBar()
@ -239,7 +248,7 @@ test.describe('Named view tests', () => {
// Create and load project
await createProject({ name: projectName, page })
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// Create named view
const projectDirName = testInfo.outputPath('electron-test-projects-dir')
@ -282,13 +291,15 @@ test.describe('Named view tests', () => {
expect(exists).toBe(true)
}).toPass()
// Read project.toml into memory
let tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
await expect(async () => {
// Read project.toml into memory
let tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
// Write the entire tomlString to a snapshot.
// There are many key/value pairs to check this is a safer match.
expect(tomlString).toMatchSnapshot('verify-two-named-view-gets-created')
// Write the entire tomlString to a snapshot.
// There are many key/value pairs to check this is a safer match.
expect(tomlString).toMatchSnapshot('verify-two-named-view-gets-created')
}).toPass()
})
})

View File

@ -12,13 +12,21 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
if (!tronApp) fail()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail()
const newProject =
app.applicationMenu.getMenuItemById('File.New project')
if (!newProject) fail()
newProject.click()
})
await expect
.poll(
async () =>
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) {
return false
}
const newProject =
app.applicationMenu.getMenuItemById('File.New project')
if (!newProject) return false
newProject.click()
return true
})
)
.toBe(true)
// Check that the command bar is opened
await expect(cmdBar.cmdBarElement).toBeVisible()
// Check the placeholder project name exists
@ -32,13 +40,21 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
if (!tronApp) fail()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail()
const openProject =
app.applicationMenu.getMenuItemById('File.Open project')
if (!openProject) fail()
openProject.click()
})
await expect
.poll(
async () =>
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) return false
const openProject =
app.applicationMenu.getMenuItemById('File.Open project')
if (!openProject) {
return false
}
openProject.click()
return true
})
)
.toBe(true)
// Check that the command bar is opened
await expect(cmdBar.cmdBarElement).toBeVisible()
// Check the placeholder project name exists
@ -56,14 +72,23 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
if (!tronApp) fail()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail()
const userSettings = app.applicationMenu.getMenuItemById(
'File.Preferences.User settings'
await expect
.poll(
async () =>
await tronApp.electron.evaluate(async ({ app }) => {
console.log(app)
if (!app || !app.applicationMenu) {
return false
}
const userSettings = app.applicationMenu.getMenuItemById(
'File.Preferences.User settings'
)
if (!userSettings) return false
userSettings.click()
return true
})
)
if (!userSettings) fail()
userSettings.click()
})
.toBe(true)
const settings = page.getByTestId('settings-dialog-panel')
await expect(settings).toBeVisible()
// You are viewing the user tab
@ -77,17 +102,27 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
cmdBar,
page,
}) => {
if (!tronApp) fail()
if (!tronApp) {
fail()
}
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail()
const keybindings = app.applicationMenu.getMenuItemById(
'File.Preferences.Keybindings'
await expect
.poll(
async () =>
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) return false
const keybindings = app.applicationMenu.getMenuItemById(
'File.Preferences.Keybindings'
)
if (!keybindings) {
return false
}
keybindings.click()
return true
})
)
if (!keybindings) fail()
keybindings.click()
})
.toBe(true)
const settings = page.getByTestId('settings-dialog-panel')
await expect(settings).toBeVisible()
// You are viewing the keybindings tab
@ -102,14 +137,22 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
if (!tronApp) fail()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail()
const menu = app.applicationMenu.getMenuItemById(
'File.Preferences.User default units'
await expect
.poll(
async () =>
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) {
return false
}
const menu = app.applicationMenu.getMenuItemById(
'File.Preferences.User default units'
)
if (!menu) return false
menu.click()
return true
})
)
if (!menu) fail()
menu.click()
})
.toBe(true)
const settings = page.getByTestId('settings-dialog-panel')
await expect(settings).toBeVisible()
const defaultUnit = settings.locator('#defaultUnit')
@ -119,14 +162,22 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
if (!tronApp) fail()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail()
const menu = app.applicationMenu.getMenuItemById(
'File.Preferences.Theme'
await expect
.poll(
async () =>
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) return false
const menu = app.applicationMenu.getMenuItemById(
'File.Preferences.Theme'
)
if (!menu) {
return false
}
menu.click()
return true
})
)
if (!menu) fail()
menu.click()
})
.toBe(true)
// Check that the command bar is opened
await expect(cmdBar.cmdBarElement).toBeVisible()
// Check the placeholder project name exists
@ -144,14 +195,22 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
if (!tronApp) fail()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail()
const menu = app.applicationMenu.getMenuItemById(
'File.Preferences.Theme color'
await expect
.poll(
async () =>
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) {
return false
}
const menu = app.applicationMenu.getMenuItemById(
'File.Preferences.Theme color'
)
if (!menu) return false
menu.click()
return true
})
)
if (!menu) fail()
menu.click()
})
.toBe(true)
const settings = page.getByTestId('settings-dialog-panel')
await expect(settings).toBeVisible()
const defaultUnit = settings.locator('#themeColor')
@ -165,13 +224,22 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
if (!tronApp) fail()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail()
const menu = app.applicationMenu.getMenuItemById('File.Sign out')
if (!menu) fail()
// FIXME: Add back when you can actually sign out
// menu.click()
})
await expect
.poll(
async () =>
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) return false
const menu =
app.applicationMenu.getMenuItemById('File.Sign out')
if (!menu) {
return false
}
// FIXME: Add back when you can actually sign out
// menu.click()
return true
})
)
.toBe(true)
// FIXME: When signing out during E2E the page is not bound correctly.
// It cannot find the button
// const signIn = page.getByTestId('sign-in-button')
@ -184,14 +252,22 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
if (!tronApp) fail()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail()
const menu = app.applicationMenu.getMenuItemById(
'Edit.Rename project'
await expect
.poll(
async () =>
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) {
return false
}
const menu = app.applicationMenu.getMenuItemById(
'Edit.Rename project'
)
if (!menu) return false
menu.click()
return true
})
)
if (!menu) fail()
menu.click()
})
.toBe(true)
// Check the placeholder project name exists
const actual = await cmdBar.cmdBarElement
.getByTestId('command-name')
@ -203,20 +279,27 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
if (!tronApp) fail()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail()
const menu = app.applicationMenu.getMenuItemById(
'Edit.Delete project'
await expect
.poll(
async () =>
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) return false
const menu = app.applicationMenu.getMenuItemById(
'Edit.Delete project'
)
if (!menu) {
return false
}
menu.click()
return true
})
)
if (!menu) fail()
menu.click()
})
.toBe(true)
// Check the placeholder project name exists
const actual = await cmdBar.cmdBarElement
.getByTestId('command-name')
.textContent()
const actual = async () =>
cmdBar.cmdBarElement.getByTestId('command-name').textContent()
const expected = 'Delete project'
expect(actual).toBe(expected)
await expect.poll(async () => await actual()).toBe(expected)
})
test('Home.Edit.Change project directory', async ({
tronApp,
@ -226,14 +309,22 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
if (!tronApp) fail()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail()
const menu = app.applicationMenu.getMenuItemById(
'Edit.Change project directory'
await expect
.poll(
async () =>
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) {
return false
}
const menu = app.applicationMenu.getMenuItemById(
'Edit.Change project directory'
)
if (!menu) return false
menu.click()
return true
})
)
if (!menu) fail()
menu.click()
})
.toBe(true)
const settings = page.getByTestId('settings-dialog-panel')
await expect(settings).toBeVisible()
const projectDirectory = settings.locator('#projectDirectory')
@ -249,14 +340,22 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
if (!tronApp) fail()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail()
const menu = app.applicationMenu.getMenuItemById(
'View.Command Palette...'
await expect
.poll(
async () =>
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) return false
const menu = app.applicationMenu.getMenuItemById(
'View.Command Palette...'
)
if (!menu) {
return false
}
menu.click()
return true
})
)
if (!menu) fail()
menu.click()
})
.toBe(true)
// Check the placeholder project name exists
const actual = cmdBar.cmdBarElement.getByTestId('cmd-bar-search')
await expect(actual).toBeVisible()
@ -267,14 +366,22 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
if (!tronApp) fail()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail()
const menu = app.applicationMenu.getMenuItemById(
'Help.Show all commands'
await expect
.poll(
async () =>
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) {
return false
}
const menu = app.applicationMenu.getMenuItemById(
'Help.Show all commands'
)
if (!menu) return false
menu.click()
return true
})
)
if (!menu) fail()
menu.click()
})
.toBe(true)
// Check the placeholder project name exists
const actual = cmdBar.cmdBarElement.getByTestId('cmd-bar-search')
await expect(actual).toBeVisible()
@ -283,13 +390,21 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
if (!tronApp) fail()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail()
const menu = app.applicationMenu.getMenuItemById(
'Help.KCL code samples'
await expect
.poll(
async () =>
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) return false
const menu = app.applicationMenu.getMenuItemById(
'Help.KCL code samples'
)
if (!menu) {
return false
}
return true
})
)
if (!menu) fail()
})
.toBe(true)
})
test('Home.Help.Refresh and report a bug', async ({
tronApp,
@ -299,14 +414,22 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
if (!tronApp) fail()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail()
const menu = app.applicationMenu.getMenuItemById(
'Help.Refresh and report a bug'
await expect
.poll(
async () =>
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) {
return false
}
const menu = app.applicationMenu.getMenuItemById(
'Help.Refresh and report a bug'
)
if (!menu) return false
menu.click()
return true
})
)
if (!menu) fail()
menu.click()
})
.toBe(true)
// Core dump and refresh magic number timeout
await page.waitForTimeout(7000)
const actual = page.getByText(
@ -318,14 +441,22 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
if (!tronApp) fail()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail()
const menu = app.applicationMenu.getMenuItemById(
'Help.Reset onboarding'
await expect
.poll(
async () =>
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) return false
const menu = app.applicationMenu.getMenuItemById(
'Help.Reset onboarding'
)
if (!menu) {
return false
}
menu.click()
return true
})
)
if (!menu) fail()
menu.click()
})
.toBe(true)
const actual = page.getByText(
`This is a hardware design tool that lets you edit visually, with code, or both. It's powered by the KittyCAD Design API, the first API created for anyone to build hardware design tools.`
@ -345,7 +476,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
}) => {
if (!tronApp) fail()
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -377,7 +508,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -413,7 +544,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -450,7 +581,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -487,7 +618,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -523,7 +654,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -560,7 +691,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -596,7 +727,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -630,7 +761,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -663,7 +794,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -700,7 +831,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -733,21 +864,28 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) {
throw new Error('app or app.applicationMenu is missing')
}
const menu = app.applicationMenu.getMenuItemById('File.Sign out')
if (!menu) {
throw new Error('File.Sign out')
}
// FIXME: Add back when you can actually sign out
// menu.click()
})
await expect
.poll(
async () =>
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) {
throw new Error('app or app.applicationMenu is missing')
}
const menu =
app.applicationMenu.getMenuItemById('File.Sign out')
if (!menu) {
throw new Error('File.Sign out')
}
// FIXME: Add back when you can actually sign out
// menu.click()
return true
})
)
.toBe(true)
// FIXME: When signing out during E2E the page is not bound correctly.
// It cannot find the button
// const signIn = page.getByTestId('sign-in-button')
@ -767,7 +905,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -802,7 +940,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -837,7 +975,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -867,7 +1005,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -902,7 +1040,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -937,7 +1075,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => {
@ -971,7 +1109,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1003,7 +1141,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1039,7 +1177,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1075,7 +1213,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1112,7 +1250,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1141,7 +1279,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1170,7 +1308,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1199,7 +1337,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1228,7 +1366,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1257,7 +1395,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1286,7 +1424,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1315,7 +1453,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1344,7 +1482,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1381,7 +1519,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1418,7 +1556,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1455,7 +1593,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1488,7 +1626,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1521,7 +1659,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1554,7 +1692,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1587,7 +1725,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1621,7 +1759,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1658,7 +1796,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1695,7 +1833,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1733,7 +1871,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1770,7 +1908,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1807,7 +1945,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1844,7 +1982,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1881,7 +2019,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1918,7 +2056,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1956,7 +2094,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -1994,7 +2132,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -2032,7 +2170,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -2071,7 +2209,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -2099,7 +2237,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
@ -2124,20 +2262,26 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) fail()
const menu = app.applicationMenu.getMenuItemById(
'Help.Refresh and report a bug'
await expect
.poll(
async () =>
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) return false
const menu = app.applicationMenu.getMenuItemById(
'Help.Refresh and report a bug'
)
if (!menu) return false
menu.click()
return true
})
)
if (!menu) fail()
menu.click()
})
.toBe(true)
// Core dump and refresh magic number timeout
await scene.waitForExecutionDone()
await scene.connectionEstablished()
await expect(toolbar.startSketchBtn).toBeVisible()
})
test('Modeling.Help.Reset onboarding', async ({
@ -2152,7 +2296,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
return
}
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run

View File

@ -5,13 +5,14 @@ import path from 'node:path'
import type { EditorFixture } from '@e2e/playwright/fixtures/editorFixture'
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
import type { ToolbarFixture } from '@e2e/playwright/fixtures/toolbarFixture'
import { getUtils, orRunWhenFullSuiteEnabled } from '@e2e/playwright/test-utils'
import { orRunWhenFullSuiteEnabled } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
// test file is for testing point an click code gen functionality that's not sketch mode related
test.describe('Point-and-click tests', () => {
test('verify extruding circle works', async ({
page,
context,
homePage,
cmdBar,
@ -30,8 +31,9 @@ test.describe('Point-and-click tests', () => {
await context.addInitScript((file) => {
localStorage.setItem('persistCode', file)
}, file)
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
const [clickCircle, moveToCircle] = scene.makeMouseHelpers(582, 217)
@ -72,7 +74,6 @@ test.describe('Point-and-click tests', () => {
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',
@ -186,6 +187,7 @@ test.describe('Point-and-click tests', () => {
editor,
toolbar,
scene,
cmdBar,
}) => {
const file = await fs.readFile(
path.resolve(
@ -200,9 +202,7 @@ test.describe('Point-and-click tests', () => {
}, file)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await expect(
page.getByTestId('model-state-indicator-receive-reliable')
).toBeVisible()
await scene.settled(cmdBar)
const sketchOnAChamfer = _sketchOnAChamfer(page, editor, toolbar, scene)
@ -261,7 +261,7 @@ test.describe('Point-and-click tests', () => {
clickCoords: { x: 677, y: 87 },
cameraPos: { x: -6200, y: 1500, z: 6200 },
cameraTarget: { x: 8300, y: 1100, z: 4800 },
beforeChamferSnippet: `angledLine(angle = 0, length = 268.43, tag = $rectangleSegmentA001)chamfer(
beforeChamferSnippet: `angledLine([0, 268.43], %, $rectangleSegmentA001)chamfer(
length = 30,
tags = [
getNextAdjacentEdge(yo),
@ -302,7 +302,7 @@ test.describe('Point-and-click tests', () => {
`@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag]
|> angledLine(angle = 0, length = 268.43, tag = $rectangleSegmentA001)
|> angledLine([0, 268.43], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001) - 90,
217.26
@ -320,14 +320,14 @@ extrude001 = extrude(sketch001, length = 100)
|> chamfer(length = 30, tags = [getNextAdjacentEdge(yo)], tag = $seg06)
sketch005 = startSketchOn(extrude001, seg06)
profile004=startProfileAt([-23.43,19.69], sketch005)
|> angledLine(angle = 0, length = 9.1, tag = $rectangleSegmentA005)
|> angledLine(angle = segAng(rectangleSegmentA005) - 90, length = 84.07)
|> angledLine(angle = segAng(rectangleSegmentA005), length = -segLen(rectangleSegmentA005))
|> angledLine([0, 9.1], %, $rectangleSegmentA005)
|> angledLine([segAng(rectangleSegmentA005) - 90, 84.07], %)
|> angledLine([segAng(rectangleSegmentA005), -segLen(rectangleSegmentA005)], %)
|> line(endAbsolute=[profileStartX(%), profileStartY(%)])
|> close()
sketch004 = startSketchOn(extrude001, seg05)
profile003 = startProfileAt([82.57, 322.96], sketch004)
|> angledLine(angle = 0, length = 11.16, tag = $rectangleSegmentA004)
|> angledLine([0, 11.16], %, $rectangleSegmentA004)
|> angledLine([
segAng(rectangleSegmentA004) - 90,
103.07
@ -340,7 +340,7 @@ profile003 = startProfileAt([82.57, 322.96], sketch004)
|> close()
sketch003 = startSketchOn(extrude001, seg04)
profile002 = startProfileAt([-209.64, 255.28], sketch003)
|> angledLine(angle = 0, length = 11.56, tag = $rectangleSegmentA003)
|> angledLine([0, 11.56], %, $rectangleSegmentA003)
|> angledLine([
segAng(rectangleSegmentA003) - 90,
106.84
@ -353,7 +353,7 @@ profile002 = startProfileAt([-209.64, 255.28], sketch003)
|> close()
sketch002 = startSketchOn(extrude001, seg03)
profile001 = startProfileAt([205.96, 254.59], sketch002)
|> angledLine(angle = 0, length = 11.39, tag = $rectangleSegmentA002)
|> angledLine([0, 11.39], %, $rectangleSegmentA002)
|> angledLine([
segAng(rectangleSegmentA002) - 90,
105.26
@ -377,6 +377,7 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
editor,
toolbar,
scene,
cmdBar,
}) => {
const file = await fs.readFile(
path.resolve(
@ -392,7 +393,7 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
const sketchOnAChamfer = _sketchOnAChamfer(page, editor, toolbar, scene)
@ -422,7 +423,7 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
`@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> startProfileAt([75.8, 317.2], %)
|> angledLine(angle = 0, length = 268.43, tag = $rectangleSegmentA001)
|> angledLine([0, 268.43], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001) - 90,
217.26
@ -450,7 +451,7 @@ chamf = chamfer(
)
sketch002 = startSketchOn(extrude001, seg03)
profile001 = startProfileAt([205.96, 254.59], sketch002)
|> angledLine(angle = 0, length = 11.39, tag = $rectangleSegmentA002)
|> angledLine([0, 11.39], %, $rectangleSegmentA002)
|> angledLine([
segAng(rectangleSegmentA002) - 90,
105.26
@ -479,6 +480,7 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
await page.setBodyDimensions(viewPortSize)
await homePage.goToModelingScene()
await scene.connectionEstablished()
// Constants and locators
// These are mappings from screenspace to KCL coordinates,
@ -537,8 +539,7 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
await toolbar.startSketchPlaneSelection()
await moveToXzPlane()
await clickOnXzPlane()
// timeout wait for engine animation is unavoidable
await page.waitForTimeout(600)
await toolbar.waitUntilSketchingReady()
await editor.expectEditor.toContain(expectedCodeSnippets.sketchOnXzPlane)
})
await test.step(`Place a point a few pixels off the middle, verify it still snaps to 0,0`, async () => {
@ -580,9 +581,8 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
editor,
toolbar,
scene,
cmdBar,
}) => {
const u = await getUtils(page)
const initialCode = `closedSketch = startSketchOn(XZ)
|> circle(center = [8, 5], radius = 2)
openSketch = startSketchOn(XY)
@ -599,8 +599,6 @@ openSketch = startSketchOn(XY)
}, initialCode)
await homePage.goToModelingScene()
await u.waitForPageLoad()
await page.waitForTimeout(1000)
const pointInsideCircle = {
x: viewPortSize.width * 0.63,
@ -625,15 +623,16 @@ openSketch = startSketchOn(XY)
const exitSketch = async () => {
await test.step(`Exit sketch mode`, async () => {
await toolbar.exitSketchBtn.click()
await expect(toolbar.exitSketchBtn).not.toBeVisible()
await expect(toolbar.startSketchBtn).toBeEnabled()
})
}
await test.step(`Double-click on the closed sketch`, async () => {
await scene.settled(cmdBar)
await moveToCircle()
await page.waitForTimeout(1000)
await dblClickCircle()
await expect(toolbar.startSketchBtn).not.toBeVisible()
await page.waitForTimeout(1000)
await expect(toolbar.exitSketchBtn).toBeVisible()
await editor.expectState({
activeLines: [`|>circle(center=[8,5],radius=2)`],
@ -670,7 +669,6 @@ openSketch = startSketchOn(XY)
// There is a full execution after exiting sketch that clears the scene.
await page.waitForTimeout(500)
await dblClickOpenPath()
await expect(toolbar.startSketchBtn).not.toBeVisible()
await expect(toolbar.exitSketchBtn).toBeVisible()
// Wait for enter sketch mode to complete
await page.waitForTimeout(500)
@ -1031,6 +1029,9 @@ openSketch = startSketchOn(XY)
})
await test.step(`Go through the command bar flow`, async () => {
await toolbar.offsetPlaneButton.click()
await expect
.poll(() => page.getByText('Please select one').count())
.toBe(1)
await cmdBar.expectState({
stage: 'arguments',
currentArgKey: 'plane',
@ -1088,6 +1089,7 @@ openSketch = startSketchOn(XY)
const expectedLine = `axis=X,`
await homePage.goToModelingScene()
await scene.connectionEstablished()
await test.step(`Go through the command bar flow`, async () => {
await toolbar.helixButton.click()
@ -1106,6 +1108,7 @@ openSketch = startSketchOn(XY)
commandName: 'Helix',
})
await cmdBar.progressCmdBar()
await expect.poll(() => page.getByText('Axis').count()).toBe(6)
await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
@ -1233,6 +1236,7 @@ openSketch = startSketchOn(XY)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.settled(cmdBar)
await test.step(`Go through the command bar flow`, async () => {
await toolbar.closePane('code')
@ -1252,15 +1256,22 @@ openSketch = startSketchOn(XY)
commandName: 'Helix',
})
await cmdBar.selectOption({ name: 'Edge' }).click()
await expect
.poll(() => page.getByText('Please select one').count())
.toBe(1)
await clickOnEdge()
await page.waitForTimeout(1000)
await cmdBar.progressCmdBar()
await page.waitForTimeout(1000)
await cmdBar.argumentInput.focus()
await page.waitForTimeout(1000)
await page.keyboard.insertText('20')
await cmdBar.progressCmdBar()
await page.keyboard.insertText('0')
await cmdBar.progressCmdBar()
await page.keyboard.insertText('1')
await cmdBar.progressCmdBar()
await page.keyboard.insertText('100')
await cmdBar.expectState({
stage: 'review',
headerArguments: {
@ -1274,6 +1285,7 @@ openSketch = startSketchOn(XY)
commandName: 'Helix',
})
await cmdBar.progressCmdBar()
await page.waitForTimeout(1000)
})
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
@ -1369,7 +1381,7 @@ extrude001 = extrude(profile001, length = 100)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// One dumb hardcoded screen pixel value
const testPoint = { x: 620, y: 257 }
@ -1530,6 +1542,9 @@ extrude001 = extrude(profile001, length = 100)
if (!shouldPreselect) {
await test.step(`Go through the command bar flow without preselected sketches`, async () => {
await toolbar.loftButton.click()
await expect
.poll(() => page.getByText('Please select one').count())
.toBe(1)
await cmdBar.expectState({
stage: 'arguments',
currentArgKey: 'selection',
@ -1579,6 +1594,7 @@ extrude001 = extrude(profile001, length = 100)
page,
homePage,
scene,
cmdBar,
}) => {
const initialCode = `sketch001 = startSketchOn(XZ)
|> circle(center = [0, 0], radius = 30)
@ -1592,7 +1608,7 @@ loft001 = loft([sketch001, sketch002])
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// One dumb hardcoded screen pixel value
const testPoint = { x: 575, y: 200 }
@ -1687,7 +1703,7 @@ sketch002 = startSketchOn(XZ)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// One dumb hardcoded screen pixel value
const [clickOnSketch1] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
@ -1707,6 +1723,9 @@ sketch002 = startSketchOn(XZ)
await test.step(`Go through the command bar flow`, async () => {
await toolbar.sweepButton.click()
await expect
.poll(() => page.getByText('Please select one').count())
.toBe(1)
await cmdBar.expectState({
commandName: 'Sweep',
currentArgKey: 'target',
@ -1826,7 +1845,7 @@ sketch002 = startSketchOn(XZ)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// One dumb hardcoded screen pixel value
const testPoint = { x: 700, y: 250 }
@ -1843,6 +1862,9 @@ sketch002 = startSketchOn(XZ)
await test.step(`Go through the command bar flow and fail validation with a toast`, async () => {
await toolbar.sweepButton.click()
await expect
.poll(() => page.getByText('Please select one').count())
.toBe(1)
await cmdBar.expectState({
commandName: 'Sweep',
currentArgKey: 'target',
@ -2059,6 +2081,9 @@ extrude001 = extrude(sketch001, length = -12)
await test.step(`Open fillet UI without selecting edges`, async () => {
await page.waitForTimeout(100)
await toolbar.filletButton.click()
await expect
.poll(() => page.getByText('Please select one').count())
.toBe(1)
await cmdBar.expectState({
stage: 'arguments',
currentArgKey: 'selection',
@ -2184,6 +2209,7 @@ extrude001 = extrude(sketch001, length = -12)
homePage,
scene,
toolbar,
cmdBar,
}) => {
const initialCode = `sketch001 = startSketchOn(XY)
profile001 = circle(
@ -2200,7 +2226,7 @@ fillet001 = fillet(extrude001, radius = 5, tags = [getOppositeEdge(seg01)])
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
await test.step('Double-click in feature tree and expect error toast', async () => {
await toolbar.openPane('feature-tree')
@ -2521,7 +2547,7 @@ extrude001 = extrude(sketch001, length = -12)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
})
// Test 1: Command bar flow with preselected edges
@ -2554,6 +2580,7 @@ extrude001 = extrude(sketch001, length = -12)
stage: 'arguments',
})
await cmdBar.progressCmdBar()
await page.waitForTimeout(1000)
await cmdBar.expectState({
commandName: 'Chamfer',
highlightedHeaderArg: 'length',
@ -2565,7 +2592,10 @@ extrude001 = extrude(sketch001, length = -12)
},
stage: 'arguments',
})
await cmdBar.argumentInput.focus()
await page.waitForTimeout(1000)
await cmdBar.progressCmdBar()
await page.waitForTimeout(1000)
await cmdBar.expectState({
commandName: 'Chamfer',
headerArguments: {
@ -2649,6 +2679,9 @@ extrude001 = extrude(sketch001, length = -12)
await test.step(`Open chamfer UI without selecting edges`, async () => {
await page.waitForTimeout(100)
await toolbar.chamferButton.click()
await expect
.poll(() => page.getByText('Please select one').count())
.toBe(1)
await cmdBar.expectState({
stage: 'arguments',
currentArgKey: 'selection',
@ -2771,6 +2804,7 @@ extrude001 = extrude(sketch001, length = -12)
scene,
editor,
toolbar,
cmdBar,
}) => {
// Code samples
const initialCode = `@settings(defaultLengthUnit = in)
@ -2814,7 +2848,7 @@ chamfer04 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg02)])
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// verify modeling scene is loaded
await scene.expectPixelColor(
@ -2936,9 +2970,11 @@ extrude001 = extrude(sketch001, length = 30)
await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// One dumb hardcoded screen pixel value
const testPoint = { x: 575, y: 200 }
@ -2955,6 +2991,9 @@ extrude001 = extrude(sketch001, length = 30)
if (!shouldPreselect) {
await test.step(`Go through the command bar flow without preselected faces`, async () => {
await toolbar.shellButton.click()
await expect
.poll(() => page.getByText('Please select one').count())
.toBe(1)
await cmdBar.expectState({
stage: 'arguments',
currentArgKey: 'selection',
@ -3015,7 +3054,6 @@ extrude001 = extrude(sketch001, length = 30)
})
await test.step('Edit shell via feature tree selection works', async () => {
await toolbar.closePane('code')
await toolbar.openPane('feature-tree')
const operationButton = await toolbar.getFeatureTreeOperation(
'Shell',
@ -3044,7 +3082,6 @@ extrude001 = extrude(sketch001, length = 30)
await cmdBar.progressCmdBar()
await toolbar.closePane('feature-tree')
await scene.expectPixelColor([150, 150, 150], testPoint, 15)
await toolbar.openPane('code')
await editor.expectEditor.toContain(editedShellDeclaration)
await editor.expectState({
diagnostics: [],
@ -3079,7 +3116,7 @@ extrude001 = extrude(sketch001, length = 40)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// One dumb hardcoded screen pixel value
const testPoint = { x: 580, y: 180 }
@ -3097,6 +3134,9 @@ extrude001 = extrude(sketch001, length = 40)
await test.step(`Go through the command bar flow, selecting a wall and keeping default thickness`, async () => {
await toolbar.shellButton.click()
await expect
.poll(() => page.getByText('Please select one').count())
.toBe(1)
await cmdBar.expectState({
stage: 'arguments',
currentArgKey: 'selection',
@ -3108,6 +3148,9 @@ extrude001 = extrude(sketch001, length = 40)
highlightedHeaderArg: 'selection',
commandName: 'Shell',
})
await expect
.poll(() => page.getByText('Please select one').count())
.toBe(1)
await clickOnCap()
await page.keyboard.down('Shift')
await clickOnWall()
@ -3116,6 +3159,7 @@ extrude001 = extrude(sketch001, length = 40)
await cmdBar.progressCmdBar()
await page.waitForTimeout(500)
await cmdBar.progressCmdBar()
await page.waitForTimeout(500)
await cmdBar.expectState({
stage: 'review',
headerArguments: {
@ -3124,7 +3168,9 @@ extrude001 = extrude(sketch001, length = 40)
},
commandName: 'Shell',
})
await page.waitForTimeout(500)
await cmdBar.progressCmdBar()
await page.waitForTimeout(500)
})
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
@ -3139,7 +3185,6 @@ extrude001 = extrude(sketch001, length = 40)
})
await test.step('Edit shell via feature tree selection works', async () => {
await editor.closePane()
const operationButton = await toolbar.getFeatureTreeOperation('Shell', 0)
await operationButton.dblclick({ button: 'left' })
await cmdBar.expectState({
@ -3154,6 +3199,7 @@ extrude001 = extrude(sketch001, length = 40)
})
await page.keyboard.insertText('1')
await cmdBar.progressCmdBar()
await page.waitForTimeout(500)
await cmdBar.expectState({
stage: 'review',
headerArguments: {
@ -3164,7 +3210,6 @@ extrude001 = extrude(sketch001, length = 40)
await cmdBar.progressCmdBar()
await toolbar.closePane('feature-tree')
await scene.expectPixelColor([150, 150, 150], testPoint, 15)
await toolbar.openPane('code')
await editor.expectEditor.toContain(editedShellDeclaration)
await editor.expectState({
diagnostics: [],
@ -3218,7 +3263,7 @@ extrude002 = extrude(sketch002, length = 50)
}, initialCode)
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// One dumb hardcoded screen pixel value
const testPoint = { x: 580, y: 320 }
@ -3243,12 +3288,13 @@ extrude002 = extrude(sketch002, length = 50)
highlightedHeaderArg: 'selection',
commandName: 'Shell',
})
await expect
.poll(() => page.getByText('Please select one').count())
.toBe(1)
await clickOnCap()
await page.waitForTimeout(500)
await page.waitForTimeout(1000)
await cmdBar.progressCmdBar()
await page.waitForTimeout(500)
await cmdBar.progressCmdBar()
await page.waitForTimeout(500)
await cmdBar.expectState({
stage: 'review',
headerArguments: {
@ -3306,7 +3352,7 @@ profile001 = startProfileAt([-20, 20], sketch001)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
await toolbar.openPane('feature-tree')
// One dumb hardcoded screen pixel value
@ -3386,7 +3432,7 @@ sweep001 = sweep(sketch001, path = sketch002)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// One dumb hardcoded screen pixel value
const testPoint = { x: 500, y: 250 }
@ -3399,6 +3445,9 @@ sweep001 = sweep(sketch001, path = sketch002)
await test.step(`Go through the Shell flow and fail validation with a toast`, async () => {
await toolbar.shellButton.click()
await expect
.poll(() => page.getByText('Please select one').count())
.toBe(1)
await cmdBar.expectState({
stage: 'arguments',
currentArgKey: 'selection',
@ -3433,8 +3482,8 @@ sweep001 = sweep(sketch001, path = sketch002)
const initialCode = `
sketch001 = startSketchOn(XZ)
|> startProfileAt([-100.0, 100.0], %)
|> angledLine(angle = 0, length = 200.0, tag = $rectangleSegmentA001)
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 200, tag = $rectangleSegmentB001)
|> angledLine([0, 200.0], %, $rectangleSegmentA001)
|> angledLine([segAng(rectangleSegmentA001) - 90, 200], %, $rectangleSegmentB001)
|> angledLine([
segAng(rectangleSegmentA001),
-segLen(rectangleSegmentA001)
@ -3444,7 +3493,7 @@ segAng(rectangleSegmentA001),
extrude001 = extrude(sketch001, length = 200)
sketch002 = startSketchOn(extrude001, rectangleSegmentA001)
|> startProfileAt([-66.77, 84.81], %)
|> angledLine(angle = 180, length = 27.08, tag = $rectangleSegmentA002)
|> angledLine([180, 27.08], %, $rectangleSegmentA002)
|> angledLine([
segAng(rectangleSegmentA002) - 90,
27.8
@ -3462,12 +3511,13 @@ segAng(rectangleSegmentA002),
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// select line of code
const codeToSelecton = `segAng(rectangleSegmentA002) - 90,`
const codeToSelection = `segAng(rectangleSegmentA002) - 90,`
// revolve
await page.getByText(codeToSelecton).click()
await editor.scrollToText(codeToSelection)
await page.getByText(codeToSelection).click()
await toolbar.revolveButton.click()
await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
@ -3519,20 +3569,19 @@ segAng(rectangleSegmentA002),
toolbar,
cmdBar,
}) => {
const initialCode = `
sketch001 = startSketchOn(XZ)
|> startProfileAt([-102.57, 101.72], %)
|> angledLine(angle = 0, length = 202.6, tag = $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001) - 90,
202.6
], %, $rectangleSegmentB001)
|> angledLine([
segAng(rectangleSegmentA001),
-segLen(rectangleSegmentA001)
], %, $rectangleSegmentC001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
const initialCode = `sketch001 = startSketchOn(XZ)
|> startProfileAt([-102.57, 101.72], %)
|> angledLine([0, 202.6], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001) - 90,
202.6
], %, $rectangleSegmentB001)
|> angledLine([
segAng(rectangleSegmentA001),
-segLen(rectangleSegmentA001)
], %, $rectangleSegmentC001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
extrude001 = extrude(sketch001, length = 50)
sketch002 = startSketchOn(extrude001, rectangleSegmentA001)
|> circle(center = [-11.34, 10.0], radius = 8.69)
@ -3542,15 +3591,17 @@ sketch002 = startSketchOn(extrude001, rectangleSegmentA001)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
await scene.settled(cmdBar)
// select line of code
const codeToSelecton = `center = [-11.34, 10.0]`
const codeToSelection = `center = [-11.34, 10.0]`
// revolve
await page.getByText(codeToSelecton).click()
await editor.scrollToText(codeToSelection)
await page.getByText(codeToSelection).click()
await toolbar.revolveButton.click()
await page.getByText('Edge', { exact: true }).click()
const lineCodeToSelection = `|> angledLine(angle = 0, length = 202.6, tag = $rectangleSegmentA001)`
const lineCodeToSelection = `angledLine([0, 202.6], %, $rectangleSegmentA001)`
await page.getByText(lineCodeToSelection).click()
await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
@ -3596,6 +3647,7 @@ sketch002 = startSketchOn(extrude001, rectangleSegmentA001)
await editor.expectEditor.toContain(
newCodeToFind.replace('angle = 360', 'angle = angle001')
)
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
})
test('revolve sketch circle around line segment from startProfileAt sketch', async ({
context,
@ -3606,26 +3658,22 @@ sketch002 = startSketchOn(extrude001, rectangleSegmentA001)
toolbar,
cmdBar,
}) => {
const initialCode = `
sketch002 = startSketchOn(XY)
|> startProfileAt([-2.02, 1.79], %)
|> xLine(length = 2.6)
sketch001 = startSketchOn('-XY')
|> startProfileAt([-0.48, 1.25], %)
|> angledLine(angle = 0, length = 2.38, tag = $rectangleSegmentA001)
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 2.4, tag = $rectangleSegmentB001)
|> angledLine([
segAng(rectangleSegmentA001),
-segLen(rectangleSegmentA001)
], %, $rectangleSegmentC001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
extrude001 = extrude(sketch001, length = 5)
sketch003 = startSketchOn(extrude001, 'START')
|> circle(
center = [-0.69, 0.56],
radius = 0.28
)
const initialCode = `sketch002 = startSketchOn(XY)
|> startProfileAt([-2.02, 1.79], %)
|> xLine(length = 2.6)
sketch001 = startSketchOn(-XY)
|> startProfileAt([-0.48, 1.25], %)
|> angledLine([0, 2.38], %, $rectangleSegmentA001)
|> angledLine([segAng(rectangleSegmentA001) - 90, 2.4], %, $rectangleSegmentB001)
|> angledLine([
segAng(rectangleSegmentA001),
-segLen(rectangleSegmentA001)
], %, $rectangleSegmentC001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
extrude001 = extrude(sketch001, length = 5)
sketch003 = startSketchOn(extrude001, 'START')
|> circle(center = [-0.69, 0.56], radius = 0.28)
`
await context.addInitScript((initialCode) => {
@ -3633,15 +3681,20 @@ sketch002 = startSketchOn(extrude001, rectangleSegmentA001)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
await scene.settled(cmdBar)
// select line of code
const codeToSelecton = `center = [-0.69, 0.56]`
const codeToSelection = `center = [-0.69, 0.56]`
// revolve
await page.getByText(codeToSelecton).click()
await toolbar.revolveButton.click()
await page.waitForTimeout(1000)
await editor.scrollToText(codeToSelection)
await page.getByText(codeToSelection).click()
await expect.poll(() => page.getByText('AxisOrEdge').count()).toBe(2)
await page.getByText('Edge', { exact: true }).click()
const lineCodeToSelection = `|> xLine(length = 2.6)`
const lineCodeToSelection = `length = 2.6`
await editor.scrollToText(lineCodeToSelection)
await page.getByText(lineCodeToSelection).click()
await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
@ -3708,7 +3761,7 @@ extrude001 = extrude(profile001, length = 100)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// One dumb hardcoded screen pixel value
const testPoint = { x: 500, y: 250 }

View File

@ -83,7 +83,7 @@ test(
test(
'click help/keybindings from project page',
{ tag: '@electron' },
async ({ context, page }, testInfo) => {
async ({ scene, cmdBar, context, page }, testInfo) => {
await context.folderSetupFn(async (dir) => {
const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true })
@ -95,17 +95,11 @@ test(
await page.setBodyDimensions({ width: 1200, height: 500 })
page.on('console', console.log)
// expect to see the text bracket
await expect(page.getByText('bracket')).toBeVisible()
await page.getByText('bracket').click()
await expect(page.getByTestId('loading')).toBeAttached()
await expect(page.getByTestId('loading')).not.toBeAttached({
timeout: 20_000,
})
await scene.settled(cmdBar)
// click ? button
await page.getByTestId('help-button').click()
@ -120,7 +114,7 @@ test(
test(
'open a file in a project works and renders, open another file in different project with errors, it should clear the scene',
{ tag: '@electron' },
async ({ context, page, editor }, testInfo) => {
async ({ scene, cmdBar, context, page, editor }, testInfo) => {
await context.folderSetupFn(async (dir) => {
const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true })
@ -149,24 +143,7 @@ test(
await page.getByText('bracket').click()
await expect(page.getByTestId('loading')).toBeAttached()
await expect(page.getByTestId('loading')).not.toBeAttached({
timeout: 20_000,
})
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).toBeEnabled({
timeout: 20_000,
})
// gray at this pixel means the stream has loaded in the most
// user way we can verify it (pixel color)
await expect
.poll(() => u.getGreatestPixDiff(pointOnModel, [110, 110, 110]), {
timeout: 10_000,
})
.toBeLessThan(20)
await scene.settled(cmdBar)
})
await test.step('Clicking the logo takes us back to the projects page / home', async () => {
@ -209,7 +186,7 @@ test(
test(
'open a file in a project works and renders, open another file in different project that is empty, it should clear the scene',
{ tag: '@electron' },
async ({ context, page }, testInfo) => {
async ({ scene, cmdBar, context, page }, testInfo) => {
await context.folderSetupFn(async (dir) => {
const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true })
@ -235,24 +212,7 @@ test(
await page.getByText('bracket').click()
await expect(page.getByTestId('loading')).toBeAttached()
await expect(page.getByTestId('loading')).not.toBeAttached({
timeout: 20_000,
})
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).toBeEnabled({
timeout: 20_000,
})
// gray at this pixel means the stream has loaded in the most
// user way we can verify it (pixel color)
await expect
.poll(() => u.getGreatestPixDiff(pointOnModel, [125, 125, 125]), {
timeout: 10_000,
})
.toBeLessThan(15)
await scene.settled(cmdBar)
})
await test.step('Clicking the logo takes us back to the projects page / home', async () => {
@ -352,7 +312,7 @@ test(
test(
'open a file in a project works and renders, open another file in the same project with errors, it should clear the scene',
{ tag: '@electron' },
async ({ context, page }, testInfo) => {
async ({ scene, cmdBar, context, page }, testInfo) => {
if (runningOnWindows()) {
test.fixme(orRunWhenFullSuiteEnabled())
}
@ -380,10 +340,7 @@ test(
await page.getByText('bracket').click()
await expect(page.getByTestId('loading')).toBeAttached()
await expect(page.getByTestId('loading')).not.toBeAttached({
timeout: 20_000,
})
await scene.settled(cmdBar)
await expect(
page.getByRole('button', { name: 'Start Sketch' })
@ -443,10 +400,10 @@ test(
await expect(page.getByText('broken-code')).toBeVisible()
await page.getByText('broken-code').click()
// Gotcha: You can not use scene.waitForExecutionDone() since the KCL code is going to fail
await expect(page.getByTestId('loading')).not.toBeAttached({
timeout: 20_000,
})
// Gotcha: You can not use scene.settled() since the KCL code is going to fail
await expect(
page.getByTestId('model-state-indicator-playing')
).toBeAttached()
// Gotcha: Scroll to the text content in code mirror because CodeMirror lazy loads DOM content
await editor.scrollToText(
@ -469,7 +426,7 @@ test.describe('Can export from electron app', () => {
test(
`Can export using ${method}`,
{ tag: ['@electron', '@skipLocalEngine'] },
async ({ context, page, tronApp }, testInfo) => {
async ({ scene, cmdBar, context, page, tronApp }, testInfo) => {
if (!tronApp) {
fail()
}
@ -499,10 +456,7 @@ test.describe('Can export from electron app', () => {
await page.getByText('bracket').click()
await expect(page.getByTestId('loading')).toBeAttached()
await expect(page.getByTestId('loading')).not.toBeAttached({
timeout: 20_000,
})
await scene.settled(cmdBar)
await expect(
page.getByRole('button', { name: 'Start Sketch' })
@ -812,7 +766,7 @@ test.describe(`Project management commands`, () => {
test(
`Rename from project page`,
{ tag: '@electron' },
async ({ context, page }, testInfo) => {
async ({ context, page, scene, cmdBar }, testInfo) => {
const projectName = `my_project_to_rename`
await context.folderSetupFn(async (dir) => {
await fsp.mkdir(`${dir}/${projectName}`, { recursive: true })
@ -821,7 +775,6 @@ test.describe(`Project management commands`, () => {
`${dir}/${projectName}/main.kcl`
)
})
const u = await getUtils(page)
// Constants and locators
const projectHomeLink = page.getByTestId('project-link')
@ -843,7 +796,7 @@ test.describe(`Project management commands`, () => {
page.on('console', console.log)
await projectHomeLink.click()
await u.waitForPageLoad()
await scene.settled(cmdBar)
})
await test.step(`Run rename command via command palette`, async () => {
@ -882,7 +835,6 @@ test.describe(`Project management commands`, () => {
`${dir}/${projectName}/main.kcl`
)
})
const u = await getUtils(page)
// Constants and locators
const projectHomeLink = page.getByTestId('project-link')
@ -900,9 +852,9 @@ test.describe(`Project management commands`, () => {
await page.setBodyDimensions({ width: 1200, height: 500 })
page.on('console', console.log)
await page.waitForTimeout(3000)
await projectHomeLink.click()
await u.waitForPageLoad()
await scene.connectionEstablished()
await scene.settled(cmdBar)
})
@ -926,7 +878,7 @@ test.describe(`Project management commands`, () => {
test(
`Rename from home page`,
{ tag: '@electron' },
async ({ context, page, homePage }, testInfo) => {
async ({ context, page, homePage, scene, cmdBar }, testInfo) => {
const projectName = `my_project_to_rename`
await context.folderSetupFn(async (dir) => {
await fsp.mkdir(`${dir}/${projectName}`, { recursive: true })
@ -982,7 +934,7 @@ test.describe(`Project management commands`, () => {
test(
`Delete from home page`,
{ tag: '@electron' },
async ({ context, page }, testInfo) => {
async ({ context, page, scene, cmdBar }, testInfo) => {
const projectName = `my_project_to_delete`
await context.folderSetupFn(async (dir) => {
await fsp.mkdir(`${dir}/${projectName}`, { recursive: true })
@ -1033,6 +985,7 @@ test.describe(`Project management commands`, () => {
homePage,
toolbar,
cmdBar,
scene,
}) => {
const projectName = 'test-project'
await test.step(`Setup`, async () => {
@ -1072,10 +1025,11 @@ test.describe(`Project management commands`, () => {
})
await cmdBar.argumentInput.fill(projectName)
await cmdBar.progressCmdBar()
await scene.settled(cmdBar)
await toolbar.logoLink.click()
})
await test.step(`Check the project was created with a non-colliding name`, async () => {
await toolbar.logoLink.click()
await homePage.expectState({
projectCards: [
{
@ -1106,10 +1060,11 @@ test.describe(`Project management commands`, () => {
})
await cmdBar.argumentInput.fill(projectName)
await cmdBar.progressCmdBar()
await scene.settled(cmdBar)
await toolbar.logoLink.click()
})
await test.step(`Check the second project was created with a non-colliding name`, async () => {
await toolbar.logoLink.click()
await homePage.expectState({
projectCards: [
{
@ -1195,7 +1150,7 @@ test(
test(
'Nested directories in project without main.kcl do not create main.kcl',
{ tag: '@electron' },
async ({ context, page }, testInfo) => {
async ({ scene, cmdBar, context, page }, testInfo) => {
let testDir: string | undefined
await context.folderSetupFn(async (dir) => {
await fsp.mkdir(path.join(dir, 'router-template-slate', 'nested'), {
@ -1218,10 +1173,7 @@ test(
await test.step('Open the project', async () => {
await page.getByText('router-template-slate').click()
await expect(page.getByTestId('loading')).toBeAttached()
await expect(page.getByTestId('loading')).not.toBeAttached({
timeout: 20_000,
})
await scene.settled(cmdBar)
// It actually loads.
await expect(u.codeLocator).toContainText('mounting bracket')
@ -1334,7 +1286,7 @@ test(
test(
'Can load a file with CRLF line endings',
{ tag: '@electron' },
async ({ context, page }, testInfo) => {
async ({ context, page, scene, cmdBar }, testInfo) => {
if (runningOnWindows()) {
test.fixme(orRunWhenFullSuiteEnabled())
}
@ -1357,13 +1309,8 @@ test(
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 })
page.on('console', console.log)
await page.getByText('router-template-slate').click()
await expect(page.getByTestId('loading')).toBeAttached()
await expect(page.getByTestId('loading')).not.toBeAttached({
timeout: 20_000,
})
await scene.settled(cmdBar)
await expect(u.codeLocator).toContainText('routerDiameter')
await expect(u.codeLocator).toContainText('templateGap')
@ -1578,7 +1525,7 @@ extrude001 = extrude(sketch001, length = 200)`)
test(
'Opening a project should successfully load the stream, (regression test that this also works when switching between projects)',
{ tag: '@electron' },
async ({ context, page, cmdBar, homePage }, testInfo) => {
async ({ context, page, cmdBar, homePage, scene }, testInfo) => {
await context.folderSetupFn(async (dir) => {
await fsp.mkdir(path.join(dir, 'router-template-slate'), {
recursive: true,
@ -1607,13 +1554,10 @@ test(
path.join(dir, 'bracket', 'main.kcl')
)
})
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 })
page.on('console', console.log)
const pointOnModel = { x: 630, y: 280 }
await test.step('Opening the bracket project via command palette should load the stream', async () => {
await homePage.expectState({
projectCards: [
@ -1647,15 +1591,7 @@ test(
stage: 'commandBarClosed',
})
await u.waitForPageLoad()
// gray at this pixel means the stream has loaded in the most
// user way we can verify it (pixel color)
await expect
.poll(() => u.getGreatestPixDiff(pointOnModel, [85, 85, 85]), {
timeout: 10_000,
})
.toBeLessThan(15)
await scene.settled(cmdBar)
})
await test.step('Clicking the logo takes us back to the projects page / home', async () => {
@ -1672,15 +1608,7 @@ test(
await page.getByText('router-template-slate').click()
await u.waitForPageLoad()
// gray at this pixel means the stream has loaded in the most
// user way we can verify it (pixel color)
await expect
.poll(() => u.getGreatestPixDiff(pointOnModel, [143, 143, 143]), {
timeout: 10_000,
})
.toBeLessThan(15)
await scene.settled(cmdBar)
})
await test.step('The projects on the home page should still be normal', async () => {
@ -1733,8 +1661,6 @@ test(
})
await page.setBodyDimensions({ width: 1200, height: 500 })
page.on('console', console.log)
// we'll grab this from the settings on screen before we switch
let originalProjectDirName: string
const newProjectDirName = testInfo.outputPath(
@ -1875,7 +1801,7 @@ test(
test(
'file pane is scrollable when there are many files',
{ tag: '@electron' },
async ({ context, page }, testInfo) => {
async ({ scene, cmdBar, context, page }, testInfo) => {
await context.folderSetupFn(async (dir) => {
const testDir = path.join(dir, 'testProject')
await fsp.mkdir(testDir, { recursive: true })
@ -1954,10 +1880,8 @@ test(
await test.step('setup, open file pane', async () => {
await page.getByText('testProject').click()
await expect(page.getByTestId('loading')).toBeAttached()
await expect(page.getByTestId('loading')).not.toBeAttached({
timeout: 20_000,
})
await scene.settled(cmdBar)
await page.getByTestId('files-pane-button').click()
})

View File

@ -41,7 +41,7 @@ sketch002 = startSketchOn(XZ)
extrude002 = extrude(sketch002, length = 50)
sketch003 = startSketchOn(XY)
|> startProfileAt([52.92, 157.81], %)
|> angledLine(angle = 0, length = 176.4, tag = $rectangleSegmentA001)
|> angledLine([0, 176.4], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001) - 90,
53.4
@ -63,7 +63,7 @@ test.describe('edit with AI example snapshots', () => {
localStorage.setItem('persistCode', file)
}, file)
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
const body1CapCoords = { x: 571, y: 351 }
const [clickBody1Cap] = scene.makeMouseHelpers(

View File

@ -22,7 +22,7 @@ sketch002 = startSketchOn(XZ)
extrude002 = extrude(sketch002, length = 50)
sketch003 = startSketchOn(XY)
|> startProfileAt([52.92, 157.81], %)
|> angledLine(angle = 0, length = 176.4, tag = $rectangleSegmentA001)
|> angledLine([0, 176.4], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001) - 90,
53.4
@ -61,7 +61,7 @@ test.describe('Prompt-to-edit tests', { tag: '@skipWin' }, () => {
localStorage.setItem('persistCode', file)
}, file)
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
const body1CapCoords = { x: 571, y: 311 }
const greenCheckCoords = { x: 565, y: 305 }
@ -156,7 +156,7 @@ test.describe('Prompt-to-edit tests', { tag: '@skipWin' }, () => {
localStorage.setItem('persistCode', file)
}, file)
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
const body1CapCoords = { x: 571, y: 311 }
const [clickBody1Cap] = scene.makeMouseHelpers(
@ -212,7 +212,7 @@ test.describe('Prompt-to-edit tests', { tag: '@skipWin' }, () => {
localStorage.setItem('persistCode', file)
}, file)
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
const submittingToast = page.getByText('Submitting to Text-to-CAD API...')
const successToast = page.getByText('Prompt to edit successful')
@ -281,7 +281,7 @@ test.describe('Prompt-to-edit tests', { tag: '@skipWin' }, () => {
localStorage.setItem('persistCode', file)
}, file)
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
const submittingToast = page.getByText('Submitting to Text-to-CAD API...')
const successToast = page.getByText('Prompt to edit successful')

View File

@ -68,7 +68,7 @@ test.describe('Regression tests', { tag: ['@skipWin'] }, () => {
'persistCode',
`sketch001 = startSketchOn(XY)
|> startProfileAt([82.33, 238.21], %)
|> angledLine(angle = 0, length = 288.63, tag = $rectangleSegmentA001)
|> angledLine([0, 288.63], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001) - 90,
197.97
@ -257,7 +257,7 @@ extrude001 = extrude(sketch001, length = 50)
'persistCode',
`exampleSketch = startSketchOn("XZ")
|> startProfileAt([0, 0], %)
|> angledLine(angle = 50, length = 45 )
|> angledLine({ angle: 50, length: 45 }, %)
|> yLine(endAbsolute = 0)
|> close()
|>
@ -313,7 +313,7 @@ extrude001 = extrude(sketch001, length = 50)
await expect(page.locator('.cm-content'))
.toContainText(`exampleSketch = startSketchOn("XZ")
|> startProfileAt([0, 0], %)
|> angledLine(angle = 50, length = 45 )
|> angledLine({ angle: 50, length: 45 }, %)
|> yLine(endAbsolute = 0)
|> close()
@ -689,6 +689,7 @@ extrude002 = extrude(profile002, length = 150)
homePage,
scene,
toolbar,
viewport,
}) => {
await context.folderSetupFn(async (dir) => {
const legoDir = path.join(dir, 'lego')
@ -703,8 +704,8 @@ extrude002 = extrude(profile002, length = 150)
await homePage.openProject('lego')
await toolbar.closePane('code')
})
await test.step(`Waiting for the loading spinner to disappear`, async () => {
await scene.loadingIndicator.waitFor({ state: 'detached' })
await test.step(`Waiting for scene to settle`, async () => {
await scene.connectionEstablished()
})
await test.step(`The part should start loading quickly, not waiting until execution is complete`, async () => {
// TODO: use the viewport size to pick the center point, but the `viewport` fixture's values were wrong.
@ -762,7 +763,7 @@ plane002 = offsetPlane(XZ, offset = -2 * x)`
)
})
await homePage.openProject('test-sample')
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
await expect(toolbar.startSketchBtn).toBeEnabled({ timeout: 20_000 })
const operationButton = await toolbar.getFeatureTreeOperation(
'Offset Plane',

View File

@ -22,6 +22,7 @@ test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
context,
homePage,
scene,
cmdBar,
}) => {
const u = await getUtils(page)
const selectionsSnippets = {
@ -82,7 +83,7 @@ test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// wait for execution done
await u.openDebugPanel()
@ -108,6 +109,7 @@ test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
page,
scene,
homePage,
cmdBar,
}) => {
const u = await getUtils(page)
await page.addInitScript(async () => {
@ -122,7 +124,7 @@ sketch001 = startSketchOn(XZ)
})
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
await scene.expectPixelColor(TEST_COLORS.WHITE, { x: 587, y: 270 }, 15)
@ -673,6 +675,7 @@ sketch001 = startSketchOn(XZ)
homePage,
scene,
editor,
cmdBar,
}) => {
const u = await getUtils(page)
await page.addInitScript(async () => {
@ -689,7 +692,7 @@ sketch001 = startSketchOn(XZ)
})
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
await expect(
page.getByRole('button', { name: 'Start Sketch' })
@ -1614,7 +1617,7 @@ profile002 = startProfileAt([117.2, 56.08], sketch001)
test(
`snapToProfile start only works for current profile`,
{ tag: ['@skipWin'] },
async ({ context, page, scene, toolbar, editor, homePage }) => {
async ({ context, page, scene, toolbar, editor, homePage, cmdBar }) => {
// We seed the scene with a single offset plane
await context.addInitScript(() => {
localStorage.setItem(
@ -1630,6 +1633,8 @@ profile003 = startProfileAt([206.63, -56.73], sketch001)
})
await homePage.goToModelingScene()
await scene.settled(cmdBar)
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).not.toBeDisabled()
@ -1651,9 +1656,13 @@ profile003 = startProfileAt([206.63, -56.73], sketch001)
const codeFromTangentialArc = ` |> tangentialArcTo([39.49, 88.22], %)`
await test.step('check that tangential tool does not snap to other profile starts', async () => {
await toolbar.tangentialArcBtn.click()
await page.waitForTimeout(1000)
await endOfLowerSegMove()
await page.waitForTimeout(1000)
await endOfLowerSegClick()
await page.waitForTimeout(1000)
await profileStartOfHigherSegClick()
await page.waitForTimeout(1000)
await editor.expectEditor.toContain(codeFromTangentialArc)
await editor.expectEditor.not.toContain(
`[profileStartX(%), profileStartY(%)]`
@ -1968,8 +1977,8 @@ profile003 = startProfileAt([206.63, -56.73], sketch001)
)
await crnRect1point2()
await editor.expectEditor.toContain(
`|> angledLine(angle = 0, length = 2.37, tag = $rectangleSegmentA001)
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 7.8)
`|> angledLine([0, 2.37], %, $rectangleSegmentA001)
|> angledLine([segAng(rectangleSegmentA001) - 90, 7.8], %)
|> angledLine([
segAng(rectangleSegmentA001),
-segLen(rectangleSegmentA001)
@ -1986,7 +1995,7 @@ profile003 = startProfileAt([206.63, -56.73], sketch001)
await crnRect2point2()
await page.waitForTimeout(300)
await editor.expectEditor.toContain(
`|> angledLine(angle = 0, length = 5.49, tag = $rectangleSegmentA002)
`|> angledLine([0, 5.49], %, $rectangleSegmentA002)
|> angledLine([
segAng(rectangleSegmentA002) - 90,
4.14
@ -2011,7 +2020,7 @@ profile003 = startProfileAt([206.63, -56.73], sketch001)
await cntrRect1point2()
await page.waitForTimeout(300)
await editor.expectEditor.toContain(
`|> angledLine(angle = 0, length = 7.06, tag = $rectangleSegmentA003)
`|> angledLine([0, 7.06], %, $rectangleSegmentA003)
|> angledLine([
segAng(rectangleSegmentA003) + 90,
4.34
@ -2033,7 +2042,7 @@ profile003 = startProfileAt([206.63, -56.73], sketch001)
await cntrRect2point2()
await page.waitForTimeout(300)
await editor.expectEditor.toContain(
`|> angledLine(angle = 0, length = 3.12, tag = $rectangleSegmentA004)
`|> angledLine([0, 3.12], %, $rectangleSegmentA004)
|> angledLine([
segAng(rectangleSegmentA004) + 90,
6.24
@ -2195,7 +2204,7 @@ profile001 = startProfileAt([6.24, 4.54], sketch001)
|> line(end = [8.61, 0.74])
|> line(end = [10.99, -5.22])
profile002 = startProfileAt([11.19, 5.02], sketch001)
|> angledLine(angle = 0, length = 10.78, tag = $rectangleSegmentA001)
|> angledLine([0, 10.78], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001) - 90,
4.14
@ -2242,8 +2251,9 @@ profile004 = circleThreePoint(sketch001, p1 = [13.44, -6.8], p2 = [13.39, -2.07]
await test.step('enter sketch and setup', async () => {
await moveToClearToolBarPopover()
await page.waitForTimeout(1000)
await pointOnSegment({ shouldDbClick: true })
await page.waitForTimeout(600)
await page.waitForTimeout(2000)
await toolbar.lineBtn.click()
await page.waitForTimeout(100)
@ -2272,7 +2282,7 @@ profile004 = circleThreePoint(sketch001, p1 = [13.44, -6.8], p2 = [13.39, -2.07]
await rectDragTo()
await page.mouse.up()
await editor.expectEditor.toContain(
`angledLine(angle = -7, length = 10.27, tag = $rectangleSegmentA001)`
`angledLine([-7, 10.27], %, $rectangleSegmentA001)`
)
})
@ -2312,7 +2322,7 @@ profile004 = circleThreePoint(sketch001, p1 = [13.44, -6.8], p2 = [13.39, -2.07]
await page.waitForTimeout(100)
await rectEnd()
await editor.expectEditor.toContain(
`|> angledLine(angle = 180, length = 1.97, tag = $rectangleSegmentA002)
`|> angledLine([180, 1.97], %, $rectangleSegmentA002)
|> angledLine([
segAng(rectangleSegmentA002) + 90,
3.89
@ -2341,7 +2351,7 @@ profile001 = startProfileAt([6.24, 4.54], sketch001)
|> line(end = [8.61, 0.74])
|> line(end = [10.99, -5.22])
profile002 = startProfileAt([11.19, 5.02], sketch001)
|> angledLine(angle = 0, length = 10.78, tag = $rectangleSegmentA001)
|> angledLine([0, 10.78], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001) - 90,
4.14
@ -2359,7 +2369,7 @@ profile003 = circle(sketch001, center = [6.92, -4.2], radius = 3.16)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).not.toBeDisabled()
@ -2450,7 +2460,7 @@ profile001 = startProfileAt([-63.43, 193.08], sketch001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
profile003 = startProfileAt([16.79, 38.24], sketch001)
|> angledLine(angle = 0, length = 182.82, tag = $rectangleSegmentA001)
|> angledLine([0, 182.82], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001) - 90,
105.71
@ -2674,7 +2684,7 @@ profile002 = startProfileAt([0.75, 13.46], sketch002)
|> line(end = [4.52, 3.79])
|> line(end = [5.98, -2.81])
profile003 = startProfileAt([3.19, 13.3], sketch002)
|> angledLine(angle = 0, length = 6.64, tag = $rectangleSegmentA001)
|> angledLine([0, 6.64], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001) - 90,
2.81
@ -2722,7 +2732,7 @@ profile010 = circle(
radius = 2.67
)
profile011 = startProfileAt([5.07, -6.39], sketch003)
|> angledLine(angle = 0, length = 4.54, tag = $rectangleSegmentA002)
|> angledLine([0, 4.54], %, $rectangleSegmentA002)
|> angledLine([
segAng(rectangleSegmentA002) - 90,
4.17
@ -2879,7 +2889,7 @@ loft([profile001, profile002])
)
await rect1Crn2()
await editor.expectEditor.toContain(
`angledLine(angle = 0, length = 113.01, tag = $rectangleSegmentA001)`
`angledLine([0, 113.01], %, $rectangleSegmentA001)`
)
}
)
@ -2950,7 +2960,7 @@ loft([profile001, profile002])
)
await rect1Crn2()
await editor.expectEditor.toContain(
`angledLine(angle = 0, length = 106.42], tag = $rectangleSegmentA001)`
`angledLine([0, 106.42], %, $rectangleSegmentA001)`
)
await page.waitForTimeout(100)
})
@ -2965,6 +2975,7 @@ test.describe(`Click based selection don't brick the app when clicked out of ran
toolbar,
editor,
homePage,
cmdBar,
}) => {
// We seed the scene with a single offset plane
await context.addInitScript(() => {
@ -2982,7 +2993,7 @@ test.describe(`Click based selection don't brick the app when clicked out of ran
})
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
await test.step(`format the code`, async () => {
// doesn't contain condensed version
@ -3047,6 +3058,7 @@ test.describe('Redirecting to home page and back to the original file should cle
toolbar,
editor,
homePage,
cmdBar,
}) => {
// We seed the scene with a single offset plane
await context.addInitScript(() => {
@ -3059,7 +3071,7 @@ test.describe('Redirecting to home page and back to the original file should cle
)
})
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
const [objClick] = scene.makeMouseHelpers(634, 274)
await objClick()

View File

@ -81,7 +81,7 @@ part001 = startSketchOn(-XZ)
offset = -armThick,
intersectTag = seg04
}, %)
|> angledLine(angle = segAng(seg04, %) + 180, endAbsoluteY = turns::ZERO)
|> angledLineToY([segAng(seg04, %) + 180, turns::ZERO], %)
|> angledLineToY({
angle = -bottomAng,
to = -totalHeightHalf - armThick,
@ -93,7 +93,7 @@ part001 = startSketchOn(-XZ)
offset = -armThick,
intersectTag = seg02
}, %)
|> angledLine(angle = segAng(seg02, %) + 180, endAbsoluteY = -baseHeight)
|> angledLineToY([segAng(seg02, %) + 180, -baseHeight], %)
|> xLine(endAbsolute = turns::ZERO)
|> close()
|> extrude(length = 4)`
@ -103,7 +103,6 @@ part001 = startSketchOn(-XZ)
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
await scene.settled(cmdBar)
const axisDirectionPair: Models['AxisDirectionPair_type'] = {
@ -369,7 +368,6 @@ const extrudeDefaultPlane = async (
await page.setViewportSize({ width: 1200, height: 500 })
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
await scene.settled(cmdBar)
await expect(page).toHaveScreenshot({
@ -421,8 +419,6 @@ test(
const PUR = 400 / 37.5 //pixeltoUnitRatio
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
const startXPx = 600
const [endOfTangentClk, endOfTangentMv] = scene.makeMouseHelpers(
startXPx + PUR * 30,
@ -551,8 +547,6 @@ test(
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
// click on "Start Sketch" button
await u.doAndWaitForImageDiff(
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
@ -598,8 +592,6 @@ test(
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
await u.doAndWaitForImageDiff(
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
200
@ -650,8 +642,6 @@ test.describe(
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
await u.doAndWaitForImageDiff(
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
200
@ -744,7 +734,6 @@ test.describe(
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
await scene.settled(cmdBar)
await u.doAndWaitForImageDiff(
@ -846,7 +835,6 @@ part002 = startSketchOn(part001, seg01)
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
await scene.settled(cmdBar)
// Wait for the second extrusion to appear
@ -902,7 +890,6 @@ test(
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
await scene.settled(cmdBar)
// Wait for the second extrusion to appear
@ -943,7 +930,6 @@ test(
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
await scene.settled(cmdBar)
// Wait for the second extrusion to appear
@ -976,7 +962,6 @@ test.describe('Grid visibility', { tag: '@snapshot' }, () => {
await page.goto('/')
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
await scene.settled(cmdBar)
await u.closeKclCodePanel()
@ -1041,7 +1026,6 @@ test.describe('Grid visibility', { tag: '@snapshot' }, () => {
await page.goto('/')
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
await scene.settled(cmdBar)
await u.closeKclCodePanel()
@ -1086,7 +1070,6 @@ test.describe('Grid visibility', { tag: '@snapshot' }, () => {
await page.goto('/')
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
await scene.settled(cmdBar)
await u.closeKclCodePanel()
@ -1205,7 +1188,6 @@ sweepSketch = startSketchOn(XY)
await page.setViewportSize({ width: 1200, height: 1000 })
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
await scene.settled(cmdBar)
await expect(page, 'expect small color widget').toHaveScreenshot({
@ -1255,7 +1237,6 @@ sweepSketch = startSketchOn(XY)
await page.setViewportSize({ width: 1200, height: 1000 })
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
await scene.settled(cmdBar)
await expect(page.locator('.cm-css-color-picker-wrapper')).toBeVisible()

View File

@ -1,5 +1,5 @@
{
"original_source_code": "sketch001 = startSketchOn(XZ)\nprofile001 = startProfileAt([57.81, 250.51], sketch001)\n |> line(end = [121.13, 56.63], tag = $seg02)\n |> line(end = [83.37, -34.61], tag = $seg01)\n |> line(end = [19.66, -116.4])\n |> line(end = [-221.8, -41.69])\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\nextrude001 = extrude(profile001, length = 200)\nsketch002 = startSketchOn('XZ')\n |> startProfileAt([-73.64, -42.89], %)\n |> xLine(length = 173.71)\n |> line(end = [-22.12, -94.4])\n |> xLine(length = -156.98)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\nextrude002 = extrude(sketch002, length = 50)\nsketch003 = startSketchOn(XY)\n |> startProfileAt([52.92, 157.81], %)\n |> angledLine(angle = 0, length = 176.4, tag = $rectangleSegmentA001)\n |> angledLine(angle = segAng(rectangleSegmentA001) - 90,\n length = 53.4\n ], tag = $rectangleSegmentB001)\n |> angledLine(angle = segAng(rectangleSegmentA001),\n length = -segLen(rectangleSegmentA001)\n tag = $rectangleSegmentC001)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\nextrude003 = extrude(sketch003, length = 20)\n",
"original_source_code": "sketch001 = startSketchOn('XZ')\nprofile001 = startProfileAt([57.81, 250.51], sketch001)\n |> line(end = [121.13, 56.63], tag = $seg02)\n |> line(end = [83.37, -34.61], tag = $seg01)\n |> line(end = [19.66, -116.4])\n |> line(end = [-221.8, -41.69])\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\nextrude001 = extrude(profile001, length = 200)\nsketch002 = startSketchOn('XZ')\n |> startProfileAt([-73.64, -42.89], %)\n |> xLine(length = 173.71)\n |> line(end = [-22.12, -94.4])\n |> xLine(length = -156.98)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\nextrude002 = extrude(sketch002, length = 50)\nsketch003 = startSketchOn(XY)\n |> startProfileAt([52.92, 157.81], %)\n |> angledLine([0, 176.4], %, $rectangleSegmentA001)\n |> angledLine([\n segAng(rectangleSegmentA001) - 90,\n 53.4\n ], %, $rectangleSegmentB001)\n |> angledLine([\n segAng(rectangleSegmentA001),\n -segLen(rectangleSegmentA001)\n ], %, $rectangleSegmentC001)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\nextrude003 = extrude(sketch003, length = 20)\n",
"prompt": "make this neon green please, use #39FF14",
"source_ranges": [
{

View File

@ -80,19 +80,18 @@ export const TEST_SETTINGS_CORRUPTED = {
},
} satisfies Partial<SaveSettingsPayload>
export const TEST_CODE_GIZMO = `@settings(defaultLengthUnit = in)
part001 = startSketchOn(XZ)
export const TEST_CODE_GIZMO = `part001 = startSketchOn(XZ)
|> startProfileAt([20, 0], %)
|> line(end = [7.13, 4 + 0])
|> angledLine(angle = 3 + 0, length = 3.14 + 0 )
|> angledLine({ angle: 3 + 0, length: 3.14 + 0 }, %)
|> line(endAbsolute = [20.14 + 0, -0.14 + 0])
|> xLine(endAbsolute = 29 + 0)
|> yLine(length = -3.14 + 0, tag = $a)
|> xLine(length = 1.63)
|> angledLine(angle = 3 + 0, lengthX = 3.14 )
|> angledLine(angle = 30, lengthY = 3 + 0 )
|> angledLine(angle = 22.14 + 0, endAbsoluteX = 12)
|> angledLine(angle = 30, endAbsoluteY = 11.14)
|> 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,
intersectTag: a,

View File

@ -89,7 +89,7 @@ test.describe('Test network and connection issues', () => {
test(
'Engine disconnect & reconnect in sketch mode',
{ tag: '@skipLocalEngine' },
async ({ page, homePage, toolbar }) => {
async ({ page, homePage, toolbar, scene, cmdBar }) => {
test.fixme(orRunWhenFullSuiteEnabled())
const networkToggle = page.getByTestId('network-toggle')
@ -169,7 +169,7 @@ test.describe('Test network and connection issues', () => {
// Expect the network to be up
await expect(networkToggle).toContainText('Connected')
await expect(page.getByTestId('loading-stream')).not.toBeAttached()
await scene.settled(cmdBar)
// Click off the code pane.
await page.mouse.click(100, 100)

View File

@ -74,7 +74,10 @@ async function waitForPageLoadWithRetry(page: Page) {
await expect(async () => {
await page.goto('/')
const errorMessage = 'App failed to load - 🔃 Retrying ...'
await expect(page.getByTestId('loading'), errorMessage).not.toBeAttached({
await expect(
page.getByTestId('model-state-indicator-playing'),
errorMessage
).toBeAttached({
timeout: 20_000,
})
@ -87,9 +90,10 @@ async function waitForPageLoadWithRetry(page: Page) {
}).toPass({ timeout: 70_000, intervals: [1_000] })
}
// lee: This needs to be replaced by scene.settled() eventually.
async function waitForPageLoad(page: Page) {
// wait for all spinners to be gone
await expect(page.getByTestId('loading')).not.toBeAttached({
await expect(page.getByTestId('model-state-indicator-playing')).toBeVisible({
timeout: 20_000,
})
@ -871,9 +875,10 @@ export async function tearDown(page: Page, testInfo: TestInfo) {
export async function setup(
context: BrowserContext,
page: Page,
testDir: string,
testInfo?: TestInfo
) {
await context.addInitScript(
await page.addInitScript(
async ({
token,
settingsKey,
@ -914,7 +919,7 @@ export async function setup(
},
}),
IS_PLAYWRIGHT_KEY,
PLAYWRIGHT_TEST_DIR: TEST_SETTINGS.project?.directory || '',
PLAYWRIGHT_TEST_DIR: testDir,
PERSIST_MODELING_CONTEXT,
}
)
@ -934,7 +939,7 @@ export async function setup(
await page.emulateMedia({ reducedMotion: 'reduce' })
// Trigger a navigation, since loading file:// doesn't.
// await page.reload()
await page.reload()
}
function failOnConsoleErrors(page: Page, testInfo?: TestInfo) {

View File

@ -5,12 +5,18 @@ import { getUtils, orRunWhenFullSuiteEnabled } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Testing Camera Movement', { tag: ['@skipWin'] }, () => {
test('Can move camera reliably', async ({ page, context, homePage }) => {
test('Can move camera reliably', async ({
page,
context,
homePage,
scene,
}) => {
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.connectionEstablished()
await u.openAndClearDebugPanel()
await u.closeKclCodePanel()

View File

@ -58,7 +58,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
.click()
await expect(page.locator('.cm-content')).toHaveText(
`length001 = 20sketch001 = startSketchOn(XY) |> startProfileAt([-10, -10], %) |> line(end = [20, 0]) |> angledLine(angle = 90, length = length001) |> xLine(length = -20)`
`length001 = 20sketch001 = startSketchOn(XY) |> startProfileAt([-10, -10], %) |> line(end = [20, 0]) |> angledLine([90, length001], %) |> xLine(length = -20)`
)
// Make sure we didn't pop out of sketch mode.
@ -77,7 +77,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
})
.toBe(false)
})
test(`Remove constraints`, async ({ page, homePage }) => {
test(`Remove constraints`, async ({ page, homePage, scene, cmdBar }) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
@ -87,7 +87,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|> startProfileAt([-7.54, -26.74], %)
|> line(end = [74.36, 130.4], tag = $seg01)
|> line(end = [78.92, -120.11])
|> angledLine(angle = segAng(seg01), length = yo)
|> angledLine([segAng(seg01), yo], %)
|> line(end = [41.19, 58.97 + 5])
part002 = startSketchOn(XZ)
|> startProfileAt([299.05, 120], %)
@ -101,7 +101,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.settled(cmdBar)
await page.getByText('line(end = [74.36, 130.4], tag = $seg01)').click()
await page.getByRole('button', { name: 'Edit Sketch' }).click()
@ -142,7 +142,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
},
] as const
for (const { testName, offset } of cases) {
test(`${testName}`, async ({ page, homePage }) => {
test(`${testName}`, async ({ page, homePage, scene, cmdBar }) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
@ -152,7 +152,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|> startProfileAt([-7.54, -26.74], %)
|> line(end = [74.36, 130.4], tag = $seg01)
|> line(end = [78.92, -120.11])
|> angledLine(angle = segAng(seg01), length = 78.33)
|> angledLine([segAng(seg01), 78.33], %)
|> line(end = [51.19, 48.97])
part002 = startSketchOn(XZ)
|> startProfileAt([299.05, 231.45], %)
@ -166,7 +166,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.settled(cmdBar)
await page.getByText('line(end = [74.36, 130.4], tag = $seg01)').click()
await page.getByRole('button', { name: 'Edit Sketch' }).click()
@ -250,7 +250,12 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
},
] as const
for (const { testName, value, constraint } of cases) {
test(`${constraint} - ${testName}`, async ({ page, homePage }) => {
test(`${constraint} - ${testName}`, async ({
page,
homePage,
scene,
cmdBar,
}) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
@ -274,7 +279,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.settled(cmdBar)
await page.getByText('line(end = [74.36, 130.4])').click()
await page.getByRole('button', { name: 'Edit Sketch' }).click()
@ -361,7 +366,12 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
},
] as const
for (const { testName, addVariable, value, constraint } of cases) {
test(`${constraint} - ${testName}`, async ({ page, homePage }) => {
test(`${constraint} - ${testName}`, async ({
page,
homePage,
scene,
cmdBar,
}) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
@ -385,7 +395,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.settled(cmdBar)
await page.getByText('line(end = [74.36, 130.4])').click()
await page.getByRole('button', { name: 'Edit Sketch' }).click()
@ -475,7 +485,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
},
] as const
for (const { testName, addVariable, value, axisSelect } of cases) {
test(`${testName}`, async ({ page, homePage }) => {
test(`${testName}`, async ({ page, homePage, scene, cmdBar }) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
@ -499,7 +509,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.settled(cmdBar)
await page.getByText('line(end = [74.36, 130.4])').click()
await page.getByRole('button', { name: 'Edit Sketch' }).click()
@ -542,7 +552,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
// checking activeLines assures the cursors are where they should be
const codeAfter = [
'|> line(end = [74.36, 130.4], tag = $seg01)',
`|> angledLine(angle = ${value}, length = 78.33)`,
`|> angledLine([${value}, 78.33], %)`,
]
if (axisSelect) codeAfter.shift()
@ -578,7 +588,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
},
] as const
for (const { testName, addVariable, value, constraint } of cases) {
test(`${testName}`, async ({ page, homePage }) => {
test(`${testName}`, async ({ page, homePage, scene, cmdBar }) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
@ -602,7 +612,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.settled(cmdBar)
await page.getByText('line(end = [74.36, 130.4])').click()
await page.getByRole('button', { name: 'Edit Sketch' }).click()
@ -655,7 +665,14 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
},
] as const
for (const { testName, addVariable, value, constraint } of cases) {
test(`${testName}`, async ({ context, homePage, page, editor }) => {
test(`${testName}`, async ({
context,
homePage,
page,
editor,
scene,
cmdBar,
}) => {
// constants and locators
const cmdBarKclInput = page
.getByTestId('cmd-bar-arg-value')
@ -689,7 +706,7 @@ part002 = startSketchOn(XZ)
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.settled(cmdBar)
await editor.scrollToText('line(end = [74.36, 130.4])', true)
await page.getByText('line(end = [74.36, 130.4])').click()
@ -746,7 +763,7 @@ part002 = startSketchOn(XZ)
},
] as const
for (const { codeAfter, constraintName } of cases) {
test(`${constraintName}`, async ({ page, homePage }) => {
test(`${constraintName}`, async ({ page, homePage, scene, cmdBar }) => {
await page.addInitScript(async (customCode) => {
localStorage.setItem(
'persistCode',
@ -770,7 +787,7 @@ part002 = startSketchOn(XZ)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.settled(cmdBar)
await page.getByText('line(end = [74.36, 130.4])').click()
await page.getByRole('button', { name: 'Edit Sketch' }).click()
@ -831,11 +848,11 @@ part002 = startSketchOn(XZ)
test.describe('Two segment - no modal constraints', () => {
const cases = [
{
codeAfter: `|> angledLine(angle = 83, length = segLen(seg01))`,
codeAfter: `|> angledLine([83, segLen(seg01)], %)`,
constraintName: 'Equal Length',
},
{
codeAfter: `|> angledLine(angle = segAng(seg01), length = 78.33)`,
codeAfter: `|> angledLine([segAng(seg01), 78.33], %)`,
constraintName: 'Parallel',
},
{
@ -848,7 +865,7 @@ part002 = startSketchOn(XZ)
},
] as const
for (const { codeAfter, constraintName } of cases) {
test(`${constraintName}`, async ({ page, homePage }) => {
test(`${constraintName}`, async ({ page, homePage, scene, cmdBar }) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
@ -871,7 +888,7 @@ part002 = startSketchOn(XZ)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.settled(cmdBar)
await page.getByText('line(end = [74.36, 130.4])').click()
await page.getByRole('button', { name: 'Edit Sketch' }).click()
@ -930,7 +947,7 @@ part002 = startSketchOn(XZ)
},
] as const
for (const { codeAfter, constraintName, axisClick } of cases) {
test(`${constraintName}`, async ({ page, homePage }) => {
test(`${constraintName}`, async ({ page, homePage, scene, cmdBar }) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
@ -953,7 +970,7 @@ part002 = startSketchOn(XZ)
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.settled(cmdBar)
await page.getByText('line(end = [74.36, 130.4])').click()
await page.getByRole('button', { name: 'Edit Sketch' }).click()
@ -994,6 +1011,8 @@ part002 = startSketchOn(XZ)
test('Horizontally constrained line remains selected after applying constraint', async ({
page,
homePage,
scene,
cmdBar,
}) => {
test.fixme(orRunWhenFullSuiteEnabled())
test.setTimeout(70_000)
@ -1010,7 +1029,7 @@ part002 = startSketchOn(XZ)
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.settled(cmdBar)
await page.getByText('line(end = [3.79, 2.68], tag = $seg01)').click()
await expect(page.getByRole('button', { name: 'Edit Sketch' })).toBeEnabled(
@ -1129,7 +1148,7 @@ test.describe('Electron constraint tests', () => {
sortBy: 'last-modified-desc',
})
await homePage.openProject('test-sample')
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
})
async function clickOnFirstSegmentLabel() {
@ -1150,9 +1169,7 @@ test.describe('Electron constraint tests', () => {
await clickOnFirstSegmentLabel()
await cmdBar.progressCmdBar()
await editor.expectEditor.toContain('length001 = 15.3')
await editor.expectEditor.toContain(
'|> angledLine(angle = 9, length = length001)'
)
await editor.expectEditor.toContain('|> angledLine([9, length001], %)')
})
await test.step('Double click again and expect failure', async () => {

View File

@ -8,37 +8,37 @@ test.describe('Testing Gizmo', { tag: ['@skipWin'] }, () => {
const cases = [
{
testDescription: 'top view',
clickPosition: { x: 951, y: 385 },
clickPosition: { x: 951, y: 347 },
expectedCameraPosition: { x: 800, y: -152, z: 4886.02 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},
{
testDescription: 'bottom view',
clickPosition: { x: 951, y: 429 },
clickPosition: { x: 951, y: 391 },
expectedCameraPosition: { x: 800, y: -152, z: -4834.02 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},
{
testDescription: 'right view',
clickPosition: { x: 929, y: 417 },
clickPosition: { x: 929, y: 379 },
expectedCameraPosition: { x: 5660.02, y: -152, z: 26 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},
{
testDescription: 'left view',
clickPosition: { x: 974, y: 397 },
clickPosition: { x: 974, y: 359 },
expectedCameraPosition: { x: -4060.02, y: -152, z: 26 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},
{
testDescription: 'back view',
clickPosition: { x: 967, y: 421 },
clickPosition: { x: 967, y: 383 },
expectedCameraPosition: { x: 800, y: 4708.02, z: 26 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},
{
testDescription: 'front view',
clickPosition: { x: 935, y: 393 },
clickPosition: { x: 935, y: 355 },
expectedCameraPosition: { x: 800, y: -5012.02, z: 26 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},
@ -259,7 +259,7 @@ test.describe(`Testing gizmo, fixture-based`, () => {
`@settings(defaultLengthUnit = in)
const sketch002 = startSketchOn(XZ)
|> startProfileAt([-108.83, -57.48], %)
|> angledLine(angle = 0, length = 105.13, tag = $rectangleSegmentA001)
|> angledLine([0, 105.13], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001) - 90,
77.9

View File

@ -2,11 +2,7 @@ import { getUtils, orRunWhenFullSuiteEnabled } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Test toggling perspective', () => {
test('via command palette and toggle', async ({
page,
homePage,
toolbar,
}) => {
test('via command palette and toggle', async ({ page, homePage }) => {
test.fixme(orRunWhenFullSuiteEnabled())
const u = await getUtils(page)
@ -18,7 +14,7 @@ test.describe('Test toggling perspective', () => {
y: screenHeight * 0.2,
}
const backgroundColor: [number, number, number] = [29, 29, 29]
const xzPlaneColor: [number, number, number] = [72, 55, 96]
const xzPlaneColor: [number, number, number] = [82, 55, 96]
const locationToHaveColor = async (color: [number, number, number]) => {
return u.getGreatestPixDiff(checkedScreenLocation, color)
}
@ -30,29 +26,9 @@ test.describe('Test toggling perspective', () => {
const commandToast = page.getByText(
`Set camera projection to "orthographic"`
)
const checkSettingValue = async () => {
const settingsButton = page.getByRole('link', {
name: 'Settings',
exact: false,
})
let settingValue: string | null = null
await test.step(`Check the setting value`, async () => {
await settingsButton.click()
const userTab = page.getByRole('radio', { name: 'User' })
await userTab.click()
await expect(userTab).toBeChecked()
const setting = page.locator('#cameraProjection').first()
await expect(setting).toBeAttached()
await setting.scrollIntoViewIfNeeded()
settingValue = await setting.getByRole('combobox').inputValue()
await page.getByTestId('settings-close-button').click()
})
return settingValue
}
const projectionToggle = page.getByRole('switch', {
name: 'Camera projection: ',
})
await test.step('Setup', async () => {
await page.setBodyDimensions({ width: screenWidth, height: screenHeight })
@ -63,8 +39,8 @@ test.describe('Test toggling perspective', () => {
timeout: 5000,
message: 'This spot should have the background color',
})
.toBeLessThan(30)
expect(await checkSettingValue()).toBe('perspective')
.toBeLessThan(15)
await expect(projectionToggle).toHaveAttribute('aria-checked', 'true')
})
// Extremely wild note: flicking between ortho and persp actually changes
@ -83,22 +59,33 @@ test.describe('Test toggling perspective', () => {
timeout: 5000,
message: 'This spot should have the XZ plane color',
})
.toBeLessThan(30)
expect(await checkSettingValue()).toBe('orthographic')
.toBeLessThan(15)
await expect(projectionToggle).toHaveAttribute('aria-checked', 'false')
})
await test.step(`Refresh the page and ensure the stream is loaded in ortho`, async () => {
await page.reload()
await expect(toolbar.startSketchBtn).toBeEnabled({ timeout: 15_000 })
await page.waitForTimeout(1000)
await u.closeKclCodePanel()
await expect
.poll(async () => locationToHaveColor(xzPlaneColor), {
timeout: 5000,
message: 'This spot should have the XZ plane color',
})
.toBeLessThan(30)
.toBeLessThan(15)
await expect(commandToast).not.toBeVisible()
expect(await checkSettingValue()).toBe('orthographic')
await expect(projectionToggle).toHaveAttribute('aria-checked', 'false')
})
await test.step(`Switch to perspective via toggle`, async () => {
await projectionToggle.click()
await expect(projectionToggle).toHaveAttribute('aria-checked', 'true')
await expect
.poll(async () => locationToHaveColor(backgroundColor), {
timeout: 5000,
message: 'This spot should have the background color',
})
.toBeLessThan(15)
})
})
})

View File

@ -11,7 +11,8 @@ test.describe('Testing in-app sample loading', () => {
* Note this test implicitly depends on the KCL sample "a-parametric-bearing-pillow-block",
* its title, and its units settings. https://github.com/KittyCAD/kcl-samples/blob/main/a-parametric-bearing-pillow-block/main.kcl
*/
test('Web: should overwrite current code, cannot create new file', async ({
// We have no more web tests
test.skip('Web: should overwrite current code, cannot create new file', async ({
editor,
context,
page,
@ -78,7 +79,7 @@ test.describe('Testing in-app sample loading', () => {
test(
'Desktop: should create new file by default, optionally overwrite',
{ tag: '@electron' },
async ({ editor, context, page }, testInfo) => {
async ({ editor, context, page, scene, cmdBar }, testInfo) => {
const { dir } = await context.folderSetupFn(async (dir) => {
const bracketDir = join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true })
@ -125,7 +126,7 @@ test.describe('Testing in-app sample loading', () => {
await test.step(`Test setup`, async () => {
await page.setBodyDimensions({ width: 1200, height: 500 })
await projectCard.click()
await u.waitForPageLoad()
await scene.settled(cmdBar)
})
await test.step(`Precondition: check the initial code`, async () => {
@ -140,11 +141,14 @@ test.describe('Testing in-app sample loading', () => {
await test.step(`Load a KCL sample with the command palette`, async () => {
await commandBarButton.click()
await page.waitForTimeout(1000)
await commandOption.click()
await page.waitForTimeout(1000)
await commandSampleOption(sampleOne.title).click()
await expect(overwriteWarning).not.toBeVisible()
await expect(newFileWarning).toBeVisible()
await confirmButton.click()
await page.waitForTimeout(1000)
})
await test.step(`Ensure we made and opened a new file`, async () => {
@ -155,14 +159,20 @@ test.describe('Testing in-app sample loading', () => {
await test.step(`Now overwrite the current file`, async () => {
await commandBarButton.click()
await page.waitForTimeout(1000)
await commandOption.click()
await page.waitForTimeout(1000)
await commandSampleOption(sampleTwo.title).click()
await page.waitForTimeout(1000)
await commandMethodArgButton.click()
await page.waitForTimeout(1000)
await commandMethodOption.click()
await page.waitForTimeout(1000)
await expect(commandMethodArgButton).toContainText('overwrite')
await expect(newFileWarning).not.toBeVisible()
await expect(overwriteWarning).toBeVisible()
await confirmButton.click()
await page.waitForTimeout(1000)
})
await test.step(`Ensure we overwrote the current file without navigating`, async () => {

View File

@ -214,16 +214,16 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
part001 = startSketchOn(XZ)
|> startProfileAt([5 + 0, 20 + 0], %)
|> line(end = [0.5, -14 + 0])
|> angledLine(angle = 3 + 0, length = 32 + 0)
|> angledLine({ angle = 3 + 0, length = 32 + 0 }, %)
|> line(endAbsolute = [5 + 33, 20 + 11.5 + 0])
|> xLine(endAbsolute = 5 + 9 - 5)
|> yLine(endAbsolute = 20 + -10.77, tag = $a)
|> xLine(length = 26.04)
|> yLine(length = 21.14 + 0)
|> angledLine(angle = 181 + 0, lengthX = 23.14)
|> angledLine(angle = -91, lengthY = 19 + 0)
|> angledLine(angle = 3 + 0, endAbsoluteX = 5 + 26)
|> angledLine(angle = 89, endAbsoluteY = 20 + 9.14 + 0)
|> angledLineOfXLength({ angle = 181 + 0, length = 23.14 }, %)
|> angledLineOfYLength({ angle = -91, length = 19 + 0 }, %)
|> angledLineToX({ angle = 3 + 0, to = 5 + 26 }, %)
|> angledLineToY({ angle = 89, to = 20 + 9.14 + 0 }, %)
|> angledLineThatIntersects({
angle = 4.14,
intersectTag = a,
@ -306,9 +306,11 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
await clickConstrained({
hoverPos: { x: angledLine.x, y: angledLine.y },
constraintType: 'angle',
expectBeforeUnconstrained: 'angledLine(angle = 3 + 0, length = 32 + 0)',
expectAfterUnconstrained: 'angledLine(angle = 3, length = 32 + 0)',
expectFinal: 'angledLine(angle = angle001, length = 32 + 0)',
expectBeforeUnconstrained:
'angledLine({ angle = 3 + 0, length = 32 + 0 }, %)',
expectAfterUnconstrained:
'angledLine({ angle = 3, length = 32 + 0 }, %)',
expectFinal: 'angledLine({ angle = angle001, length = 32 + 0 }, %)',
ang: ang + 180,
locator: '[data-overlay-toolbar-index="1"]',
})
@ -317,9 +319,10 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
hoverPos: { x: angledLine.x, y: angledLine.y },
constraintType: 'length',
expectBeforeUnconstrained:
'angledLine(angle = angle001, length = 32 + 0)',
expectAfterUnconstrained: 'angledLine(angle = angle001, length = 32)',
expectFinal: 'angledLine(angle = angle001, length = len001)',
'angledLine({ angle = angle001, length = 32 + 0 }, %)',
expectAfterUnconstrained:
'angledLine({ angle = angle001, length = 32 }, %)',
expectFinal: 'angledLine({ angle = angle001, length = len001 }, %)',
ang: ang + 180,
locator: '[data-overlay-toolbar-index="1"]',
})
@ -389,13 +392,13 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
part001 = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> line(end = [0.5, yRel001])
|> angledLine(angle = angle001, length = len001)
|> angledLine({ angle = angle001, length = len001 }, %)
|> line(endAbsolute = [33, yAbs001])
|> xLine(endAbsolute = xAbs002)
|> yLine(endAbsolute = -10.77, tag = $a)
|> xLine(length = 26.04)
|> yLine(length = 21.14 + 0)
|> angledLine(angle = 181 + 0, lengthX = 23.14)
|> angledLineOfXLength({ angle = 181 + 0, length = 23.14 }, %)
`
)
})
@ -462,16 +465,16 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
part001 = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> line(end = [0.5, -14 + 0])
|> angledLine(angle = 3 + 0, length = 32 + 0)
|> angledLine({ angle = 3 + 0, length = 32 + 0 }, %)
|> line(endAbsolute = [33, 11.5 + 0])
|> xLine(endAbsolute = 9 - 5)
|> yLine(endAbsolute = -10.77, tag = $a)
|> xLine(length = 26.04)
|> yLine(length = 21.14 + 0)
|> angledLine(angle = 181 + 0, lengthX = 23.14)
|> angledLine(angle = -91, lengthY = 19 + 0)
|> angledLine(angle = 3 + 0, endAbsoluteX = 26)
|> angledLine(angle = 89, endAbsoluteY = 9.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,
intersectTag = a,
@ -527,9 +530,11 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
hoverPos: { x: angledLineOfXLength.x, y: angledLineOfXLength.y },
constraintType: 'angle',
expectBeforeUnconstrained:
'angledLine(angle = 181 + 0, lengthX = 23.14)',
expectAfterUnconstrained: 'angledLine(angle = -179, lengthX = 23.14)',
expectFinal: 'angledLine(angle = angle001, lengthX = 23.14)',
'angledLineOfXLength({ angle = 181 + 0, length = 23.14 }, %)',
expectAfterUnconstrained:
'angledLineOfXLength({ angle = -179, length = 23.14 }, %)',
expectFinal:
'angledLineOfXLength({ angle = angle001, length = 23.14 }, %)',
ang: ang + 180,
locator: '[data-overlay-toolbar-index="7"]',
})
@ -538,10 +543,11 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
hoverPos: { x: angledLineOfXLength.x, y: angledLineOfXLength.y },
constraintType: 'xRelative',
expectBeforeUnconstrained:
'angledLine(angle = angle001, lengthX = 23.14)',
'angledLineOfXLength({ angle = angle001, length = 23.14 }, %)',
expectAfterUnconstrained:
'angledLine(angle = angle001, lengthX = xRel001)',
expectFinal: 'angledLine(angle = angle001, lengthX = 23.14)',
'angledLineOfXLength({ angle = angle001, length = xRel001 }, %)',
expectFinal:
'angledLineOfXLength({ angle = angle001, length = 23.14 }, %)',
steps: 7,
ang: ang + 180,
locator: '[data-overlay-toolbar-index="7"]',
@ -555,10 +561,11 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
await clickUnconstrained({
hoverPos: { x: angledLineOfYLength.x, y: angledLineOfYLength.y },
constraintType: 'angle',
expectBeforeUnconstrained: 'angledLine(angle = -91, lengthY = 19 + 0)',
expectBeforeUnconstrained:
'angledLineOfYLength({ angle = -91, length = 19 + 0 }, %)',
expectAfterUnconstrained:
'angledLine(angle = angle002, lengthY = 19 + 0)',
expectFinal: 'angledLine(angle = -91, lengthY = 19 + 0)',
'angledLineOfYLength({ angle = angle002, length = 19 + 0 }, %)',
expectFinal: 'angledLineOfYLength({ angle = -91, length = 19 + 0 }, %)',
ang: ang + 180,
steps: 6,
locator: '[data-overlay-toolbar-index="8"]',
@ -567,9 +574,12 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
await clickConstrained({
hoverPos: { x: angledLineOfYLength.x, y: angledLineOfYLength.y },
constraintType: 'yRelative',
expectBeforeUnconstrained: 'angledLine(angle = -91, lengthY = 19 + 0)',
expectAfterUnconstrained: 'angledLine(angle = -91, lengthY = 19)',
expectFinal: 'angledLine(angle = -91, lengthY = yRel002)',
expectBeforeUnconstrained:
'angledLineOfYLength({ angle = -91, length = 19 + 0 }, %)',
expectAfterUnconstrained:
'angledLineOfYLength({ angle = -91, length = 19 }, %)',
expectFinal:
'angledLineOfYLength({ angle = -91, length = yRel002 }, %)',
ang: ang + 180,
steps: 7,
locator: '[data-overlay-toolbar-index="8"]',
@ -587,16 +597,16 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
part001 = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> line(end = [0.5, -14 + 0])
|> angledLine(angle = 3 + 0, length = 32 + 0)
|> angledLine({ angle = 3 + 0, length = 32 + 0 }, %)
|> line(endAbsolute = [33, 11.5 + 0])
|> xLine(endAbsolute = 9 - 5)
|> yLine(endAbsolute = -10.77, tag = $a)
|> xLine(length = 26.04)
|> yLine(length = 21.14 + 0)
|> angledLine(angle = 181 + 0, lengthX = 23.14)
|> angledLine(angle = -91, lengthY = 19 + 0)
|> angledLine(angle = 3 + 0, endAbsoluteX = 26)
|> angledLine(angle = 89, endAbsoluteY = 9.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,
intersectTag = a,
@ -636,9 +646,9 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
hoverPos: { x: angledLineToX.x, y: angledLineToX.y },
constraintType: 'angle',
expectBeforeUnconstrained:
'angledLine(angle = 3 + 0, endAbsoluteX = 26)',
expectAfterUnconstrained: 'angledLine(angle = 3, endAbsoluteX = 26)',
expectFinal: 'angledLine(angle = angle001, endAbsoluteX = 26)',
'angledLineToX({ angle = 3 + 0, to = 26 }, %)',
expectAfterUnconstrained: 'angledLineToX({ angle = 3, to = 26 }, %)',
expectFinal: 'angledLineToX({ angle = angle001, to = 26 }, %)',
ang: ang + 180,
locator: '[data-overlay-toolbar-index="9"]',
})
@ -647,10 +657,10 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
hoverPos: { x: angledLineToX.x, y: angledLineToX.y },
constraintType: 'xAbsolute',
expectBeforeUnconstrained:
'angledLine(angle = angle001, endAbsoluteX = 26)',
'angledLineToX({ angle = angle001, to = 26 }, %)',
expectAfterUnconstrained:
'angledLine(angle = angle001, endAbsoluteX = xAbs001)',
expectFinal: 'angledLine(angle = angle001, endAbsoluteX = 26)',
'angledLineToX({ angle = angle001, to = xAbs001 }, %)',
expectFinal: 'angledLineToX({ angle = angle001, to = 26 }, %)',
ang: ang + 180,
locator: '[data-overlay-toolbar-index="9"]',
})
@ -661,9 +671,11 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
await clickUnconstrained({
hoverPos: { x: angledLineToY.x, y: angledLineToY.y },
constraintType: 'angle',
expectBeforeUnconstrained: 'angledLine(angle = 89, to = 9.14 + 0)',
expectAfterUnconstrained: 'angledLine(angle = angle002, to = 9.14 + 0)',
expectFinal: 'angledLine(angle = 89, to = 9.14 + 0)',
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,
ang: ang + 180,
locator: '[data-overlay-toolbar-index="10"]',
@ -673,9 +685,9 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
hoverPos: { x: angledLineToY.x, y: angledLineToY.y },
constraintType: 'yAbsolute',
expectBeforeUnconstrained:
'angledLine(angle = 89, endAbsoluteY = 9.14 + 0)',
expectAfterUnconstrained: 'angledLine(angle = 89, endAbsoluteY = 9.14)',
expectFinal: 'angledLine(angle = 89, endAbsoluteY = yAbs001)',
'angledLineToY({ angle = 89, to = 9.14 + 0 }, %)',
expectAfterUnconstrained: 'angledLineToY({ angle = 89, to = 9.14 }, %)',
expectFinal: 'angledLineToY({ angle = 89, to = yAbs001 }, %)',
ang: ang + 180,
locator: '[data-overlay-toolbar-index="10"]',
})
@ -747,14 +759,14 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
part001 = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> line(end = [0.5, -14 + 0])
|> angledLine(angle = 3 + 0, length = 32 + 0)
|> angledLine({ angle = 3 + 0, length = 32 + 0 }, %)
|> line(endAbsolute = [33, 11.5 + 0])
|> xLine(endAbsolute = 9 - 5)
|> yLine(endAbsolute = -10.77, tag = $a)
|> xLine(length = 26.04)
|> yLine(length = 21.14 + 0)
|> angledLine(angle = 181 + 0, lengthX = 23.14)
|> angledLine(angle = -91, lengthY = 19 + 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({
@ -1082,8 +1094,8 @@ part001 = startSketchOn(XZ)
|> yLine(endAbsolute = -10.77, tag = $a)
|> xLine(length = 26.04)
|> yLine(length = 21.14 + 0)
|> angledLine(angle = 181 + 0, lengthX = 23.14)
|> angledLine(angle = -91, lengthY = 19 + 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({
@ -1218,7 +1230,8 @@ part001 = startSketchOn(XZ)
ang = await u.getAngle('[data-overlay-index="7"]')
await deleteSegmentSequence({
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
codeToBeDeleted: 'angledLine(angle = 181 + 0, lengthX = 23.14)',
codeToBeDeleted:
'angledLineOfXLength({ angle = 181 + 0, length = 23.14 }, %)',
stdLibFnName: 'angledLineOfXLength',
ang: ang + 180,
locator: '[data-overlay-toolbar-index="7"]',
@ -1327,8 +1340,10 @@ part001 = startSketchOn(XZ)
'yLine(length = -8, tag = $seg01)',
'xLine(endAbsolute = 30, tag = $seg01)',
'yLine(endAbsolute = -4, tag = $seg01)',
'angledLine(angle = 3, lengthX = 30, tag = $seg01)',
'angledLine(angle = 3, lengthY = 1.5, tag = $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)',
@ -1482,25 +1497,32 @@ part001 = startSketchOn(XZ)
after: `line(end = [0, -10], tag = $seg01)`,
},
{
before: `angledLine(angle = 3 + 0, lengthX = 30 + 0, tag = $seg01)`,
before: `angledLineOfXLength({ angle = 3 + 0, length = 30 + 0 }, %, $seg01)`,
after: `line(end = [30, 1.57], tag = $seg01)`,
},
{
before: `angledLine(angle = 3 + 0, lengthY = 1.5 + 0, tag = $seg01)`,
before: `angledLineOfYLength({ angle = 3 + 0, length = 1.5 + 0 }, %, $seg01)`,
after: `line(end = [28.62, 1.5], tag = $seg01)`,
},
{
before: `angledLine(angle = 3 + 0, endAbsoluteX = 30 + 0, tag = $seg01)`,
before: `angledLineToX({ angle = 3 + 0, to = 30 + 0 }, %, $seg01)`,
after: `line(end = [25, 1.31], tag = $seg01)`,
},
{
before: `angledLine(angle = 3 + 0, endAbsoluteY = 7 + 0, $seg01)`,
before: `angledLineToY({ angle = 3 + 0, to = 7 + 0 }, %, $seg01)`,
after: `line(end = [19.08, 1], tag = $seg01)`,
},
]
for (const { before, after } of cases) {
test(`${before.split('=')[0]}`, async ({ page, editor, homePage }) => {
const isObj = before.includes('{ angle = 3')
test(`${before.split('=')[0]}${isObj ? '-[obj-input]' : ''}`, async ({
page,
editor,
homePage,
scene,
cmdBar,
}) => {
await page.addInitScript(
async ({ lineToBeDeleted }) => {
localStorage.setItem(
@ -1510,7 +1532,7 @@ part001 = startSketchOn(XZ)
|> startProfileAt([5, 6], %)
|> ${lineToBeDeleted}
|> line(end = [-10, -15])
|> angledLine(angle = -176, length = segLen(seg01))`
|> angledLine([-176, segLen(seg01)], %)`
)
},
{
@ -1521,7 +1543,8 @@ part001 = startSketchOn(XZ)
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.connectionEstablished()
await scene.settled(cmdBar)
await page.waitForTimeout(300)
await page.getByText(before).click()

View File

@ -320,9 +320,9 @@ part009 = startSketchOn(XY)
|> line(end = [0, -1])
|> line(end = [-thickness, 0])
|> line(end = [0, 1])
|> angledLine(angle = 120, endAbsoluteX = pipeSmallDia)
|> angledLineToX({ angle = 120, to = pipeSmallDia }, %)
|> line(end = [0, pipeLength])
|> angledLine(angle = 60, endAbsoluteX = pipeLargeDia)
|> angledLineToX({ angle = 60, to = pipeLargeDia }, %)
|> close()
rev = revolve(part009, axis = Y)
sketch006 = startSketchOn(XY)
@ -332,7 +332,7 @@ profile001 = circle(
radius = 17.96
)
profile002 = startProfileAt([86.92, -63.81], sketch006)
|> angledLine(angle = 0, length = 63.81, tag = $rectangleSegmentA001)
|> angledLine([0, 63.81], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001) - 90,
17.05
@ -471,7 +471,7 @@ yo = startProfileAt([4.83, 12.56], part001)
|> line(end = [15.1, 2.48])
|> line(end = [3.15, -9.85], tag = $seg01)
|> line(end = [-15.17, -4.1])
|> angledLine(angle = segAng(seg01), length = 12.35, tag = $seg02)
|> angledLine([segAng(seg01), 12.35], %, $seg02)
|> line(end = [-13.02, 10.03])
|> close()
yoo = extrude(yo, length = 4)
@ -484,7 +484,7 @@ profile002 = startProfileAt([-11.08, 2.39], sketch002)
|> close()
extrude001 = extrude(profile002, length = 15)
profile001 = startProfileAt([7.49, 9.96], sketch001)
|> angledLine(angle = 0, length = 5.05, tag = $rectangleSegmentA001)
|> angledLine([0, 5.05], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001) - 90,
4.81
@ -528,6 +528,8 @@ profile001 = startProfileAt([7.49, 9.96], sketch001)
test('Hovering over 3d features highlights code, clicking puts the cursor in the right place and sends selection id to engine', async ({
page,
homePage,
scene,
cmdBar,
}) => {
const u = await getUtils(page)
await page.addInitScript(async (KCL_DEFAULT_LENGTH) => {
@ -537,15 +539,15 @@ profile001 = startProfileAt([7.49, 9.96], sketch001)
part001 = startSketchOn(XZ)
|> startProfileAt([20, 0], %)
|> line(end = [7.13, 4 + 0])
|> angledLine(angle = 3 + 0, length = 3.14 + 0 )
|> angledLine({ angle = 3 + 0, length = 3.14 + 0 }, %)
|> line(endAbsolute = [20.14 + 0, -0.14 + 0])
|> xLine(endAbsolute = 29 + 0)
|> yLine(length = -3.14 + 0, tag = $a)
|> xLine(length = 1.63)
|> angledLineOfXLength({ angle = 3 + 0, length = 3.14 }, %)
|> angledLineOfYLength({ angle = 30, length = 3 + 0 }, %)
|> angledLine(angle = 22.14 + 0, endAbsoluteX = 12)
|> angledLine(angle = 30, endAbsoluteY = 11.14)
|> angledLineToX({ angle = 22.14 + 0, to = 12 }, %)
|> angledLineToY({ angle = 30, to = 11.14 }, %)
|> angledLineThatIntersects({
angle = 3.14,
intersectTag = a,
@ -735,13 +737,13 @@ part001 = startSketchOn(XZ)
'straightSegmentEdge',
straightSegmentEdge,
`angledLineToY({angle=30,to=11.14},%)`,
'angledLine(angle = 30, endAbsoluteY = 11.14)'
'angledLineToY({ angle = 30, to = 11.14 }, %)'
)
await checkCodeAtHoverPosition(
'straightSegmentOppositeEdge',
straightSegmentOppositeEdge,
`angledLineToY({angle=30,to=11.14},%)`,
'angledLine(angle = 30, endAbsoluteY = 11.14)'
'angledLineToY({ angle = 30, to = 11.14 }, %)'
)
await checkCodeAtHoverPosition(
'straightSegmentAdjacentEdge',
@ -756,7 +758,7 @@ part001 = startSketchOn(XZ)
await u.codeLocator.fill(`@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag]
|> angledLine(angle = 0, length = 268.43, tag = $rectangleSegmentA001)
|> angledLine([0, 268.43], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001) - 90,
217.26
@ -779,11 +781,7 @@ part001 = startSketchOn(XZ)
)
`)
await expect(
page
.getByTestId('model-state-indicator-receive-reliable')
.or(page.getByTestId('model-state-indicator-execution-done'))
).toBeVisible()
await scene.settled(cmdBar)
await u.openAndClearDebugPanel()
await u.sendCustomCmd({
@ -953,6 +951,7 @@ part001 = startSketchOn(XZ)
page,
homePage,
scene,
cmdBar,
}) => {
const cases = [
{
@ -961,7 +960,7 @@ part001 = startSketchOn(XZ)
},
{
pos: [816, 244],
expectedCode: 'angledLine(angle = segAng(seg01), length = yo)',
expectedCode: 'angledLine([segAng(seg01), yo], %)',
},
{
pos: [1107, 161],
@ -989,7 +988,7 @@ part001 = startSketchOn(XZ)
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
await u.openAndClearDebugPanel()
await u.sendCustomCmd({
@ -1024,6 +1023,7 @@ part001 = startSketchOn(XZ)
page,
homePage,
scene,
cmdBar,
}) => {
await page.addInitScript(async () => {
localStorage.setItem(
@ -1043,7 +1043,7 @@ part001 = startSketchOn(XZ)
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
await u.openAndClearDebugPanel()
await u.sendCustomCmd({

View File

@ -1 +1 @@
part001 = startSketchOn('XY')yo = startProfileAt([4.83, 12.56], part001) |> line(end = [15.1, 2.48]) |> line(end = [3.15, -9.85], tag = $seg01) |> line(end = [-15.17, -4.1]) |> angledLine(angle = segAng(seg01), 12.35], %, $seg02) |> line(end = [-13.02, 10.03]) |> close()sketch002 = startSketchOn({ plane = { origin = { x = 7.49, y = 2.4, z = 0 }, xAxis = { x = -0.3, y = 0.95, z = 0 }, yAxis = { x = 0, y = 0, z = 1 }, zAxis = { x = 0.95, y = 0.3, z = 0 } }})sketch001 = startSketchOn({ plane = { origin = { x = 0, y = 0, z = 4 }, xAxis = { x = 1, y = 0, z = 0 }, yAxis = { x = 0, y = 1, z = 0 }, zAxis = { x = 0, y = 0, z = 1 } }})profile002 = startProfileAt([-11.08, 2.39], sketch002) |> line(end = [4.89, 0.9]) |> line(end = [-0.61, -2.41]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> close()extrude001 = extrude(profile002, length = 15)profile001 = startProfileAt([7.49, 9.96], sketch001) |> angledLine(angle = 0, length = 5.05, tag = $rectangleSegmentA001) |> angledLine([ segAng(rectangleSegmentA001) - 90, 4.81 ], %) |> angledLine([ segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001) ) |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> close()
part001 = startSketchOn('XY')yo = startProfileAt([4.83, 12.56], part001) |> line(end = [15.1, 2.48]) |> line(end = [3.15, -9.85], tag = $seg01) |> line(end = [-15.17, -4.1]) |> angledLine([segAng(seg01), 12.35], %, $seg02) |> line(end = [-13.02, 10.03]) |> close()sketch002 = startSketchOn({ plane = { origin = { x = 7.49, y = 2.4, z = 0 }, xAxis = { x = -0.3, y = 0.95, z = 0 }, yAxis = { x = 0, y = 0, z = 1 }, zAxis = { x = 0.95, y = 0.3, z = 0 } }})sketch001 = startSketchOn({ plane = { origin = { x = 0, y = 0, z = 4 }, xAxis = { x = 1, y = 0, z = 0 }, yAxis = { x = 0, y = 1, z = 0 }, zAxis = { x = 0, y = 0, z = 1 } }})profile002 = startProfileAt([-11.08, 2.39], sketch002) |> line(end = [4.89, 0.9]) |> line(end = [-0.61, -2.41]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> close()extrude001 = extrude(profile002, length = 15)profile001 = startProfileAt([7.49, 9.96], sketch001) |> angledLine([0, 5.05], %, $rectangleSegmentA001) |> angledLine([ segAng(rectangleSegmentA001) - 90, 4.81 ], %) |> angledLine([ segAng(rectangleSegmentA001), -segLen(rectangleSegmentA001) ], %) |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> close()

View File

@ -55,7 +55,8 @@ test.describe('Testing settings', () => {
// Check that the invalid settings were changed to good defaults
expect(storedSettings.settings?.modeling?.base_unit).toBe('in')
expect(storedSettings.settings?.modeling?.mouse_controls).toBe('zoo')
expect(storedSettings.settings?.project?.directory).toBe('')
// Commenting this out because tests need this to be set to work properly.
// expect(storedSettings.settings?.app?.project_directory).toBe('')
expect(storedSettings.settings?.project?.default_project_name).toBe(
'untitled'
)
@ -865,6 +866,8 @@ test.describe('Testing settings', () => {
page,
homePage,
tronApp,
scene,
cmdBar,
}) => {
if (!tronApp) {
fail()
@ -886,6 +889,7 @@ test.describe('Testing settings', () => {
})
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await scene.connectionEstablished()
// Constants and locators
const resizeHandle = page.locator('.sidebar-resize-handles > div.block')
@ -897,6 +901,7 @@ test.describe('Testing settings', () => {
async function setShowDebugPanelTo(value: 'On' | 'Off') {
await commandsButton.click()
await debugPaneOption.scrollIntoViewIfNeeded()
await debugPaneOption.click()
await page.getByRole('option', { name: value }).click()
await expect(

View File

@ -59,11 +59,10 @@ part001 = startSketchOn(-XZ)
|> startProfileAt([0, 0], %)
|> yLine(length = baseHeight)
|> xLine(length = baseLen)
|> angledLine(
|> angledLineToY({
angle = topAng,
endAbsoluteY = totalHeightHalf,
tag = $seg04,
)
to = totalHeightHalf,
}, %, $seg04)
|> xLine(endAbsolute = totalLen, tag = $seg03)
|> yLine(length = -armThick, tag = $seg01)
|> angledLineThatIntersects({
@ -71,12 +70,11 @@ part001 = startSketchOn(-XZ)
offset = -armThick,
intersectTag = seg04
}, %)
|> angledLine(angle = segAng(seg04) + 180, endAbsoluteY = turns::ZERO)
|> angledLine(
|> angledLineToY([segAng(seg04) + 180, turns::ZERO], %)
|> angledLineToY({
angle = -bottomAng,
endAbsoluteY = -totalHeightHalf - armThick,
tag = $seg02,
)
to = -totalHeightHalf - armThick,
}, %, $seg02)
|> xLine(endAbsolute = segEndX(seg03) + 0)
|> yLine(length = -segLen(seg01))
|> angledLineThatIntersects({
@ -84,7 +82,7 @@ part001 = startSketchOn(-XZ)
offset = -armThick,
intersectTag = seg02
}, %)
|> angledLine(angle = segAng(seg02) + 180, endAbsoluteY = -baseHeight)
|> angledLineToY([segAng(seg02) + 180, -baseHeight], %)
|> xLine(endAbsolute = turns::ZERO)
|> close()
|> extrude(length = 4)`

View File

@ -17,7 +17,6 @@ declare module '@playwright/test' {
}
interface Page {
dir: string
TEST_SETTINGS_FILE_KEY?: string
setBodyDimensions: (dims: {
width: number
height: number

1
interface.d.ts vendored
View File

@ -72,7 +72,6 @@ export interface IElectronAPI {
process: {
env: {
BASE_URL: string
TEST_SETTINGS_FILE_KEY: string
IS_PLAYWRIGHT: string
VITE_KC_DEV_TOKEN: string
VITE_KC_API_WS_MODELING_URL: string

View File

@ -4,10 +4,10 @@ $ dpdm --no-warning --no-tree -T --skip-dynamic-imports=circular src/index.tsx
02) src/lang/std/sketch.ts -> src/lang/modifyAst.ts
03) src/lang/std/sketch.ts -> src/lang/modifyAst.ts -> src/lang/std/sketchcombos.ts
04) src/lib/singletons.ts -> src/editor/manager.ts -> src/lib/selections.ts
05) src/lib/singletons.ts -> src/lang/KclSingleton.ts
06) src/lib/singletons.ts -> src/lang/codeManager.ts
07) src/lib/singletons.ts -> src/clientSideScene/sceneEntities.ts -> src/clientSideScene/segments.ts -> src/components/Toolbar/angleLengthInfo.ts
08) src/lib/singletons.ts -> src/clientSideScene/sceneEntities.ts -> src/clientSideScene/segments.ts -> src/machines/commandBarMachine.ts -> src/lib/commandBarConfigs/authCommandConfig.ts -> src/machines/appMachine.ts -> src/machines/settingsMachine.ts
09) src/machines/commandBarMachine.ts -> src/lib/commandBarConfigs/authCommandConfig.ts -> src/machines/appMachine.ts -> src/machines/settingsMachine.ts
05) src/lib/singletons.ts -> src/editor/manager.ts -> src/lib/selections.ts -> src/machines/appMachine.ts -> src/machines/engineStreamMachine.ts
06) src/lib/singletons.ts -> src/editor/manager.ts -> src/lib/selections.ts -> src/machines/appMachine.ts -> src/machines/settingsMachine.ts
07) src/machines/appMachine.ts -> src/machines/settingsMachine.ts -> src/machines/commandBarMachine.ts -> src/lib/commandBarConfigs/authCommandConfig.ts
08) src/lib/singletons.ts -> src/lang/codeManager.ts
09) src/lib/singletons.ts -> src/clientSideScene/sceneEntities.ts -> src/clientSideScene/segments.ts -> src/components/Toolbar/angleLengthInfo.ts
10) src/hooks/useModelingContext.ts -> src/components/ModelingMachineProvider.tsx -> src/components/Toolbar/Intersect.tsx -> src/components/SetHorVertDistanceModal.tsx -> src/lib/useCalculateKclExpression.ts
11) src/routes/Onboarding/index.tsx -> src/routes/Onboarding/Camera.tsx -> src/routes/Onboarding/utils.tsx

View File

@ -233,7 +233,7 @@
"ts-node": "^10.0.0",
"typescript": "^5.8.2",
"typescript-eslint": "^8.26.1",
"vite": "^5.4.17",
"vite": "^5.4.16",
"vite-plugin-package-version": "^1.1.0",
"vite-plugin-top-level-await": "^1.5.0",
"vite-tsconfig-paths": "^4.3.2",

View File

@ -683,9 +683,9 @@ vite-tsconfig-paths@^4.3.2:
tsconfck "^3.0.3"
vite@^5.0.0:
version "5.4.17"
resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.17.tgz#4bf61dd4cdbf64b0d6661f5dba76954cc81d5082"
integrity sha512-5+VqZryDj4wgCs55o9Lp+p8GE78TLVg0lasCH5xFZ4jacZjtqZa6JUw9/p0WeAojaOfncSM6v77InkFPGnvPvg==
version "5.4.16"
resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.16.tgz#471983257a890ef33f2700cbbbc2134f2d08abf1"
integrity sha512-Y5gnfp4NemVfgOTDQAunSD4346fal44L9mszGGY/e+qxsRT5y1sMlS/8tiQ8AFAp+MFgYNSINdfEchJiPm41vQ==
dependencies:
esbuild "^0.21.3"
postcss "^8.4.43"

View File

@ -4,7 +4,7 @@
// Set units
@settings(defaultLengthUnit = in)
// Create a function to make the 80-20 rail
// Define function
fn rail8020(originStart, railHeight, railLength) {
// Sketch side 1 of profile
sketch001 = startSketchOn(-XZ)
@ -31,9 +31,15 @@ fn rail8020(originStart, railHeight, railLength) {
|> xLine(length = 0.06 * railHeight, tag = $edge1)
|> yLine(length = 0.087 * railHeight, tag = $edge2)
|> xLine(length = -0.183 * railHeight, tag = $edge3)
|> angledLine(angle = 45, endAbsoluteY = (1 - 0.356) / 2 * railHeight + originStart[1], tag = $edge4)
|> angledLineToY({
angle = 45,
to = (1 - 0.356) / 2 * railHeight + originStart[1]
}, %, $edge4)
|> xLine(length = 0.232 * railHeight, tag = $edge5)
|> angledLine(angle = -45, endAbsoluteY = 0.087 * railHeight + originStart[1], tag = $edge6)
|> angledLineToY({
angle = -45,
to = 0.087 * railHeight + originStart[1]
}, %, $edge6)
|> xLine(length = -0.183 * railHeight, tag = $edge7)
|> yLine(length = -0.087 * railHeight, tag = $edge8)
|> xLine(length = 0.06 * railHeight)
@ -69,9 +75,15 @@ fn rail8020(originStart, railHeight, railLength) {
|> yLine(length = 0.06 * railHeight, tag = $edge9)
|> xLine(length = -0.087 * railHeight, tag = $edge10)
|> yLine(length = -0.183 * railHeight, tag = $edge11) // edge11
|> angledLine(angle = 135, endAbsoluteX = ((1 - 0.356) / 2 + 0.356) * railHeight + originStart[0], tag = $edge12) // edge12
|> angledLineToX({
angle = 135,
to = ((1 - 0.356) / 2 + 0.356) * railHeight + originStart[0]
}, %, $edge12) // edge12
|> yLine(length = 0.232 * railHeight, tag = $edge13) // 13
|> angledLine(angle = 45, endAbsoluteX = (1 - 0.087) * railHeight + originStart[0], tag = $edge14) // 14
|> angledLineToX({
angle = 45,
to = (1 - 0.087) * railHeight + originStart[0]
}, %, $edge14) // 14
|> yLine(length = -0.183 * railHeight, tag = $edge15) // 15
|> xLine(length = 0.087 * railHeight, tag = $edge16)
|> yLine(length = 0.06 * railHeight)
@ -107,9 +119,15 @@ fn rail8020(originStart, railHeight, railLength) {
|> xLine(length = -0.06 * railHeight, tag = $edge17)
|> yLine(length = -0.087 * railHeight, tag = $edge18)
|> xLine(length = 0.183 * railHeight, tag = $edge19)
|> angledLine(angle = 45, endAbsoluteY = ((1 - 0.356) / 2 + 0.356) * railHeight + originStart[1], tag = $edge20)
|> angledLineToY({
angle = 45,
to = ((1 - 0.356) / 2 + 0.356) * railHeight + originStart[1]
}, %, $edge20)
|> xLine(length = -0.232 * railHeight, tag = $edge21)
|> angledLine(angle = 135, endAbsoluteY = (1 - 0.087) * railHeight + originStart[1], tag = $edge22)
|> angledLineToY({
angle = 135,
to = (1 - 0.087) * railHeight + originStart[1]
}, %, $edge22)
|> xLine(length = 0.183 * railHeight, tag = $edge23)
|> yLine(length = 0.087 * railHeight, tag = $edge24)
|> xLine(length = -0.06 * railHeight)
@ -145,9 +163,15 @@ fn rail8020(originStart, railHeight, railLength) {
|> yLine(length = -0.06 * railHeight, tag = $edge25)
|> xLine(length = 0.087 * railHeight, tag = $edge26)
|> yLine(length = 0.183 * railHeight, tag = $edge27)
|> angledLine(angle = 135, endAbsoluteX = (1 - 0.356) / 2 * railHeight + originStart[0], tag = $edge28)
|> angledLineToX({
angle = 135,
to = (1 - 0.356) / 2 * railHeight + originStart[0]
}, %, $edge28)
|> yLine(length = -0.232 * railHeight, tag = $edge29)
|> angledLine(angle = 45, endAbsoluteX = 0.087 * railHeight + originStart[0], tag = $edge30)
|> angledLineToX({
angle = 45,
to = 0.087 * railHeight + originStart[0]
}, %, $edge30)
|> yLine(length = 0.183 * railHeight, tag = $edge31)
|> xLine(length = -0.087 * railHeight, tag = $edge32)
|> yLine(length = -0.06 * railHeight)

View File

@ -25,6 +25,8 @@ When you submit a PR to add or modify KCL samples, images and STEP files will be
---
#### [80-20-rail](80-20-rail/main.kcl) ([screenshot](screenshots/80-20-rail.png))
[![80-20-rail](screenshots/80-20-rail.png)](80-20-rail/main.kcl)
#### [a-parametric-bearing-pillow-block](a-parametric-bearing-pillow-block/main.kcl) ([screenshot](screenshots/a-parametric-bearing-pillow-block.png))
[![a-parametric-bearing-pillow-block](screenshots/a-parametric-bearing-pillow-block.png)](a-parametric-bearing-pillow-block/main.kcl)
#### [ball-bearing](ball-bearing/main.kcl) ([screenshot](screenshots/ball-bearing.png))
[![ball-bearing](screenshots/ball-bearing.png)](ball-bearing/main.kcl)
#### [bench](bench/main.kcl) ([screenshot](screenshots/bench.png))
@ -81,8 +83,6 @@ When you submit a PR to add or modify KCL samples, images and STEP files will be
[![mounting-plate](screenshots/mounting-plate.png)](mounting-plate/main.kcl)
#### [multi-axis-robot](multi-axis-robot/main.kcl) ([screenshot](screenshots/multi-axis-robot.png))
[![multi-axis-robot](screenshots/multi-axis-robot.png)](multi-axis-robot/main.kcl)
#### [parametric-bearing-pillow-block](parametric-bearing-pillow-block/main.kcl) ([screenshot](screenshots/parametric-bearing-pillow-block.png))
[![parametric-bearing-pillow-block](screenshots/parametric-bearing-pillow-block.png)](parametric-bearing-pillow-block/main.kcl)
#### [pipe](pipe/main.kcl) ([screenshot](screenshots/pipe.png))
[![pipe](screenshots/pipe.png)](pipe/main.kcl)
#### [pipe-flange-assembly](pipe-flange-assembly/main.kcl) ([screenshot](screenshots/pipe-flange-assembly.png))

View File

@ -1,10 +1,10 @@
// Parametric Bearing Pillow Block
// A Parametric Bearing Pillow Block
// A bearing pillow block, also known as a plummer block or pillow block bearing, is a pedestal used to provide support for a rotating shaft with the help of compatible bearings and various accessories. Housing a bearing, the pillow block provides a secure and stable foundation that allows the shaft to rotate smoothly within its machinery setup. These components are essential in a wide range of mechanical systems and machinery, playing a key role in reducing friction and supporting radial and axial loads.
// Set units
@settings(defaultLengthUnit = in)
// Define parameters
// Define constants such as length, width, height, counter-bore depth and diameter, bearing diameter, hole location padding, and more
length = 6
width = 4
height = 1
@ -14,15 +14,15 @@ holeDia = .375
padding = 1.5
bearingDia = 3
// Sketch the block body
body = startSketchOn(XY)
// (Needs to be updated). Sketch the block and extrude up to where the counterbore diameter starts.
extrude001 = startSketchOn(XY)
|> startProfileAt([-width / 2, -length / 2], %)
|> line(endAbsolute = [width / 2, -length / 2])
|> line(endAbsolute = [width / 2, length / 2])
|> line(endAbsolute = [-width / 2, length / 2])
|> close()
|> extrude(length = height)
counterBoreHoles = startSketchOn(body, 'end')
extrude002 = startSketchOn(extrude001, 'end')
|> circle(
center = [
-(width / 2 - (padding / 2)),
@ -34,7 +34,7 @@ counterBoreHoles = startSketchOn(body, 'end')
|> patternLinear2d(instances = 2, distance = width - padding, axis = [1, 0])
|> extrude(%, length = -cbDepth)
boltHoles = startSketchOn(body, 'start')
extrude003 = startSketchOn(extrude001, 'start')
|> circle(
center = [
-(width / 2 - (padding / 2)),
@ -46,6 +46,6 @@ boltHoles = startSketchOn(body, 'start')
|> patternLinear2d(instances = 2, distance = width - padding, axis = [1, 0])
|> extrude(length = -height + cbDepth)
centerHole = startSketchOn(body, 'end')
extrude004 = startSketchOn(extrude001, 'end')
|> circle(center = [0, 0], radius = bearingDia / 2)
|> extrude(length = -height)

View File

@ -4,7 +4,7 @@
// Set units
@settings(defaultLengthUnit = in)
// Define parameters
// Define constants like ball diameter, inside diamter, overhange length, and thickness
outsideDiameter = 1.625
sphereDia = 0.25
shaftDia = 0.75
@ -95,3 +95,5 @@ outsideWallSketch = startSketchOn(offsetPlane(XY, offset = -overallThickness / 2
|> hole(circle(center = [0, 0], radius = shaftDia / 2 + wallThickness + sphereDia), %)
outsideWall = extrude(outsideWallSketch, length = overallThickness)
// https://www.mcmaster.com/60355K185/

View File

@ -86,11 +86,11 @@ export fn seatSlats(plane, length) {
fn backSlatsSketch(plane) {
sketch004 = startSketchOn(plane)
|> startProfileAt([22, 38.5], %)
|> angledLine(angle = 173, length = 2)
|> angledLine([173, 2], %)
|> line(end = [-1.74, 2.03])
|> angledLine(angle = 82, length = 6.6)
|> angledLine([82, 6.6], %)
|> line(end = [2.23, 1.42])
|> angledLine(angle = -7, length = 2)
|> angledLine([-7, 2], %)
|> line(endAbsolute = profileStart(%))
|> close()
|> patternLinear2d(instances = 2, distance = 11, axis = [-0.137, -1])

View File

@ -4,8 +4,8 @@
// Set units
@settings(defaultLengthUnit = in)
// Import parameters
import caliperTolerance, caliperPadLength, caliperThickness, caliperOuterEdgeRadius, caliperInnerEdgeRadius, rotorDiameter, rotorTotalThickness, yAxisOffset from "parameters.kcl"
// Import Constants
import caliperTolerance, caliperPadLength, caliperThickness, caliperOuterEdgeRadius, caliperInnerEdgeRadius, rotorDiameter, rotorTotalThickness, yAxisOffset from "globals.kcl"
// Sketch the brake caliper profile
brakeCaliperSketch = startSketchOn(XY)

View File

@ -4,8 +4,8 @@
// Set units
@settings(defaultLengthUnit = in)
// Import parameters
import rotorDiameter, rotorInnerDiameter, rotorSinglePlateThickness, rotorInnerDiameterThickness, lugHolePatternDia, lugSpacing, rotorTotalThickness, spacerPatternDiameter, spacerDiameter, spacerLength, spacerCount, wheelDiameter, lugCount, yAxisOffset, drillAndSlotCount from "parameters.kcl"
// Import Constants
import rotorDiameter, rotorInnerDiameter, rotorSinglePlateThickness, rotorInnerDiameterThickness, lugHolePatternDia, lugSpacing, rotorTotalThickness, spacerPatternDiameter, spacerDiameter, spacerLength, spacerCount, wheelDiameter, lugCount, yAxisOffset, drillAndSlotCount from "globals.kcl"
rotorSketch = startSketchOn(XZ)
|> circle(center = [0, 0], radius = rotorDiameter / 2)

View File

@ -4,8 +4,8 @@
// Set units
@settings(defaultLengthUnit = in)
// Import parameters
import tireInnerDiameter, tireOuterDiameter, tireDepth, bendRadius, tireTreadWidth, tireTreadDepth, tireTreadOffset from "parameters.kcl"
// Import Constants
import tireInnerDiameter, tireOuterDiameter, tireDepth, bendRadius, tireTreadWidth, tireTreadDepth, tireTreadOffset from "globals.kcl"
// Create the sketch of the tire
tireSketch = startSketchOn(XY)

View File

@ -4,8 +4,8 @@
// Set units
@settings(defaultLengthUnit = in)
// Import parameters
import lugCount, lugSpacing, offset, backSpacing, wheelWidth, wheelDiameter, spokeCount, spokeGap, spokeAngle, spokeThickness from "parameters.kcl"
// Import Constants
import lugCount, lugSpacing, offset, backSpacing, wheelWidth, wheelDiameter, spokeCount, spokeGap, spokeAngle, spokeThickness from "globals.kcl"
// Create the wheel center
lugBase = startSketchOn(XZ)

View File

@ -1,9 +1,9 @@
// Car wheel assembly parameters
// Car wheel assembly global constants
// Set units
@settings(defaultLengthUnit = in)
// Car wheel
// Car Wheel
export lugCount = 5
export lugSpacing = 114.3 * mm()
export offset = -35 * mm()
@ -22,7 +22,7 @@ export lugThreadDiameter = lugDiameter / 2 * .85
export lugLength = 30 * mm()
export lugThreadDepth = lugLength - (12.7 * mm())
// Car rotor
// Car Rotor
export rotorDiameter = 12
export rotorInnerDiameter = 6
export rotorSinglePlateThickness = 0.25
@ -36,7 +36,7 @@ export spacerCount = 16
export yAxisOffset = 0.5
export drillAndSlotCount = 5
// Car tire
// Car Tire
export tireInnerDiameter = 19
export tireOuterDiameter = 24
export tireDepth = 11.02
@ -45,7 +45,7 @@ export tireTreadWidth = 0.39
export tireTreadDepth = 0.39
export tireTreadOffset = 3.15
// Brake caliper
// Brake Caliper
export caliperTolerance = 0.050
export caliperPadLength = 1.6
export caliperThickness = 0.39

View File

@ -4,8 +4,8 @@
// Set units
@settings(defaultLengthUnit = in)
// Import parameters
import lugDiameter, lugHeadLength, lugThreadDiameter, lugLength, lugThreadDepth, lugSpacing from "parameters.kcl"
// Import Constants
import lugDiameter, lugHeadLength, lugThreadDiameter, lugLength, lugThreadDepth, lugSpacing from "globals.kcl"
customPlane = {
plane = {
@ -23,7 +23,7 @@ customPlane = {
fn lug(plane, length, diameter) {
lugSketch = startSketchOn(customPlane)
|> startProfileAt([0 + diameter / 2, 0], %)
|> angledLine(angle = 70, lengthY = lugHeadLength)
|> angledLineOfYLength({ angle = 70, length = lugHeadLength }, %)
|> xLine(endAbsolute = lugDiameter / 2)
|> yLine(endAbsolute = lugLength)
|> tangentialArc({ offset = 90, radius = 3 * mm() }, %)

View File

@ -4,24 +4,16 @@
// Set units
@settings(defaultLengthUnit = in)
// Import parts
import "car-wheel.kcl" as carWheel
import "car-rotor.kcl" as carRotor
import "brake-caliper.kcl" as brakeCaliper
import "lug-nut.kcl" as lugNut
import "car-tire.kcl" as carTire
import lugCount from "globals.kcl"
// Import parameters
import * from "parameters.kcl"
// Place the car rotor
carRotor
|> translate(x = 0, y = 0.5, z = 0)
// Place the car wheel
carWheel
// Place the lug nuts
lugNut
|> patternCircular3d(
arcDegrees = 360,
@ -30,10 +22,6 @@ lugNut
instances = lugCount,
rotateDuplicates = false,
)
// Place the brake caliper
brakeCaliper
|> translate(x = 0, y = 0.5, z = 0)
// Place the car tire
carTire

Some files were not shown because too many files have changed in this diff Show More