Compare commits
36 Commits
kcl-82
...
jtran/anim
Author | SHA1 | Date | |
---|---|---|---|
bfefa0f51a | |||
0ad619e1d2 | |||
8d876a806e | |||
c7f0a6c2a0 | |||
e4941cb524 | |||
1b687a82a6 | |||
1bb882acf8 | |||
478bf34f2b | |||
dbc87292e4 | |||
bb3a74076f | |||
0cd6031aae | |||
1e1bdbd6e7 | |||
631b63b1b6 | |||
eabcf86436 | |||
7ce0ef770a | |||
599ab33e40 | |||
c584d942d4 | |||
35b8872678 | |||
2f245fe445 | |||
4b95980e9e | |||
53d6613d0d | |||
416d0b37a2 | |||
5f2a10ec7e | |||
24edb66b3c | |||
903ba33c46 | |||
c5bf6ad42d | |||
eeaa71142a | |||
0d1fc1b513 | |||
d510e58ebc | |||
23a01e86e6 | |||
9dd6e3e852 | |||
9eaacc2a51 | |||
de6e0f6b18 | |||
d02a9f59ae | |||
92f930dfc0 | |||
e651e0c2cf |
@ -9,6 +9,7 @@ VITE_KC_SITE_BASE_URL=https://dev.zoo.dev
|
|||||||
VITE_KC_SITE_APP_URL=https://app.dev.zoo.dev
|
VITE_KC_SITE_APP_URL=https://app.dev.zoo.dev
|
||||||
VITE_KC_SKIP_AUTH=false
|
VITE_KC_SKIP_AUTH=false
|
||||||
VITE_KC_CONNECTION_TIMEOUT_MS=5000
|
VITE_KC_CONNECTION_TIMEOUT_MS=5000
|
||||||
|
#VITE_WASM_URL="optional way of overriding the wasm url, particular for unit tests which need this if you running not on the default 3000 port"
|
||||||
#VITE_KC_DEV_TOKEN="optional token to skip auth in the app"
|
#VITE_KC_DEV_TOKEN="optional token to skip auth in the app"
|
||||||
#token="required token for playwright. TODO: clean up env vars in #3973"
|
#token="required token for playwright. TODO: clean up env vars in #3973"
|
||||||
|
|
||||||
|
11
.github/ISSUE_TEMPLATE/release.md
vendored
@ -2,7 +2,7 @@
|
|||||||
name: Release
|
name: Release
|
||||||
about: Create a new release for the Zoo Design Studio
|
about: Create a new release for the Zoo Design Studio
|
||||||
title: "Cut release v1.?.?"
|
title: "Cut release v1.?.?"
|
||||||
labels: [release]
|
labels: [meta/release]
|
||||||
---
|
---
|
||||||
|
|
||||||
> Instructions: https://github.com/KittyCAD/modeling-app/blob/main/CONTRIBUTING.md#shipping-releases
|
> Instructions: https://github.com/KittyCAD/modeling-app/blob/main/CONTRIBUTING.md#shipping-releases
|
||||||
@ -19,7 +19,8 @@ Release builds URL: ???
|
|||||||
* [ ] Confirm the application opens (dismiss the updater)
|
* [ ] Confirm the application opens (dismiss the updater)
|
||||||
* [ ] Create a project with a basic Text-to-CAD prompt
|
* [ ] Create a project with a basic Text-to-CAD prompt
|
||||||
* [ ] Confirm the result is viewable in an engine stream
|
* [ ] Confirm the result is viewable in an engine stream
|
||||||
* [ ] Open the application again and confirm the updater can downgrade
|
* [ ] Use 'Check for updates' to bring back the updater toast
|
||||||
|
* [ ] Confirm the app can update to the previous release
|
||||||
|
|
||||||
## macOS via ???
|
## macOS via ???
|
||||||
|
|
||||||
@ -27,7 +28,8 @@ Release builds URL: ???
|
|||||||
* [ ] Confirm the application opens (dismiss the updater)
|
* [ ] Confirm the application opens (dismiss the updater)
|
||||||
* [ ] Create a project with a basic Text-to-CAD prompt
|
* [ ] Create a project with a basic Text-to-CAD prompt
|
||||||
* [ ] Confirm the result is viewable in an engine stream
|
* [ ] Confirm the result is viewable in an engine stream
|
||||||
* [ ] Open the application again and confirm the updater can downgrade
|
* [ ] Use 'Check for updates' to bring back the updater toast
|
||||||
|
* [ ] Confirm the app can update to the previous release
|
||||||
|
|
||||||
## Linux via ???
|
## Linux via ???
|
||||||
|
|
||||||
@ -35,4 +37,5 @@ Release builds URL: ???
|
|||||||
* [ ] Confirm the application opens (dismiss the updater)
|
* [ ] Confirm the application opens (dismiss the updater)
|
||||||
* [ ] Create a project with a basic Text-to-CAD prompt
|
* [ ] Create a project with a basic Text-to-CAD prompt
|
||||||
* [ ] Confirm the result is viewable in an engine stream
|
* [ ] Confirm the result is viewable in an engine stream
|
||||||
* [ ] Open the application again and confirm the updater can downgrade
|
* [ ] Use 'Check for updates' to bring back the updater toast
|
||||||
|
* [ ] Confirm the app can update to the previous release
|
||||||
|
@ -280,6 +280,9 @@ Assign someone to each section of the manual checklist generated by the issue te
|
|||||||
Follow the instructions [here](./rust/README.md) to publish new crates.
|
Follow the instructions [here](./rust/README.md) to publish new crates.
|
||||||
This ensures that the KCL accepted by the app is also accepted by the CLI.
|
This ensures that the KCL accepted by the app is also accepted by the CLI.
|
||||||
|
|
||||||
|
If there are documentation changes, merge the corresponding Dependabot PRs [here](https://github.com/KittyCAD/website/pulls/app%2Fdependabot) for the website.
|
||||||
|
You can trigger Dependabot to check for updates [here](https://github.com/KittyCAD/website/network/updates/17261214/jobs).
|
||||||
|
|
||||||
#### 5. Publish the release
|
#### 5. Publish the release
|
||||||
|
|
||||||
Head over to https://github.com/KittyCAD/modeling-app/releases/new, pick the newly created tag and type it in the **Release title** field as well.
|
Head over to https://github.com/KittyCAD/modeling-app/releases/new, pick the newly created tag and type it in the **Release title** field as well.
|
||||||
|
@ -83,6 +83,13 @@ Allow orbiting in sketch mode.
|
|||||||
Whether to show the debug panel, which lets you see various states of the app to aid in development.
|
Whether to show the debug panel, which lets you see various states of the app to aid in development.
|
||||||
|
|
||||||
|
|
||||||
|
**Default:** None
|
||||||
|
|
||||||
|
##### fixed_size_grid
|
||||||
|
|
||||||
|
If true, the grid cells will be fixed-size, where the width is your default length unit. If false, the grid will get larger as you zoom out, and smaller as you zoom in.
|
||||||
|
|
||||||
|
|
||||||
**Default:** None
|
**Default:** None
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,9 +10,11 @@ Extend the current sketch with a new involute circular curve.
|
|||||||
```kcl
|
```kcl
|
||||||
involuteCircular(
|
involuteCircular(
|
||||||
@sketch: Sketch,
|
@sketch: Sketch,
|
||||||
startRadius: number(Length),
|
|
||||||
endRadius: number(Length),
|
|
||||||
angle: number(Angle),
|
angle: number(Angle),
|
||||||
|
startRadius?: number(Length),
|
||||||
|
endRadius?: number(Length),
|
||||||
|
startDiameter?: number(Length),
|
||||||
|
endDiameter?: number(Length),
|
||||||
reverse?: bool,
|
reverse?: bool,
|
||||||
tag?: TagDecl,
|
tag?: TagDecl,
|
||||||
): Sketch
|
): Sketch
|
||||||
@ -25,9 +27,11 @@ involuteCircular(
|
|||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `sketch` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) | Which sketch should this path be added to? | Yes |
|
| `sketch` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) | Which sketch should this path be added to? | Yes |
|
||||||
| `startRadius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The involute is described between two circles, start_radius is the radius of the inner circle. | Yes |
|
|
||||||
| `endRadius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The involute is described between two circles, end_radius is the radius of the outer circle. | Yes |
|
|
||||||
| `angle` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | The angle to rotate the involute by. A value of zero will produce a curve with a tangent along the x-axis at the start point of the curve. | Yes |
|
| `angle` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | The angle to rotate the involute by. A value of zero will produce a curve with a tangent along the x-axis at the start point of the curve. | Yes |
|
||||||
|
| `startRadius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The involute is described between two circles, startRadius is the radius of the inner circle. Either `startRadius` or `startDiameter` must be given (but not both). | No |
|
||||||
|
| `endRadius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The involute is described between two circles, endRadius is the radius of the outer circle. Either `endRadius` or `endDiameter` must be given (but not both). | No |
|
||||||
|
| `startDiameter` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The involute is described between two circles, startDiameter describes the inner circle. Either `startRadius` or `startDiameter` must be given (but not both). | No |
|
||||||
|
| `endDiameter` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The involute is described between two circles, endDiameter describes the outer circle. Either `endRadius` or `endDiameter` must be given (but not both). | No |
|
||||||
| `reverse` | [`bool`](/docs/kcl-std/types/std-types-bool) | If reverse is true, the segment will start from the end of the involute, otherwise it will start from that start. | No |
|
| `reverse` | [`bool`](/docs/kcl-std/types/std-types-bool) | If reverse is true, the segment will start from the end of the involute, otherwise it will start from that start. | No |
|
||||||
| `tag` | [`TagDecl`](/docs/kcl-std/types/std-types-TagDecl) | Create a new tag which refers to this line. | No |
|
| `tag` | [`TagDecl`](/docs/kcl-std/types/std-types-TagDecl) | Create a new tag which refers to this line. | No |
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ revolved around the same axis.
|
|||||||
| `sketches` | [`[Sketch; 1+]`](/docs/kcl-std/types/std-types-Sketch) | The sketch or set of sketches that should be revolved | Yes |
|
| `sketches` | [`[Sketch; 1+]`](/docs/kcl-std/types/std-types-Sketch) | The sketch or set of sketches that should be revolved | Yes |
|
||||||
| `axis` | [`Axis2d`](/docs/kcl-std/types/std-types-Axis2d) or [`Edge`](/docs/kcl-std/types/std-types-Edge) | Axis of revolution. | Yes |
|
| `axis` | [`Axis2d`](/docs/kcl-std/types/std-types-Axis2d) or [`Edge`](/docs/kcl-std/types/std-types-Edge) | Axis of revolution. | Yes |
|
||||||
| `angle` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | Angle to revolve (in degrees). Default is 360. | No |
|
| `angle` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | Angle to revolve (in degrees). Default is 360. | No |
|
||||||
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Tolerance for the revolve operation. | No |
|
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Defines the smallest distance below which two entities are considered coincident, intersecting, coplanar, or similar. For most use cases, it should not be changed from its default value of 10^-7 millimeters. | No |
|
||||||
| `symmetric` | [`bool`](/docs/kcl-std/types/std-types-bool) | If true, the extrusion will happen symmetrically around the sketch. Otherwise, the extrusion will happen on only one side of the sketch. | No |
|
| `symmetric` | [`bool`](/docs/kcl-std/types/std-types-bool) | If true, the extrusion will happen symmetrically around the sketch. Otherwise, the extrusion will happen on only one side of the sketch. | No |
|
||||||
| `bidirectionalAngle` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | If specified, will also revolve in the opposite direction to 'angle' to the specified angle. If 'symmetric' is true, this value is ignored. | No |
|
| `bidirectionalAngle` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | If specified, will also revolve in the opposite direction to 'angle' to the specified angle. If 'symmetric' is true, this value is ignored. | No |
|
||||||
| `tagStart` | [`TagDecl`](/docs/kcl-std/types/std-types-TagDecl) | A named tag for the face at the start of the revolve, i.e. the original sketch. | No |
|
| `tagStart` | [`TagDecl`](/docs/kcl-std/types/std-types-TagDecl) | A named tag for the face at the start of the revolve, i.e. the original sketch. | No |
|
||||||
|
@ -28,7 +28,7 @@ will smoothly blend the transition.
|
|||||||
| `solid` | [`Solid`](/docs/kcl-std/types/std-types-Solid) | The solid whose edges should be filletted | Yes |
|
| `solid` | [`Solid`](/docs/kcl-std/types/std-types-Solid) | The solid whose edges should be filletted | Yes |
|
||||||
| `radius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The radius of the fillet | Yes |
|
| `radius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The radius of the fillet | Yes |
|
||||||
| `tags` | [`[Edge; 1+]`](/docs/kcl-std/types/std-types-Edge) | The paths you want to fillet | Yes |
|
| `tags` | [`[Edge; 1+]`](/docs/kcl-std/types/std-types-Edge) | The paths you want to fillet | Yes |
|
||||||
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The tolerance for this fillet | No |
|
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Defines the smallest distance below which two entities are considered coincident, intersecting, coplanar, or similar. For most use cases, it should not be changed from its default value of 10^-7 millimeters. | No |
|
||||||
| `tag` | [`TagDecl`](/docs/kcl-std/types/std-types-TagDecl) | Create a new tag which refers to this fillet | No |
|
| `tag` | [`TagDecl`](/docs/kcl-std/types/std-types-TagDecl) | Create a new tag which refers to this fillet | No |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
@ -24,7 +24,7 @@ verifying fit, and analyzing overlapping geometries in assemblies.
|
|||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `solids` | `[Solid; 2+]` | The solids to intersect. | Yes |
|
| `solids` | `[Solid; 2+]` | The solids to intersect. | Yes |
|
||||||
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The tolerance to use for the intersection operation. | No |
|
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Defines the smallest distance below which two entities are considered coincident, intersecting, coplanar, or similar. For most use cases, it should not be changed from its default value of 10^-7 millimeters. | No |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ and complex multi-body part modeling.
|
|||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `solids` | [`[Solid; 1+]`](/docs/kcl-std/types/std-types-Solid) | The solids to use as the base to subtract from. | Yes |
|
| `solids` | [`[Solid; 1+]`](/docs/kcl-std/types/std-types-Solid) | The solids to use as the base to subtract from. | Yes |
|
||||||
| `tools` | [`[Solid]`](/docs/kcl-std/types/std-types-Solid) | The solids to subtract. | Yes |
|
| `tools` | [`[Solid]`](/docs/kcl-std/types/std-types-Solid) | The solids to subtract. | Yes |
|
||||||
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The tolerance to use for the subtraction operation. | No |
|
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Defines the smallest distance below which two entities are considered coincident, intersecting, coplanar, or similar. For most use cases, it should not be changed from its default value of 10^-7 millimeters. | No |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ union(
|
|||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `solids` | `[Solid; 2+]` | The solids to union. | Yes |
|
| `solids` | `[Solid; 2+]` | The solids to union. | Yes |
|
||||||
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The tolerance to use for the union operation. | No |
|
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Defines the smallest distance below which two entities are considered coincident, intersecting, coplanar, or similar. For most use cases, it should not be changed from its default value of 10^-7 millimeters. | No |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
|
@ -265,6 +265,8 @@ middle(0)
|
|||||||
})
|
})
|
||||||
await expect(
|
await expect(
|
||||||
page.getByText(`assert failed: Expected 0 to be greater than 0 but it wasn't
|
page.getByText(`assert failed: Expected 0 to be greater than 0 but it wasn't
|
||||||
|
|
||||||
|
Backtrace:
|
||||||
assert()
|
assert()
|
||||||
check()
|
check()
|
||||||
middle()`)
|
middle()`)
|
||||||
|
@ -307,7 +307,7 @@ test.describe('Command bar tests', () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const continueButton = page.getByRole('button', { name: 'Continue' })
|
const continueButton = page.getByRole('button', { name: 'Continue' })
|
||||||
const submitButton = page.getByRole('button', { name: 'Submit command' })
|
const submitButton = page.getByTestId('command-bar-submit')
|
||||||
await continueButton.click()
|
await continueButton.click()
|
||||||
|
|
||||||
// Review step and argument hotkeys
|
// Review step and argument hotkeys
|
||||||
|
@ -54,9 +54,7 @@ test(
|
|||||||
await page.keyboard.press('Enter')
|
await page.keyboard.press('Enter')
|
||||||
|
|
||||||
// Click the checkbox
|
// Click the checkbox
|
||||||
const submitButton = page.getByText('Confirm Export')
|
await cmdBar.submit()
|
||||||
await expect(submitButton).toBeVisible()
|
|
||||||
await page.keyboard.press('Enter')
|
|
||||||
|
|
||||||
// Expect it to succeed
|
// Expect it to succeed
|
||||||
const errorToastMessage = page.getByText(`Error while exporting`)
|
const errorToastMessage = page.getByText(`Error while exporting`)
|
||||||
@ -119,9 +117,7 @@ test(
|
|||||||
await page.keyboard.press('Enter')
|
await page.keyboard.press('Enter')
|
||||||
|
|
||||||
// Click the checkbox
|
// Click the checkbox
|
||||||
const submitButton = page.getByText('Confirm Export')
|
await cmdBar.submit()
|
||||||
await expect(submitButton).toBeVisible()
|
|
||||||
await page.keyboard.press('Enter')
|
|
||||||
|
|
||||||
// Look out for the toast message
|
// Look out for the toast message
|
||||||
const exportingToastMessage = page.getByText(`Exporting...`)
|
const exportingToastMessage = page.getByText(`Exporting...`)
|
||||||
|
@ -1617,4 +1617,33 @@ sketch001 = startSketchOn(XZ)
|
|||||||
// Verify error is still visible
|
// Verify error is still visible
|
||||||
await expect(page.locator('.cm-lint-marker-error')).toHaveCount(1)
|
await expect(page.locator('.cm-lint-marker-error')).toHaveCount(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('Core dump hotkey', async ({ page, scene, cmdBar, homePage }) => {
|
||||||
|
await page.addInitScript(async () => {
|
||||||
|
localStorage.setItem(
|
||||||
|
'persistCode',
|
||||||
|
`sketch001 = startSketchOn(XZ)
|
||||||
|
profile001 = circle(sketch001, center = [-100.0, -100.0], radius = 50.0)
|
||||||
|
`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const viewportSize = { width: 1200, height: 800 }
|
||||||
|
await page.setBodyDimensions(viewportSize)
|
||||||
|
|
||||||
|
await homePage.goToModelingScene()
|
||||||
|
|
||||||
|
await scene.connectionEstablished()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
|
const modifier = process.platform === 'darwin' ? 'Meta' : 'Control'
|
||||||
|
|
||||||
|
await page.keyboard.press(`${modifier}+Shift+.`)
|
||||||
|
|
||||||
|
const toast1 = page.getByText('Starting core dump...')
|
||||||
|
await expect(toast1).toBeVisible()
|
||||||
|
|
||||||
|
const toast2 = page.getByText('Core dump completed')
|
||||||
|
await expect(toast2).toBeVisible()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -229,11 +229,12 @@ test.describe('Feature Tree pane', () => {
|
|||||||
const initialCode = `sketch001 = startSketchOn(XZ)
|
const initialCode = `sketch001 = startSketchOn(XZ)
|
||||||
|> circle(center = [0, 0], radius = 5)
|
|> circle(center = [0, 0], radius = 5)
|
||||||
renamedExtrude = extrude(sketch001, length = ${initialInput})`
|
renamedExtrude = extrude(sketch001, length = ${initialInput})`
|
||||||
const newConstantName = 'length001'
|
const newParameterName = 'length001'
|
||||||
const expectedCode = `${newConstantName} = 23
|
const expectedCode = `${newParameterName} = 23
|
||||||
sketch001 = startSketchOn(XZ)
|
sketch001 = startSketchOn(XZ)
|
||||||
|> circle(center = [0, 0], radius = 5)
|
|> circle(center = [0, 0], radius = 5)
|
||||||
renamedExtrude = extrude(sketch001, length = ${newConstantName})`
|
renamedExtrude = extrude(sketch001, length = ${newParameterName})`
|
||||||
|
const editedParameterValue = '23 * 2'
|
||||||
|
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const testDir = join(dir, 'test-sample')
|
const testDir = join(dir, 'test-sample')
|
||||||
@ -279,7 +280,7 @@ test.describe('Feature Tree pane', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('Add a named constant for distance argument and submit', async () => {
|
await test.step('Add a parameter for distance argument and submit', async () => {
|
||||||
await expect(cmdBar.currentArgumentInput).toBeVisible()
|
await expect(cmdBar.currentArgumentInput).toBeVisible()
|
||||||
await cmdBar.variableCheckbox.click()
|
await cmdBar.variableCheckbox.click()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
@ -296,13 +297,43 @@ test.describe('Feature Tree pane', () => {
|
|||||||
highlightedCode: '',
|
highlightedCode: '',
|
||||||
diagnostics: [],
|
diagnostics: [],
|
||||||
activeLines: [
|
activeLines: [
|
||||||
`renamedExtrude = extrude(sketch001, length = ${newConstantName})`,
|
`renamedExtrude = extrude(sketch001, length = ${newParameterName})`,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
await editor.expectEditor.toContain(expectedCode, {
|
await editor.expectEditor.toContain(expectedCode, {
|
||||||
shouldNormalise: true,
|
shouldNormalise: true,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
await test.step('Edit the parameter via the feature tree', async () => {
|
||||||
|
const parameter = await toolbar.getFeatureTreeOperation('Parameter', 0)
|
||||||
|
await parameter.dblclick()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
commandName: 'Edit parameter',
|
||||||
|
currentArgKey: 'value',
|
||||||
|
currentArgValue: '23',
|
||||||
|
headerArguments: {
|
||||||
|
Name: newParameterName,
|
||||||
|
Value: '23',
|
||||||
|
},
|
||||||
|
stage: 'arguments',
|
||||||
|
highlightedHeaderArg: 'value',
|
||||||
|
})
|
||||||
|
await cmdBar.argumentInput
|
||||||
|
.locator('[contenteditable]')
|
||||||
|
.fill(editedParameterValue)
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'review',
|
||||||
|
commandName: 'Edit parameter',
|
||||||
|
headerArguments: {
|
||||||
|
Name: newParameterName,
|
||||||
|
Value: '46', // Shows calculated result
|
||||||
|
},
|
||||||
|
})
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await editor.expectEditor.toContain(editedParameterValue)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
test(`User can edit an offset plane operation from the feature tree`, async ({
|
test(`User can edit an offset plane operation from the feature tree`, async ({
|
||||||
context,
|
context,
|
||||||
|
@ -118,15 +118,11 @@ export class CmdBarFixture {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const arrowButton = this.page.getByRole('button', {
|
const arrowButton = this.page.getByTestId('command-bar-continue')
|
||||||
name: 'arrow right Continue',
|
|
||||||
})
|
|
||||||
if (await arrowButton.isVisible()) {
|
if (await arrowButton.isVisible()) {
|
||||||
await arrowButton.click()
|
await this.continue()
|
||||||
} else {
|
} else {
|
||||||
await this.page
|
await this.submit()
|
||||||
.getByRole('button', { name: 'checkmark Submit command' })
|
|
||||||
.click()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,6 +187,13 @@ export class CmdBarFixture {
|
|||||||
return this.page.getByRole('option', options)
|
return this.page.getByRole('option', options)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select an optional argument from the command bar during review
|
||||||
|
*/
|
||||||
|
clickOptionalArgument = async (argName: string) => {
|
||||||
|
await this.page.getByTestId(`cmd-bar-add-optional-arg-${argName}`).click()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clicks the Create new variable button for kcl input
|
* Clicks the Create new variable button for kcl input
|
||||||
*/
|
*/
|
||||||
|
@ -183,14 +183,15 @@ export class EditorFixture {
|
|||||||
scrollToText(text: string, placeCursor?: boolean) {
|
scrollToText(text: string, placeCursor?: boolean) {
|
||||||
return this.page.evaluate(
|
return this.page.evaluate(
|
||||||
(args: { text: string; placeCursor?: boolean }) => {
|
(args: { text: string; placeCursor?: boolean }) => {
|
||||||
|
const editorView = window.editorManager.getEditorView()
|
||||||
// error TS2339: Property 'docView' does not exist on type 'EditorView'.
|
// error TS2339: Property 'docView' does not exist on type 'EditorView'.
|
||||||
// Except it does so :shrug:
|
// Except it does so :shrug:
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
let index = window.editorManager._editorView?.docView.view.state.doc
|
const index = editorView?.docView.view.state.doc
|
||||||
.toString()
|
.toString()
|
||||||
.indexOf(args.text)
|
.indexOf(args.text)
|
||||||
window.editorManager._editorView?.focus()
|
editorView?.focus()
|
||||||
window.editorManager._editorView?.dispatch({
|
editorView?.dispatch({
|
||||||
selection: window.EditorSelection.create([
|
selection: window.EditorSelection.create([
|
||||||
window.EditorSelection.cursor(index),
|
window.EditorSelection.cursor(index),
|
||||||
]),
|
]),
|
||||||
|
@ -5,7 +5,7 @@ import type {
|
|||||||
FullResult,
|
FullResult,
|
||||||
} from '@playwright/test/reporter'
|
} from '@playwright/test/reporter'
|
||||||
|
|
||||||
class MyAPIReporter implements Reporter {
|
class APIReporter implements Reporter {
|
||||||
private pendingRequests: Promise<void>[] = []
|
private pendingRequests: Promise<void>[] = []
|
||||||
private allResults: Record<string, any>[] = []
|
private allResults: Record<string, any>[] = []
|
||||||
private blockingResults: Record<string, any>[] = []
|
private blockingResults: Record<string, any>[] = []
|
||||||
@ -32,7 +32,7 @@ class MyAPIReporter implements Reporter {
|
|||||||
'X-API-Key': process.env.TAB_API_KEY || '',
|
'X-API-Key': process.env.TAB_API_KEY || '',
|
||||||
}),
|
}),
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
project: 'https://github.com/KittyCAD/modeling-app',
|
project: `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}`,
|
||||||
branch:
|
branch:
|
||||||
process.env.GITHUB_HEAD_REF || process.env.GITHUB_REF_NAME || '',
|
process.env.GITHUB_HEAD_REF || process.env.GITHUB_REF_NAME || '',
|
||||||
commit: process.env.CI_COMMIT_SHA || process.env.GITHUB_SHA || '',
|
commit: process.env.CI_COMMIT_SHA || process.env.GITHUB_SHA || '',
|
||||||
@ -60,7 +60,7 @@ class MyAPIReporter implements Reporter {
|
|||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
// Required information
|
// Required information
|
||||||
project: 'https://github.com/KittyCAD/modeling-app',
|
project: `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}`,
|
||||||
suite: process.env.CI_SUITE || 'e2e',
|
suite: process.env.CI_SUITE || 'e2e',
|
||||||
branch: process.env.GITHUB_HEAD_REF || process.env.GITHUB_REF_NAME || '',
|
branch: process.env.GITHUB_HEAD_REF || process.env.GITHUB_REF_NAME || '',
|
||||||
commit: process.env.CI_COMMIT_SHA || process.env.GITHUB_SHA || '',
|
commit: process.env.CI_COMMIT_SHA || process.env.GITHUB_SHA || '',
|
||||||
@ -124,4 +124,4 @@ class MyAPIReporter implements Reporter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default MyAPIReporter
|
export default APIReporter
|
||||||
|
@ -1083,14 +1083,13 @@ openSketch = startSketchOn(XY)
|
|||||||
cmdBar,
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
// One dumb hardcoded screen pixel value
|
// One dumb hardcoded screen pixel value
|
||||||
const testPoint = { x: 700, y: 150 }
|
const testPoint = { x: 700, y: 200 }
|
||||||
|
// TODO: replace the testPoint selection with a feature tree click once that's supported #7544
|
||||||
const [clickOnXzPlane] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
const [clickOnXzPlane] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
||||||
const expectedOutput = `plane001 = offsetPlane(XZ, offset = 5)`
|
const expectedOutput = `plane001 = offsetPlane(XZ, offset = 5)`
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
// FIXME: Since there is no KCL code loaded. We need to wait for the scene to load before we continue.
|
await scene.settled(cmdBar)
|
||||||
// The engine may not be connected
|
|
||||||
await page.waitForTimeout(15000)
|
|
||||||
|
|
||||||
await test.step(`Look for the blue of the XZ plane`, async () => {
|
await test.step(`Look for the blue of the XZ plane`, async () => {
|
||||||
//await scene.expectPixelColor([50, 51, 96], testPoint, 15) // FIXME
|
//await scene.expectPixelColor([50, 51, 96], testPoint, 15) // FIXME
|
||||||
@ -1611,6 +1610,8 @@ sketch002 = startSketchOn(plane001)
|
|||||||
testPoint.y + 80
|
testPoint.y + 80
|
||||||
)
|
)
|
||||||
const loftDeclaration = 'loft001 = loft([sketch001, sketch002])'
|
const loftDeclaration = 'loft001 = loft([sketch001, sketch002])'
|
||||||
|
const editedLoftDeclaration =
|
||||||
|
'loft001 = loft([sketch001, sketch002], vDegree = 3)'
|
||||||
|
|
||||||
await test.step(`Look for the white of the sketch001 shape`, async () => {
|
await test.step(`Look for the white of the sketch001 shape`, async () => {
|
||||||
await scene.expectPixelColor([254, 254, 254], testPoint, 15)
|
await scene.expectPixelColor([254, 254, 254], testPoint, 15)
|
||||||
@ -1682,6 +1683,39 @@ sketch002 = startSketchOn(plane001)
|
|||||||
await scene.expectPixelColor([89, 89, 89], testPoint, 15)
|
await scene.expectPixelColor([89, 89, 89], testPoint, 15)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
await test.step('Go through the edit flow via feature tree', async () => {
|
||||||
|
await toolbar.openPane('feature-tree')
|
||||||
|
const op = await toolbar.getFeatureTreeOperation('Loft', 0)
|
||||||
|
await op.dblclick()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'review',
|
||||||
|
headerArguments: {},
|
||||||
|
commandName: 'Loft',
|
||||||
|
})
|
||||||
|
await cmdBar.clickOptionalArgument('vDegree')
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'arguments',
|
||||||
|
currentArgKey: 'vDegree',
|
||||||
|
currentArgValue: '',
|
||||||
|
headerArguments: {
|
||||||
|
VDegree: '',
|
||||||
|
},
|
||||||
|
highlightedHeaderArg: 'vDegree',
|
||||||
|
commandName: 'Loft',
|
||||||
|
})
|
||||||
|
await page.keyboard.insertText('3')
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'review',
|
||||||
|
headerArguments: {
|
||||||
|
VDegree: '3',
|
||||||
|
},
|
||||||
|
commandName: 'Loft',
|
||||||
|
})
|
||||||
|
await cmdBar.submit()
|
||||||
|
await editor.expectEditor.toContain(editedLoftDeclaration)
|
||||||
|
})
|
||||||
|
|
||||||
await test.step('Delete loft via feature tree selection', async () => {
|
await test.step('Delete loft via feature tree selection', async () => {
|
||||||
await editor.closePane()
|
await editor.closePane()
|
||||||
const operationButton = await toolbar.getFeatureTreeOperation('Loft', 0)
|
const operationButton = await toolbar.getFeatureTreeOperation('Loft', 0)
|
||||||
@ -1692,72 +1726,6 @@ sketch002 = startSketchOn(plane001)
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// TODO: merge with above test. Right now we're not able to delete a loft
|
|
||||||
// right after creation via selection for some reason, so we go with a new instance
|
|
||||||
test('Loft and offset plane deletion via selection', async ({
|
|
||||||
context,
|
|
||||||
page,
|
|
||||||
homePage,
|
|
||||||
scene,
|
|
||||||
cmdBar,
|
|
||||||
}) => {
|
|
||||||
const initialCode = `sketch001 = startSketchOn(XZ)
|
|
||||||
|> circle(center = [0, 0], radius = 30)
|
|
||||||
plane001 = offsetPlane(XZ, offset = 50)
|
|
||||||
sketch002 = startSketchOn(plane001)
|
|
||||||
|> circle(center = [0, 0], radius = 20)
|
|
||||||
loft001 = loft([sketch001, sketch002])
|
|
||||||
`
|
|
||||||
await context.addInitScript((initialCode) => {
|
|
||||||
localStorage.setItem('persistCode', initialCode)
|
|
||||||
}, initialCode)
|
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
||||||
await homePage.goToModelingScene()
|
|
||||||
await scene.settled(cmdBar)
|
|
||||||
|
|
||||||
// One dumb hardcoded screen pixel value
|
|
||||||
const testPoint = { x: 575, y: 200 }
|
|
||||||
const [clickOnSketch1] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
|
||||||
const [clickOnSketch2] = scene.makeMouseHelpers(
|
|
||||||
testPoint.x,
|
|
||||||
testPoint.y + 80
|
|
||||||
)
|
|
||||||
|
|
||||||
await test.step(`Delete loft`, async () => {
|
|
||||||
// Check for loft
|
|
||||||
await scene.expectPixelColor([89, 89, 89], testPoint, 15)
|
|
||||||
await clickOnSketch1()
|
|
||||||
await expect(page.locator('.cm-activeLine')).toHaveText(`
|
|
||||||
|> circle(center = [0, 0], radius = 30)
|
|
||||||
`)
|
|
||||||
await page.keyboard.press('Delete')
|
|
||||||
// Check for sketch 1
|
|
||||||
await scene.expectPixelColor([254, 254, 254], testPoint, 15)
|
|
||||||
})
|
|
||||||
|
|
||||||
await test.step('Delete sketch002', async () => {
|
|
||||||
await page.waitForTimeout(1000)
|
|
||||||
await clickOnSketch2()
|
|
||||||
await expect(page.locator('.cm-activeLine')).toHaveText(`
|
|
||||||
|> circle(center = [0, 0], radius = 20)
|
|
||||||
`)
|
|
||||||
await page.keyboard.press('Delete')
|
|
||||||
// Check for plane001
|
|
||||||
await scene.expectPixelColor([228, 228, 228], testPoint, 15)
|
|
||||||
})
|
|
||||||
|
|
||||||
await test.step('Delete plane001', async () => {
|
|
||||||
await page.waitForTimeout(1000)
|
|
||||||
await clickOnSketch2()
|
|
||||||
await expect(page.locator('.cm-activeLine')).toHaveText(`
|
|
||||||
plane001 = offsetPlane(XZ, offset = 50)
|
|
||||||
`)
|
|
||||||
await page.keyboard.press('Delete')
|
|
||||||
// Check for sketch 1
|
|
||||||
await scene.expectPixelColor([254, 254, 254], testPoint, 15)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
const sweepCases = [
|
const sweepCases = [
|
||||||
{
|
{
|
||||||
targetType: 'circle',
|
targetType: 'circle',
|
||||||
@ -1829,7 +1797,6 @@ profile002 = startProfile(sketch002, at = [0, 0])
|
|||||||
currentArgKey: 'sketches',
|
currentArgKey: 'sketches',
|
||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sectional: '',
|
|
||||||
Profiles: '',
|
Profiles: '',
|
||||||
Path: '',
|
Path: '',
|
||||||
},
|
},
|
||||||
@ -1843,7 +1810,6 @@ profile002 = startProfile(sketch002, at = [0, 0])
|
|||||||
currentArgKey: 'path',
|
currentArgKey: 'path',
|
||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sectional: '',
|
|
||||||
Profiles: '1 profile',
|
Profiles: '1 profile',
|
||||||
Path: '',
|
Path: '',
|
||||||
},
|
},
|
||||||
@ -1856,7 +1822,6 @@ profile002 = startProfile(sketch002, at = [0, 0])
|
|||||||
currentArgKey: 'path',
|
currentArgKey: 'path',
|
||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sectional: '',
|
|
||||||
Profiles: '1 profile',
|
Profiles: '1 profile',
|
||||||
Path: '',
|
Path: '',
|
||||||
},
|
},
|
||||||
@ -1869,7 +1834,6 @@ profile002 = startProfile(sketch002, at = [0, 0])
|
|||||||
headerArguments: {
|
headerArguments: {
|
||||||
Profiles: '1 profile',
|
Profiles: '1 profile',
|
||||||
Path: '1 segment',
|
Path: '1 segment',
|
||||||
Sectional: '',
|
|
||||||
},
|
},
|
||||||
stage: 'review',
|
stage: 'review',
|
||||||
})
|
})
|
||||||
@ -1894,6 +1858,9 @@ profile002 = startProfile(sketch002, at = [0, 0])
|
|||||||
0
|
0
|
||||||
)
|
)
|
||||||
await operationButton.dblclick({ button: 'left' })
|
await operationButton.dblclick({ button: 'left' })
|
||||||
|
await page
|
||||||
|
.getByRole('button', { name: 'sectional', exact: false })
|
||||||
|
.click()
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
commandName: 'Sweep',
|
commandName: 'Sweep',
|
||||||
currentArgKey: 'sectional',
|
currentArgKey: 'sectional',
|
||||||
@ -1956,6 +1923,7 @@ profile002 = startProfile(sketch002, at = [0, 0])
|
|||||||
sketch001 = startSketchOn(XZ)
|
sketch001 = startSketchOn(XZ)
|
||||||
profile001 = ${circleCode}`
|
profile001 = ${circleCode}`
|
||||||
const sweepDeclaration = 'sweep001 = sweep(profile001, path = helix001)'
|
const sweepDeclaration = 'sweep001 = sweep(profile001, path = helix001)'
|
||||||
|
const editedSweepDeclaration = `sweep001 = sweep(profile001, path = helix001, relativeTo = 'sketchPlane')`
|
||||||
|
|
||||||
await context.addInitScript((initialCode) => {
|
await context.addInitScript((initialCode) => {
|
||||||
localStorage.setItem('persistCode', initialCode)
|
localStorage.setItem('persistCode', initialCode)
|
||||||
@ -1971,7 +1939,6 @@ profile001 = ${circleCode}`
|
|||||||
currentArgKey: 'sketches',
|
currentArgKey: 'sketches',
|
||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sectional: '',
|
|
||||||
Profiles: '',
|
Profiles: '',
|
||||||
Path: '',
|
Path: '',
|
||||||
},
|
},
|
||||||
@ -1986,7 +1953,6 @@ profile001 = ${circleCode}`
|
|||||||
currentArgKey: 'path',
|
currentArgKey: 'path',
|
||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sectional: '',
|
|
||||||
Profiles: '1 profile',
|
Profiles: '1 profile',
|
||||||
Path: '',
|
Path: '',
|
||||||
},
|
},
|
||||||
@ -2000,7 +1966,6 @@ profile001 = ${circleCode}`
|
|||||||
currentArgKey: 'path',
|
currentArgKey: 'path',
|
||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sectional: '',
|
|
||||||
Profiles: '1 profile',
|
Profiles: '1 profile',
|
||||||
Path: '',
|
Path: '',
|
||||||
},
|
},
|
||||||
@ -2013,7 +1978,6 @@ profile001 = ${circleCode}`
|
|||||||
headerArguments: {
|
headerArguments: {
|
||||||
Profiles: '1 profile',
|
Profiles: '1 profile',
|
||||||
Path: '1 helix',
|
Path: '1 helix',
|
||||||
Sectional: '',
|
|
||||||
},
|
},
|
||||||
stage: 'review',
|
stage: 'review',
|
||||||
})
|
})
|
||||||
@ -2021,11 +1985,43 @@ profile001 = ${circleCode}`
|
|||||||
await editor.expectEditor.toContain(sweepDeclaration)
|
await editor.expectEditor.toContain(sweepDeclaration)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
await test.step('Go through the edit flow via feature tree', async () => {
|
||||||
|
await toolbar.openPane('feature-tree')
|
||||||
|
const op = await toolbar.getFeatureTreeOperation('Sweep', 0)
|
||||||
|
await op.dblclick()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'review',
|
||||||
|
headerArguments: {},
|
||||||
|
commandName: 'Sweep',
|
||||||
|
})
|
||||||
|
await cmdBar.clickOptionalArgument('relativeTo')
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'arguments',
|
||||||
|
currentArgKey: 'relativeTo',
|
||||||
|
currentArgValue: '',
|
||||||
|
headerArguments: {
|
||||||
|
RelativeTo: '',
|
||||||
|
},
|
||||||
|
highlightedHeaderArg: 'relativeTo',
|
||||||
|
commandName: 'Sweep',
|
||||||
|
})
|
||||||
|
await cmdBar.selectOption({ name: 'sketchPlane' }).click()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'review',
|
||||||
|
headerArguments: {
|
||||||
|
RelativeTo: 'sketchPlane',
|
||||||
|
},
|
||||||
|
commandName: 'Sweep',
|
||||||
|
})
|
||||||
|
await cmdBar.submit()
|
||||||
|
await editor.expectEditor.toContain(editedSweepDeclaration)
|
||||||
|
})
|
||||||
|
|
||||||
await test.step('Delete sweep via feature tree selection', async () => {
|
await test.step('Delete sweep via feature tree selection', async () => {
|
||||||
const sweep = await toolbar.getFeatureTreeOperation('Sweep', 0)
|
const sweep = await toolbar.getFeatureTreeOperation('Sweep', 0)
|
||||||
await sweep.click()
|
await sweep.click()
|
||||||
await page.keyboard.press('Delete')
|
await page.keyboard.press('Delete')
|
||||||
await editor.expectEditor.not.toContain(sweepDeclaration)
|
await editor.expectEditor.not.toContain(editedSweepDeclaration)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -3885,6 +3881,8 @@ sketch002 = startSketchOn(extrude001, face = rectangleSegmentA001)
|
|||||||
|
|
||||||
// Edit flow
|
// Edit flow
|
||||||
const newAngle = '270'
|
const newAngle = '270'
|
||||||
|
const newAngle2 = '5'
|
||||||
|
const editedCodeToFind = `revolve001 = revolve(sketch003, angle = ${newAngle}, axis = seg01, bidirectionalAngle = ${newAngle2}, )`
|
||||||
await toolbar.openPane('feature-tree')
|
await toolbar.openPane('feature-tree')
|
||||||
const operationButton = await toolbar.getFeatureTreeOperation(
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
||||||
'Revolve',
|
'Revolve',
|
||||||
@ -3910,11 +3908,33 @@ sketch002 = startSketchOn(extrude001, face = rectangleSegmentA001)
|
|||||||
},
|
},
|
||||||
commandName: 'Revolve',
|
commandName: 'Revolve',
|
||||||
})
|
})
|
||||||
|
await cmdBar.clickOptionalArgument('bidirectionalAngle')
|
||||||
|
await cmdBar.expectState({
|
||||||
|
commandName: 'Revolve',
|
||||||
|
currentArgKey: 'bidirectionalAngle',
|
||||||
|
currentArgValue: '',
|
||||||
|
headerArguments: {
|
||||||
|
Angle: newAngle,
|
||||||
|
BidirectionalAngle: '',
|
||||||
|
},
|
||||||
|
highlightedHeaderArg: 'bidirectionalAngle',
|
||||||
|
stage: 'arguments',
|
||||||
|
})
|
||||||
|
await page.keyboard.insertText(newAngle2)
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'review',
|
||||||
|
headerArguments: {
|
||||||
|
Angle: newAngle,
|
||||||
|
BidirectionalAngle: newAngle2,
|
||||||
|
},
|
||||||
|
commandName: 'Revolve',
|
||||||
|
})
|
||||||
|
await cmdBar.submit()
|
||||||
await toolbar.closePane('feature-tree')
|
await toolbar.closePane('feature-tree')
|
||||||
await editor.expectEditor.toContain(
|
await editor.expectEditor.toContain(editedCodeToFind, {
|
||||||
newCodeToFind.replace('angle = 360', 'angle = ' + newAngle)
|
shouldNormalise: true,
|
||||||
)
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -4734,7 +4754,6 @@ path001 = startProfile(sketch001, at = [0, 0])
|
|||||||
headerArguments: {
|
headerArguments: {
|
||||||
Profiles: '',
|
Profiles: '',
|
||||||
Path: '',
|
Path: '',
|
||||||
Sectional: '',
|
|
||||||
},
|
},
|
||||||
highlightedHeaderArg: 'Profiles',
|
highlightedHeaderArg: 'Profiles',
|
||||||
commandName: 'Sweep',
|
commandName: 'Sweep',
|
||||||
@ -4747,7 +4766,6 @@ path001 = startProfile(sketch001, at = [0, 0])
|
|||||||
headerArguments: {
|
headerArguments: {
|
||||||
Profiles: '2 profiles',
|
Profiles: '2 profiles',
|
||||||
Path: '',
|
Path: '',
|
||||||
Sectional: '',
|
|
||||||
},
|
},
|
||||||
highlightedHeaderArg: 'path',
|
highlightedHeaderArg: 'path',
|
||||||
commandName: 'Sweep',
|
commandName: 'Sweep',
|
||||||
@ -4760,7 +4778,6 @@ path001 = startProfile(sketch001, at = [0, 0])
|
|||||||
headerArguments: {
|
headerArguments: {
|
||||||
Profiles: '2 profiles',
|
Profiles: '2 profiles',
|
||||||
Path: '1 segment',
|
Path: '1 segment',
|
||||||
Sectional: '',
|
|
||||||
},
|
},
|
||||||
commandName: 'Sweep',
|
commandName: 'Sweep',
|
||||||
})
|
})
|
||||||
@ -4932,4 +4949,154 @@ extrude001 = extrude(profile001 length = 1)`
|
|||||||
await editor.expectEditor.toContain(badCode, { shouldNormalise: true })
|
await editor.expectEditor.toContain(badCode, { shouldNormalise: true })
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('Point-and-click extrude with optional args', async ({
|
||||||
|
context,
|
||||||
|
page,
|
||||||
|
homePage,
|
||||||
|
scene,
|
||||||
|
editor,
|
||||||
|
toolbar,
|
||||||
|
cmdBar,
|
||||||
|
}) => {
|
||||||
|
const squareProfileCode = `length001 = 100
|
||||||
|
sketch001 = startSketchOn(XY)
|
||||||
|
profile001 = startProfile(sketch001, at = [0, 0])
|
||||||
|
|> yLine(length = length001)
|
||||||
|
|> xLine(length = length001)
|
||||||
|
|> yLine(length = -length001)
|
||||||
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|
|> close()
|
||||||
|
`
|
||||||
|
await context.addInitScript((initialCode) => {
|
||||||
|
localStorage.setItem('persistCode', initialCode)
|
||||||
|
}, squareProfileCode)
|
||||||
|
await homePage.goToModelingScene()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
|
await test.step('Select through code', async () => {
|
||||||
|
await editor.selectText('startProfile(sketch001, at = [0, 0])')
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('Go through command bar flow', async () => {
|
||||||
|
await toolbar.extrudeButton.click()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'arguments',
|
||||||
|
currentArgKey: 'sketches',
|
||||||
|
currentArgValue: '',
|
||||||
|
headerArguments: {
|
||||||
|
Profiles: '',
|
||||||
|
Length: '',
|
||||||
|
},
|
||||||
|
highlightedHeaderArg: 'Profiles',
|
||||||
|
commandName: 'Extrude',
|
||||||
|
})
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'arguments',
|
||||||
|
currentArgKey: 'length',
|
||||||
|
currentArgValue: '5',
|
||||||
|
headerArguments: {
|
||||||
|
Profiles: '1 profile',
|
||||||
|
Length: '',
|
||||||
|
},
|
||||||
|
highlightedHeaderArg: 'length',
|
||||||
|
commandName: 'Extrude',
|
||||||
|
})
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'review',
|
||||||
|
headerArguments: {
|
||||||
|
Profiles: '1 profile',
|
||||||
|
Length: '5',
|
||||||
|
},
|
||||||
|
commandName: 'Extrude',
|
||||||
|
})
|
||||||
|
await cmdBar.clickOptionalArgument('bidirectionalLength')
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'arguments',
|
||||||
|
currentArgKey: 'bidirectionalLength',
|
||||||
|
currentArgValue: '',
|
||||||
|
headerArguments: {
|
||||||
|
Profiles: '1 profile',
|
||||||
|
Length: '5',
|
||||||
|
BidirectionalLength: '',
|
||||||
|
},
|
||||||
|
highlightedHeaderArg: 'bidirectionalLength',
|
||||||
|
commandName: 'Extrude',
|
||||||
|
})
|
||||||
|
await page.keyboard.insertText('10')
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'review',
|
||||||
|
headerArguments: {
|
||||||
|
Profiles: '1 profile',
|
||||||
|
Length: '5',
|
||||||
|
BidirectionalLength: '10',
|
||||||
|
},
|
||||||
|
commandName: 'Extrude',
|
||||||
|
})
|
||||||
|
await cmdBar.submit()
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('Check that the code has changed', async () => {
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
await editor.expectEditor.toContain(
|
||||||
|
`extrude001 = extrude(profile001, length = 5, bidirectionalLength = 10)`,
|
||||||
|
{ shouldNormalise: true }
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('Go through the edit flow via feature tree', async () => {
|
||||||
|
await toolbar.openPane('feature-tree')
|
||||||
|
const op = await toolbar.getFeatureTreeOperation('Extrude', 0)
|
||||||
|
await op.dblclick()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'arguments',
|
||||||
|
currentArgKey: 'length',
|
||||||
|
currentArgValue: '5',
|
||||||
|
headerArguments: {
|
||||||
|
Length: '5',
|
||||||
|
BidirectionalLength: '10',
|
||||||
|
},
|
||||||
|
highlightedHeaderArg: 'length',
|
||||||
|
commandName: 'Extrude',
|
||||||
|
})
|
||||||
|
await page.keyboard.insertText('10')
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await page.getByRole('button', { name: 'BidirectionalLength' }).click()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'arguments',
|
||||||
|
currentArgKey: 'bidirectionalLength',
|
||||||
|
currentArgValue: '10',
|
||||||
|
headerArguments: {
|
||||||
|
Length: '10',
|
||||||
|
BidirectionalLength: '10',
|
||||||
|
},
|
||||||
|
highlightedHeaderArg: 'bidirectionalLength',
|
||||||
|
commandName: 'Extrude',
|
||||||
|
})
|
||||||
|
await page.keyboard.insertText('20')
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'review',
|
||||||
|
headerArguments: {
|
||||||
|
Length: '10',
|
||||||
|
BidirectionalLength: '20',
|
||||||
|
},
|
||||||
|
commandName: 'Extrude',
|
||||||
|
})
|
||||||
|
await cmdBar.submit()
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('Check that the code has changed again', async () => {
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
await toolbar.closePane('feature-tree')
|
||||||
|
await toolbar.openPane('code')
|
||||||
|
await editor.expectEditor.toContain(
|
||||||
|
`extrude001 = extrude(profile001, length = 10, bidirectionalLength = 20)`,
|
||||||
|
{ shouldNormalise: true }
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -475,6 +475,7 @@ test.describe('Can export from electron app', () => {
|
|||||||
},
|
},
|
||||||
tronApp.projectDirName,
|
tronApp.projectDirName,
|
||||||
page,
|
page,
|
||||||
|
cmdBar,
|
||||||
method
|
method
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -779,9 +780,6 @@ test.describe(`Project management commands`, () => {
|
|||||||
const commandContinueButton = page.getByRole('button', {
|
const commandContinueButton = page.getByRole('button', {
|
||||||
name: 'Continue',
|
name: 'Continue',
|
||||||
})
|
})
|
||||||
const commandSubmitButton = page.getByRole('button', {
|
|
||||||
name: 'Submit command',
|
|
||||||
})
|
|
||||||
const toastMessage = page.getByText(`Successfully renamed`)
|
const toastMessage = page.getByText(`Successfully renamed`)
|
||||||
|
|
||||||
await test.step(`Setup`, async () => {
|
await test.step(`Setup`, async () => {
|
||||||
@ -800,8 +798,7 @@ test.describe(`Project management commands`, () => {
|
|||||||
await expect(commandContinueButton).toBeVisible()
|
await expect(commandContinueButton).toBeVisible()
|
||||||
await commandContinueButton.click()
|
await commandContinueButton.click()
|
||||||
|
|
||||||
await expect(commandSubmitButton).toBeVisible()
|
await cmdBar.submit()
|
||||||
await commandSubmitButton.click()
|
|
||||||
|
|
||||||
await expect(toastMessage).toBeVisible()
|
await expect(toastMessage).toBeVisible()
|
||||||
})
|
})
|
||||||
@ -837,9 +834,6 @@ test.describe(`Project management commands`, () => {
|
|||||||
})
|
})
|
||||||
const projectNameOption = page.getByRole('option', { name: projectName })
|
const projectNameOption = page.getByRole('option', { name: projectName })
|
||||||
const commandWarning = page.getByText('Are you sure you want to delete?')
|
const commandWarning = page.getByText('Are you sure you want to delete?')
|
||||||
const commandSubmitButton = page.getByRole('button', {
|
|
||||||
name: 'Submit command',
|
|
||||||
})
|
|
||||||
const toastMessage = page.getByText(`Successfully deleted`)
|
const toastMessage = page.getByText(`Successfully deleted`)
|
||||||
const noProjectsMessage = page.getByText('No projects found')
|
const noProjectsMessage = page.getByText('No projects found')
|
||||||
|
|
||||||
@ -859,8 +853,7 @@ test.describe(`Project management commands`, () => {
|
|||||||
await projectNameOption.click()
|
await projectNameOption.click()
|
||||||
|
|
||||||
await expect(commandWarning).toBeVisible()
|
await expect(commandWarning).toBeVisible()
|
||||||
await expect(commandSubmitButton).toBeVisible()
|
await cmdBar.submit()
|
||||||
await commandSubmitButton.click()
|
|
||||||
|
|
||||||
await expect(toastMessage).toBeVisible()
|
await expect(toastMessage).toBeVisible()
|
||||||
})
|
})
|
||||||
@ -894,9 +887,6 @@ test.describe(`Project management commands`, () => {
|
|||||||
const commandContinueButton = page.getByRole('button', {
|
const commandContinueButton = page.getByRole('button', {
|
||||||
name: 'Continue',
|
name: 'Continue',
|
||||||
})
|
})
|
||||||
const commandSubmitButton = page.getByRole('button', {
|
|
||||||
name: 'Submit command',
|
|
||||||
})
|
|
||||||
const toastMessage = page.getByText(`Successfully renamed`)
|
const toastMessage = page.getByText(`Successfully renamed`)
|
||||||
|
|
||||||
await test.step(`Setup`, async () => {
|
await test.step(`Setup`, async () => {
|
||||||
@ -914,8 +904,7 @@ test.describe(`Project management commands`, () => {
|
|||||||
await expect(commandContinueButton).toBeVisible()
|
await expect(commandContinueButton).toBeVisible()
|
||||||
await commandContinueButton.click()
|
await commandContinueButton.click()
|
||||||
|
|
||||||
await expect(commandSubmitButton).toBeVisible()
|
await cmdBar.submit()
|
||||||
await commandSubmitButton.click()
|
|
||||||
|
|
||||||
await expect(toastMessage).toBeVisible()
|
await expect(toastMessage).toBeVisible()
|
||||||
})
|
})
|
||||||
@ -949,9 +938,6 @@ test.describe(`Project management commands`, () => {
|
|||||||
})
|
})
|
||||||
const projectNameOption = page.getByRole('option', { name: projectName })
|
const projectNameOption = page.getByRole('option', { name: projectName })
|
||||||
const commandWarning = page.getByText('Are you sure you want to delete?')
|
const commandWarning = page.getByText('Are you sure you want to delete?')
|
||||||
const commandSubmitButton = page.getByRole('button', {
|
|
||||||
name: 'Submit command',
|
|
||||||
})
|
|
||||||
const toastMessage = page.getByText(`Successfully deleted`)
|
const toastMessage = page.getByText(`Successfully deleted`)
|
||||||
const noProjectsMessage = page.getByText('No projects found')
|
const noProjectsMessage = page.getByText('No projects found')
|
||||||
|
|
||||||
@ -967,8 +953,7 @@ test.describe(`Project management commands`, () => {
|
|||||||
await projectNameOption.click()
|
await projectNameOption.click()
|
||||||
|
|
||||||
await expect(commandWarning).toBeVisible()
|
await expect(commandWarning).toBeVisible()
|
||||||
await expect(commandSubmitButton).toBeVisible()
|
await cmdBar.submit()
|
||||||
await commandSubmitButton.click()
|
|
||||||
|
|
||||||
await expect(toastMessage).toBeVisible()
|
await expect(toastMessage).toBeVisible()
|
||||||
})
|
})
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { bracket } from '@e2e/playwright/fixtures/bracket'
|
import { bracket } from '@e2e/playwright/fixtures/bracket'
|
||||||
import type { Page } from '@playwright/test'
|
import type { Page } from '@playwright/test'
|
||||||
|
import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
|
||||||
import { reportRejection } from '@src/lib/trap'
|
import { reportRejection } from '@src/lib/trap'
|
||||||
import * as fsp from 'fs/promises'
|
import * as fsp from 'fs/promises'
|
||||||
|
|
||||||
@ -421,10 +422,7 @@ extrude002 = extrude(profile002, length = 150)
|
|||||||
await page.keyboard.press('Enter')
|
await page.keyboard.press('Enter')
|
||||||
|
|
||||||
// Click the checkbox
|
// Click the checkbox
|
||||||
const submitButton = page.getByText('Confirm Export')
|
await cmdBar.submit()
|
||||||
await expect(submitButton).toBeVisible()
|
|
||||||
|
|
||||||
await page.keyboard.press('Enter')
|
|
||||||
|
|
||||||
// Find the toast.
|
// Find the toast.
|
||||||
// Look out for the toast message
|
// Look out for the toast message
|
||||||
@ -461,8 +459,7 @@ extrude002 = extrude(profile002, length = 150)
|
|||||||
await page.keyboard.press('Enter')
|
await page.keyboard.press('Enter')
|
||||||
|
|
||||||
// Click the checkbox
|
// Click the checkbox
|
||||||
await expect(submitButton).toBeVisible()
|
await cmdBar.submit()
|
||||||
await page.keyboard.press('Enter')
|
|
||||||
|
|
||||||
// Find the toast.
|
// Find the toast.
|
||||||
// Look out for the toast message
|
// Look out for the toast message
|
||||||
@ -482,6 +479,7 @@ extrude002 = extrude(profile002, length = 150)
|
|||||||
test('ensure you CAN export while an export is already going', async ({
|
test('ensure you CAN export while an export is already going', async ({
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await test.step('Set up the code and durations', async () => {
|
await test.step('Set up the code and durations', async () => {
|
||||||
@ -516,11 +514,11 @@ extrude002 = extrude(profile002, length = 150)
|
|||||||
const successToastMessage = page.getByText(`Exported successfully`)
|
const successToastMessage = page.getByText(`Exported successfully`)
|
||||||
|
|
||||||
await test.step('second export', async () => {
|
await test.step('second export', async () => {
|
||||||
await clickExportButton(page)
|
await clickExportButton(page, cmdBar)
|
||||||
|
|
||||||
await expect(exportingToastMessage).toBeVisible()
|
await expect(exportingToastMessage).toBeVisible()
|
||||||
|
|
||||||
await clickExportButton(page)
|
await clickExportButton(page, cmdBar)
|
||||||
|
|
||||||
await test.step('The first export still succeeds', async () => {
|
await test.step('The first export still succeeds', async () => {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
@ -537,7 +535,7 @@ extrude002 = extrude(profile002, length = 150)
|
|||||||
|
|
||||||
await test.step('Successful, unblocked export', async () => {
|
await test.step('Successful, unblocked export', async () => {
|
||||||
// Try exporting again.
|
// Try exporting again.
|
||||||
await clickExportButton(page)
|
await clickExportButton(page, cmdBar)
|
||||||
|
|
||||||
// Find the toast.
|
// Find the toast.
|
||||||
// Look out for the toast message
|
// Look out for the toast message
|
||||||
@ -880,7 +878,7 @@ s2 = startSketchOn(XY)
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
async function clickExportButton(page: Page) {
|
async function clickExportButton(page: Page, cmdBar: CmdBarFixture) {
|
||||||
await test.step('Running export flow', async () => {
|
await test.step('Running export flow', async () => {
|
||||||
// export the model
|
// export the model
|
||||||
const exportButton = page.getByTestId('export-pane-button')
|
const exportButton = page.getByTestId('export-pane-button')
|
||||||
@ -896,9 +894,6 @@ async function clickExportButton(page: Page) {
|
|||||||
await page.keyboard.press('Enter')
|
await page.keyboard.press('Enter')
|
||||||
|
|
||||||
// Click the checkbox
|
// Click the checkbox
|
||||||
const submitButton = page.getByText('Confirm Export')
|
await cmdBar.submit()
|
||||||
await expect(submitButton).toBeVisible()
|
|
||||||
|
|
||||||
await page.keyboard.press('Enter')
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1478,6 +1478,7 @@ sketch001 = startSketchOn(XZ)
|
|||||||
await page.mouse.move(1200, 139)
|
await page.mouse.move(1200, 139)
|
||||||
await page.mouse.down()
|
await page.mouse.down()
|
||||||
await page.mouse.move(870, 250)
|
await page.mouse.move(870, 250)
|
||||||
|
await page.mouse.up()
|
||||||
|
|
||||||
await page.waitForTimeout(200)
|
await page.waitForTimeout(200)
|
||||||
|
|
||||||
@ -1487,6 +1488,60 @@ sketch001 = startSketchOn(XZ)
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('Can undo with closed code pane', async ({
|
||||||
|
page,
|
||||||
|
homePage,
|
||||||
|
editor,
|
||||||
|
toolbar,
|
||||||
|
scene,
|
||||||
|
cmdBar,
|
||||||
|
}) => {
|
||||||
|
const u = await getUtils(page)
|
||||||
|
|
||||||
|
const viewportSize = { width: 1500, height: 750 }
|
||||||
|
await page.setBodyDimensions(viewportSize)
|
||||||
|
|
||||||
|
await page.addInitScript(async () => {
|
||||||
|
localStorage.setItem(
|
||||||
|
'persistCode',
|
||||||
|
`@settings(defaultLengthUnit=in)
|
||||||
|
sketch001 = startSketchOn(XZ)
|
||||||
|
|> startProfile(at = [-10, -10])
|
||||||
|
|> line(end = [20.0, 10.0])
|
||||||
|
|> tangentialArc(end = [5.49, 8.37])`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
await homePage.goToModelingScene()
|
||||||
|
await toolbar.waitForFeatureTreeToBeBuilt()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
|
await (await toolbar.getFeatureTreeOperation('Sketch', 0)).dblclick()
|
||||||
|
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
|
|
||||||
|
await page.mouse.move(1200, 139)
|
||||||
|
await page.mouse.down()
|
||||||
|
await page.mouse.move(870, 250)
|
||||||
|
await page.mouse.up()
|
||||||
|
|
||||||
|
await editor.expectEditor.toContain(`tangentialArc(end=[-5.85,4.32])`, {
|
||||||
|
shouldNormalise: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
await u.closeKclCodePanel()
|
||||||
|
|
||||||
|
// Undo the last change
|
||||||
|
await page.keyboard.down('Control')
|
||||||
|
await page.keyboard.press('KeyZ')
|
||||||
|
await page.keyboard.up('Control')
|
||||||
|
|
||||||
|
await u.openKclCodePanel()
|
||||||
|
await editor.expectEditor.toContain(`tangentialArc(end = [5.49, 8.37])`, {
|
||||||
|
shouldNormalise: true,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
test('Can delete a single segment line with keyboard', async ({
|
test('Can delete a single segment line with keyboard', async ({
|
||||||
page,
|
page,
|
||||||
scene,
|
scene,
|
||||||
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 75 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 135 KiB |
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 118 KiB |
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 135 KiB |
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 65 KiB |
@ -12,6 +12,7 @@ export const TEST_SETTINGS: DeepPartial<Settings> = {
|
|||||||
},
|
},
|
||||||
onboarding_status: 'dismissed',
|
onboarding_status: 'dismissed',
|
||||||
show_debug_panel: true,
|
show_debug_panel: true,
|
||||||
|
fixed_size_grid: false,
|
||||||
},
|
},
|
||||||
modeling: {
|
modeling: {
|
||||||
enable_ssao: false,
|
enable_ssao: false,
|
||||||
|
@ -22,6 +22,7 @@ export const token = process.env.token || ''
|
|||||||
import type { ProjectConfiguration } from '@rust/kcl-lib/bindings/ProjectConfiguration'
|
import type { ProjectConfiguration } from '@rust/kcl-lib/bindings/ProjectConfiguration'
|
||||||
|
|
||||||
import type { ElectronZoo } from '@e2e/playwright/fixtures/fixtureSetup'
|
import type { ElectronZoo } from '@e2e/playwright/fixtures/fixtureSetup'
|
||||||
|
import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
|
||||||
import { isErrorWhitelisted } from '@e2e/playwright/lib/console-error-whitelist'
|
import { isErrorWhitelisted } from '@e2e/playwright/lib/console-error-whitelist'
|
||||||
import { TEST_SETTINGS, TEST_SETTINGS_KEY } from '@e2e/playwright/storageStates'
|
import { TEST_SETTINGS, TEST_SETTINGS_KEY } from '@e2e/playwright/storageStates'
|
||||||
import { test } from '@e2e/playwright/zoo-test'
|
import { test } from '@e2e/playwright/zoo-test'
|
||||||
@ -158,10 +159,10 @@ async function openKclCodePanel(page: Page) {
|
|||||||
await page.evaluate(() => {
|
await page.evaluate(() => {
|
||||||
// editorManager is available on the window object.
|
// editorManager is available on the window object.
|
||||||
//@ts-ignore this is in an entirely different context that tsc can't see.
|
//@ts-ignore this is in an entirely different context that tsc can't see.
|
||||||
editorManager._editorView.dispatch({
|
editorManager.getEditorView().dispatch({
|
||||||
selection: {
|
selection: {
|
||||||
//@ts-ignore this is in an entirely different context that tsc can't see.
|
//@ts-ignore this is in an entirely different context that tsc can't see.
|
||||||
anchor: editorManager._editorView.docView.length,
|
anchor: editorManager.getEditorView().docView.length,
|
||||||
},
|
},
|
||||||
scrollIntoView: true,
|
scrollIntoView: true,
|
||||||
})
|
})
|
||||||
@ -737,6 +738,7 @@ export const doExport = async (
|
|||||||
output: Models['OutputFormat3d_type'],
|
output: Models['OutputFormat3d_type'],
|
||||||
rootDir: string,
|
rootDir: string,
|
||||||
page: Page,
|
page: Page,
|
||||||
|
cmdBar: CmdBarFixture,
|
||||||
exportFrom: 'dropdown' | 'sidebarButton' | 'commandBar' = 'dropdown'
|
exportFrom: 'dropdown' | 'sidebarButton' | 'commandBar' = 'dropdown'
|
||||||
): Promise<Paths> => {
|
): Promise<Paths> => {
|
||||||
if (exportFrom === 'dropdown') {
|
if (exportFrom === 'dropdown') {
|
||||||
@ -780,9 +782,7 @@ export const doExport = async (
|
|||||||
.click()
|
.click()
|
||||||
await page.locator('#arg-form').waitFor({ state: 'detached' })
|
await page.locator('#arg-form').waitFor({ state: 'detached' })
|
||||||
}
|
}
|
||||||
await expect(page.getByText('Confirm Export')).toBeVisible()
|
await cmdBar.submit()
|
||||||
|
|
||||||
await page.getByRole('button', { name: 'Submit command' }).click()
|
|
||||||
|
|
||||||
await expect(page.getByText('Exported successfully')).toBeVisible()
|
await expect(page.getByText('Exported successfully')).toBeVisible()
|
||||||
|
|
||||||
@ -880,6 +880,10 @@ export async function setup(
|
|||||||
},
|
},
|
||||||
...TEST_SETTINGS.project,
|
...TEST_SETTINGS.project,
|
||||||
onboarding_status: 'dismissed',
|
onboarding_status: 'dismissed',
|
||||||
|
// Tests were written before this setting existed.
|
||||||
|
// It's true by default because it's a good user experience, but
|
||||||
|
// these tests require it to be false.
|
||||||
|
fixed_size_grid: false,
|
||||||
},
|
},
|
||||||
project: {
|
project: {
|
||||||
...TEST_SETTINGS.project,
|
...TEST_SETTINGS.project,
|
||||||
|
@ -10,7 +10,7 @@ import {
|
|||||||
import { expect, test } from '@e2e/playwright/zoo-test'
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
test.describe('Testing constraints', () => {
|
test.describe('Testing constraints', () => {
|
||||||
test('Can constrain line length', async ({ page, homePage }) => {
|
test('Can constrain line length', async ({ page, homePage, cmdBar }) => {
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
@ -50,11 +50,7 @@ test.describe('Testing constraints', () => {
|
|||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await page.getByTestId('constraint-length').click()
|
await page.getByTestId('constraint-length').click()
|
||||||
await page.getByTestId('cmd-bar-arg-value').getByRole('textbox').fill('20')
|
await page.getByTestId('cmd-bar-arg-value').getByRole('textbox').fill('20')
|
||||||
await page
|
await cmdBar.continue()
|
||||||
.getByRole('button', {
|
|
||||||
name: 'arrow right Continue',
|
|
||||||
})
|
|
||||||
.click()
|
|
||||||
|
|
||||||
await expect(page.locator('.cm-content')).toHaveText(
|
await expect(page.locator('.cm-content')).toHaveText(
|
||||||
`length001 = 20sketch001 = startSketchOn(XY) |> startProfile(at = [-10, -10]) |> line(end = [20, 0]) |> angledLine(angle = 90, length = length001) |> xLine(length = -20)`
|
`length001 = 20sketch001 = startSketchOn(XY) |> startProfile(at = [-10, -10]) |> line(end = [20, 0]) |> angledLine(angle = 90, length = length001) |> xLine(length = -20)`
|
||||||
@ -681,9 +677,6 @@ test.describe('Testing constraints', () => {
|
|||||||
.getByRole('textbox')
|
.getByRole('textbox')
|
||||||
const cmdBarKclVariableNameInput =
|
const cmdBarKclVariableNameInput =
|
||||||
page.getByPlaceholder('Variable name')
|
page.getByPlaceholder('Variable name')
|
||||||
const cmdBarSubmitButton = page.getByRole('button', {
|
|
||||||
name: 'arrow right Continue',
|
|
||||||
})
|
|
||||||
|
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
@ -736,7 +729,7 @@ part002 = startSketchOn(XZ)
|
|||||||
await page.waitForTimeout(500)
|
await page.waitForTimeout(500)
|
||||||
const [ang, len] = value.split(', ')
|
const [ang, len] = value.split(', ')
|
||||||
const changedCode = `|> angledLine(angle = ${ang}, length = ${len})`
|
const changedCode = `|> angledLine(angle = ${ang}, length = ${len})`
|
||||||
await cmdBarSubmitButton.click()
|
await cmdBar.continue()
|
||||||
await expect(page.locator('.cm-content')).toContainText(changedCode)
|
await expect(page.locator('.cm-content')).toContainText(changedCode)
|
||||||
|
|
||||||
// checking active assures the cursor is where it should be
|
// checking active assures the cursor is where it should be
|
||||||
@ -1101,11 +1094,7 @@ part002 = startSketchOn(XZ)
|
|||||||
await page.waitForTimeout(500)
|
await page.waitForTimeout(500)
|
||||||
|
|
||||||
await page.getByTestId('cmd-bar-arg-value').getByRole('textbox').fill('10')
|
await page.getByTestId('cmd-bar-arg-value').getByRole('textbox').fill('10')
|
||||||
await page
|
await cmdBar.continue()
|
||||||
.getByRole('button', {
|
|
||||||
name: 'arrow right Continue',
|
|
||||||
})
|
|
||||||
.click()
|
|
||||||
|
|
||||||
await pollEditorLinesSelectedLength(page, 1)
|
await pollEditorLinesSelectedLength(page, 1)
|
||||||
activeLinesContent = await page.locator('.cm-activeLine').all()
|
activeLinesContent = await page.locator('.cm-activeLine').all()
|
||||||
|
@ -21,7 +21,7 @@ test.describe('Testing loading external models', () => {
|
|||||||
// We have no more web tests
|
// We have no more web tests
|
||||||
test.fail(
|
test.fail(
|
||||||
'Web: should overwrite current code, cannot create new file',
|
'Web: should overwrite current code, cannot create new file',
|
||||||
async ({ editor, context, page, homePage }) => {
|
async ({ editor, context, page, homePage, cmdBar }) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await test.step(`Test setup`, async () => {
|
await test.step(`Test setup`, async () => {
|
||||||
await context.addInitScript((code) => {
|
await context.addInitScript((code) => {
|
||||||
@ -52,9 +52,6 @@ test.describe('Testing loading external models', () => {
|
|||||||
name,
|
name,
|
||||||
})
|
})
|
||||||
const warningText = page.getByText('Overwrite current file with sample?')
|
const warningText = page.getByText('Overwrite current file with sample?')
|
||||||
const confirmButton = page.getByRole('button', {
|
|
||||||
name: 'Submit command',
|
|
||||||
})
|
|
||||||
|
|
||||||
await test.step(`Precondition: check the initial code`, async () => {
|
await test.step(`Precondition: check the initial code`, async () => {
|
||||||
await u.openKclCodePanel()
|
await u.openKclCodePanel()
|
||||||
@ -70,7 +67,7 @@ test.describe('Testing loading external models', () => {
|
|||||||
await expect(commandMethodOption('Create new file')).not.toBeVisible()
|
await expect(commandMethodOption('Create new file')).not.toBeVisible()
|
||||||
await commandMethodOption('Overwrite').click()
|
await commandMethodOption('Overwrite').click()
|
||||||
await expect(warningText).toBeVisible()
|
await expect(warningText).toBeVisible()
|
||||||
await confirmButton.click()
|
await cmdBar.submit()
|
||||||
|
|
||||||
await editor.expectEditor.toContain('// ' + newSample.title)
|
await editor.expectEditor.toContain('// ' + newSample.title)
|
||||||
})
|
})
|
||||||
|
@ -3,6 +3,7 @@ import type { LineInputsType } from '@src/lang/std/sketchcombos'
|
|||||||
import { uuidv4 } from '@src/lib/utils'
|
import { uuidv4 } from '@src/lib/utils'
|
||||||
|
|
||||||
import type { EditorFixture } from '@e2e/playwright/fixtures/editorFixture'
|
import type { EditorFixture } from '@e2e/playwright/fixtures/editorFixture'
|
||||||
|
import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
|
||||||
import { deg, getUtils, wiggleMove } from '@e2e/playwright/test-utils'
|
import { deg, getUtils, wiggleMove } from '@e2e/playwright/test-utils'
|
||||||
import { expect, test } from '@e2e/playwright/zoo-test'
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
@ -18,7 +19,7 @@ test.describe('Testing segment overlays', () => {
|
|||||||
* @param {number} options.steps - The number of steps to perform
|
* @param {number} options.steps - The number of steps to perform
|
||||||
*/
|
*/
|
||||||
const _clickConstrained =
|
const _clickConstrained =
|
||||||
(page: Page, editor: EditorFixture) =>
|
(page: Page, editor: EditorFixture, cmdBar: CmdBarFixture) =>
|
||||||
async ({
|
async ({
|
||||||
hoverPos,
|
hoverPos,
|
||||||
constraintType,
|
constraintType,
|
||||||
@ -93,11 +94,7 @@ test.describe('Testing segment overlays', () => {
|
|||||||
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
|
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
|
||||||
).toBeFocused()
|
).toBeFocused()
|
||||||
await page.waitForTimeout(500)
|
await page.waitForTimeout(500)
|
||||||
await page
|
await cmdBar.continue()
|
||||||
.getByRole('button', {
|
|
||||||
name: 'arrow right Continue',
|
|
||||||
})
|
|
||||||
.click()
|
|
||||||
await editor.expectEditor.toContain(expectFinal, {
|
await editor.expectEditor.toContain(expectFinal, {
|
||||||
shouldNormalise: true,
|
shouldNormalise: true,
|
||||||
})
|
})
|
||||||
@ -113,7 +110,7 @@ test.describe('Testing segment overlays', () => {
|
|||||||
* @param {number} options.steps - The number of steps to perform
|
* @param {number} options.steps - The number of steps to perform
|
||||||
*/
|
*/
|
||||||
const _clickUnconstrained =
|
const _clickUnconstrained =
|
||||||
(page: Page, editor: EditorFixture) =>
|
(page: Page, editor: EditorFixture, cmdBar: CmdBarFixture) =>
|
||||||
async ({
|
async ({
|
||||||
hoverPos,
|
hoverPos,
|
||||||
constraintType,
|
constraintType,
|
||||||
@ -163,11 +160,7 @@ test.describe('Testing segment overlays', () => {
|
|||||||
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
|
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
|
||||||
).toBeFocused()
|
).toBeFocused()
|
||||||
await page.waitForTimeout(500)
|
await page.waitForTimeout(500)
|
||||||
await page
|
await cmdBar.continue()
|
||||||
.getByRole('button', {
|
|
||||||
name: 'arrow right Continue',
|
|
||||||
})
|
|
||||||
.click()
|
|
||||||
await editor.expectEditor.toContain(expectAfterUnconstrained, {
|
await editor.expectEditor.toContain(expectAfterUnconstrained, {
|
||||||
shouldNormalise: true,
|
shouldNormalise: true,
|
||||||
})
|
})
|
||||||
@ -239,8 +232,8 @@ test.describe('Testing segment overlays', () => {
|
|||||||
|
|
||||||
await expect(page.getByTestId('segment-overlay')).toHaveCount(14)
|
await expect(page.getByTestId('segment-overlay')).toHaveCount(14)
|
||||||
|
|
||||||
const clickUnconstrained = _clickUnconstrained(page, editor)
|
const clickUnconstrained = _clickUnconstrained(page, editor, cmdBar)
|
||||||
const clickConstrained = _clickConstrained(page, editor)
|
const clickConstrained = _clickConstrained(page, editor, cmdBar)
|
||||||
|
|
||||||
await u.openAndClearDebugPanel()
|
await u.openAndClearDebugPanel()
|
||||||
await u.sendCustomCmd({
|
await u.sendCustomCmd({
|
||||||
@ -664,7 +657,7 @@ profile002 = circle(sketch001, center = [345, 0], radius = 238.38)
|
|||||||
await expect(
|
await expect(
|
||||||
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
|
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
|
||||||
).toBeFocused()
|
).toBeFocused()
|
||||||
await page.getByRole('button', { name: 'arrow right Continue' }).click()
|
await cmdBar.continue()
|
||||||
|
|
||||||
// Verify the X constraint was added
|
// Verify the X constraint was added
|
||||||
await editor.expectEditor.toContain('center = [xAbs001, 0]', {
|
await editor.expectEditor.toContain('center = [xAbs001, 0]', {
|
||||||
@ -682,7 +675,7 @@ profile002 = circle(sketch001, center = [345, 0], radius = 238.38)
|
|||||||
await expect(
|
await expect(
|
||||||
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
|
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
|
||||||
).toBeFocused()
|
).toBeFocused()
|
||||||
await page.getByRole('button', { name: 'arrow right Continue' }).click()
|
await cmdBar.continue()
|
||||||
|
|
||||||
// Verify the Y constraint was added
|
// Verify the Y constraint was added
|
||||||
await editor.expectEditor.toContain('center = [xAbs001, yAbs001]', {
|
await editor.expectEditor.toContain('center = [xAbs001, yAbs001]', {
|
||||||
@ -700,7 +693,7 @@ profile002 = circle(sketch001, center = [345, 0], radius = 238.38)
|
|||||||
await expect(
|
await expect(
|
||||||
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
|
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
|
||||||
).toBeFocused()
|
).toBeFocused()
|
||||||
await page.getByRole('button', { name: 'arrow right Continue' }).click()
|
await cmdBar.continue()
|
||||||
|
|
||||||
// Verify all constraints were added
|
// Verify all constraints were added
|
||||||
await editor.expectEditor.toContain(
|
await editor.expectEditor.toContain(
|
||||||
@ -887,7 +880,7 @@ profile003 = startProfile(sketch001, at = [64.39, 35.16])
|
|||||||
await expect(
|
await expect(
|
||||||
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
|
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
|
||||||
).toBeFocused()
|
).toBeFocused()
|
||||||
await page.getByRole('button', { name: 'arrow right Continue' }).click()
|
await cmdBar.continue()
|
||||||
|
|
||||||
// Verify the constraint was added
|
// Verify the constraint was added
|
||||||
await editor.expectEditor.toContain(
|
await editor.expectEditor.toContain(
|
||||||
@ -910,7 +903,7 @@ profile003 = startProfile(sketch001, at = [64.39, 35.16])
|
|||||||
await expect(
|
await expect(
|
||||||
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
|
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
|
||||||
).toBeFocused()
|
).toBeFocused()
|
||||||
await page.getByRole('button', { name: 'arrow right Continue' }).click()
|
await cmdBar.continue()
|
||||||
|
|
||||||
// Verify both constraints were added
|
// Verify both constraints were added
|
||||||
await editor.expectEditor.toContain(
|
await editor.expectEditor.toContain(
|
||||||
@ -935,7 +928,7 @@ profile003 = startProfile(sketch001, at = [64.39, 35.16])
|
|||||||
await expect(
|
await expect(
|
||||||
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
|
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
|
||||||
).toBeFocused()
|
).toBeFocused()
|
||||||
await page.getByRole('button', { name: 'arrow right Continue' }).click()
|
await cmdBar.continue()
|
||||||
|
|
||||||
// Verify the constraint was added
|
// Verify the constraint was added
|
||||||
await editor.expectEditor.toContain('endAbsolute = [xAbs002, 84.07]', {
|
await editor.expectEditor.toContain('endAbsolute = [xAbs002, 84.07]', {
|
||||||
@ -955,7 +948,7 @@ profile003 = startProfile(sketch001, at = [64.39, 35.16])
|
|||||||
await expect(
|
await expect(
|
||||||
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
|
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
|
||||||
).toBeFocused()
|
).toBeFocused()
|
||||||
await page.getByRole('button', { name: 'arrow right Continue' }).click()
|
await cmdBar.continue()
|
||||||
|
|
||||||
// Verify all constraints were added
|
// Verify all constraints were added
|
||||||
await editor.expectEditor.toContain(
|
await editor.expectEditor.toContain(
|
||||||
|
@ -32,7 +32,7 @@ test('Units menu', async ({ page, homePage }) => {
|
|||||||
test(
|
test(
|
||||||
'Successful export shows a success toast',
|
'Successful export shows a success toast',
|
||||||
{ tag: '@skipLocalEngine' },
|
{ tag: '@skipLocalEngine' },
|
||||||
async ({ page, homePage, tronApp }) => {
|
async ({ page, homePage, cmdBar, tronApp }) => {
|
||||||
// FYI this test doesn't work with only engine running locally
|
// FYI this test doesn't work with only engine running locally
|
||||||
// And you will need to have the KittyCAD CLI installed
|
// And you will need to have the KittyCAD CLI installed
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
@ -94,7 +94,8 @@ part001 = startSketchOn(-XZ)
|
|||||||
presentation: 'pretty',
|
presentation: 'pretty',
|
||||||
},
|
},
|
||||||
tronApp?.projectDirName,
|
tronApp?.projectDirName,
|
||||||
page
|
page,
|
||||||
|
cmdBar
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -254,6 +255,7 @@ test('First escape in tool pops you out of tool, second exits sketch mode', asyn
|
|||||||
test('Basic default modeling and sketch hotkeys work', async ({
|
test('Basic default modeling and sketch hotkeys work', async ({
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await test.step(`Set up test`, async () => {
|
await test.step(`Set up test`, async () => {
|
||||||
@ -397,11 +399,8 @@ test('Basic default modeling and sketch hotkeys work', async ({
|
|||||||
await expect(page.getByRole('button', { name: 'Continue' })).toBeVisible({
|
await expect(page.getByRole('button', { name: 'Continue' })).toBeVisible({
|
||||||
timeout: 20_000,
|
timeout: 20_000,
|
||||||
})
|
})
|
||||||
await page.getByRole('button', { name: 'Continue' }).click()
|
await cmdBar.continue()
|
||||||
await expect(
|
await cmdBar.submit()
|
||||||
page.getByRole('button', { name: 'Submit command' })
|
|
||||||
).toBeVisible()
|
|
||||||
await page.getByRole('button', { name: 'Submit command' }).click()
|
|
||||||
await expect(page.locator('.cm-content')).toContainText('extrude(')
|
await expect(page.locator('.cm-content')).toContainText('extrude(')
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -575,8 +574,7 @@ profile001 = startProfile(sketch002, at = [-12.34, 12.34])
|
|||||||
|
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await expect(page.getByText('Confirm Extrude')).toBeVisible()
|
await cmdBar.submit()
|
||||||
await cmdBar.progressCmdBar()
|
|
||||||
|
|
||||||
const result2 = result.genNext`
|
const result2 = result.genNext`
|
||||||
const sketch002 = extrude(sketch002, length = ${[5, 5]} + 7)`
|
const sketch002 = extrude(sketch002, length = ${[5, 5]} + 7)`
|
||||||
|
@ -111,7 +111,8 @@ commaSep1NoTrailingComma<term> { term ("," term)* }
|
|||||||
|
|
||||||
PipeSubstitution { "%" }
|
PipeSubstitution { "%" }
|
||||||
|
|
||||||
identifier { (@asciiLetter | "_") (@asciiLetter | @digit | "_")* }
|
// Includes non-whitespace unicode characters.
|
||||||
|
identifier { $[a-zA-Z_\u{a1}-\u{167f}\u{1681}-\u{1fff}\u{200e}-\u{2027}\u{202a}-\u{202e}\u{2030}-\u{205e}\u{2061}-\u{2fff}\u{3001}-\u{fefe}\u{ff00}-\u{10ffff}] $[a-zA-Z0-9_\u{a1}-\u{167f}\u{1681}-\u{1fff}\u{200e}-\u{2027}\u{202a}-\u{202e}\u{2030}-\u{205e}\u{2061}-\u{2fff}\u{3001}-\u{fefe}\u{ff00}-\u{10ffff}]* }
|
||||||
AnnotationName { "@" identifier? }
|
AnnotationName { "@" identifier? }
|
||||||
PropertyName { identifier }
|
PropertyName { identifier }
|
||||||
TagDeclarator { "$" identifier }
|
TagDeclarator { "$" identifier }
|
||||||
|
@ -15,14 +15,14 @@ import "car-tire.kcl" as carTire
|
|||||||
import * from "parameters.kcl"
|
import * from "parameters.kcl"
|
||||||
|
|
||||||
// Place the car rotor
|
// Place the car rotor
|
||||||
carRotor
|
rotor = carRotor
|
||||||
|> translate(x = 0, y = 0.5, z = 0)
|
|> translate(x = 0, y = 0.5, z = 0)
|
||||||
|
|
||||||
// Place the car wheel
|
// Place the car wheel
|
||||||
carWheel
|
carWheel
|
||||||
|
|
||||||
// Place the lug nuts
|
// Place the lug nuts
|
||||||
lugNut
|
lgnut = lugNut
|
||||||
|> patternCircular3d(
|
|> patternCircular3d(
|
||||||
arcDegrees = 360,
|
arcDegrees = 360,
|
||||||
axis = [0, 1, 0],
|
axis = [0, 1, 0],
|
||||||
@ -32,8 +32,19 @@ lugNut
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Place the brake caliper
|
// Place the brake caliper
|
||||||
brakeCaliper
|
cal = brakeCaliper
|
||||||
|> translate(x = 0, y = 0.5, z = 0)
|
|> translate(x = 0, y = 0.5, z = 0)
|
||||||
|
|
||||||
// Place the car tire
|
// Place the car tire
|
||||||
carTire
|
carTire
|
||||||
|
|
||||||
|
|
||||||
|
fn animate(step: number(_)) {
|
||||||
|
angle = 0.6deg
|
||||||
|
rotate(rotor, pitch = angle)
|
||||||
|
rotate(lgnut, pitch = angle)
|
||||||
|
rotate(cal, pitch = angle)
|
||||||
|
rotate(carWheel, pitch = angle)
|
||||||
|
rotate(carTire, pitch = angle)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
@ -369,7 +369,7 @@ profile007 = startProfile(
|
|||||||
|> line(%, endAbsolute = [profileStartX(%), profileStartY(%)])
|
|> line(%, endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|> close(%)
|
|> close(%)
|
||||||
profile008 = circle(sketch005, center = [0, 0], diameter = nubDiameter)
|
profile008 = circle(sketch005, center = [0, 0], diameter = nubDiameter)
|
||||||
subtract2d(profile007, tool = profile008)
|
hourHand = subtract2d(profile007, tool = profile008)
|
||||||
|> extrude(%, length = 5)
|
|> extrude(%, length = 5)
|
||||||
|> appearance(%, color = "#404040")
|
|> appearance(%, color = "#404040")
|
||||||
|
|
||||||
@ -413,7 +413,7 @@ profile009 = startProfile(
|
|||||||
|> line(%, endAbsolute = [profileStartX(%), profileStartY(%)])
|
|> line(%, endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|> close(%)
|
|> close(%)
|
||||||
profile010 = circle(sketch006, center = [0, 0], diameter = 30)
|
profile010 = circle(sketch006, center = [0, 0], diameter = 30)
|
||||||
subtract2d(profile009, tool = profile010)
|
minuteHand = subtract2d(profile009, tool = profile010)
|
||||||
|> extrude(%, length = 5)
|
|> extrude(%, length = 5)
|
||||||
|> appearance(%, color = "#404040")
|
|> appearance(%, color = "#404040")
|
||||||
|
|
||||||
@ -439,3 +439,8 @@ profile004 = startProfile(sketch003, at = [-slotWidth / 2, 200])
|
|||||||
|> extrude(%, length = -20)
|
|> extrude(%, length = -20)
|
||||||
|
|
||||||
// todo: create cavity for the screw to slide into (need csg update)
|
// todo: create cavity for the screw to slide into (need csg update)
|
||||||
|
|
||||||
|
fn animate(step: number(_)) {
|
||||||
|
rotate(hourHand, yaw = -0.1deg)
|
||||||
|
return rotate(minuteHand, yaw = -0.6deg)
|
||||||
|
}
|
||||||
|
@ -42,15 +42,15 @@ fn helicalGear(nTeeth, module, pressureAngle, helixAngle, gearHeight) {
|
|||||||
helicalGearSketch = startSketchOn(offsetPlane(XY, offset = offsetHeight))
|
helicalGearSketch = startSketchOn(offsetPlane(XY, offset = offsetHeight))
|
||||||
|> startProfile(at = polar(angle = helixCalc, length = baseDiameter / 2))
|
|> startProfile(at = polar(angle = helixCalc, length = baseDiameter / 2))
|
||||||
|> involuteCircular(
|
|> involuteCircular(
|
||||||
startRadius = baseDiameter / 2,
|
startDiameter = baseDiameter,
|
||||||
endRadius = tipDiameter / 2,
|
endDiameter = tipDiameter,
|
||||||
angle = helixCalc,
|
angle = helixCalc,
|
||||||
tag = $seg01,
|
tag = $seg01,
|
||||||
)
|
)
|
||||||
|> line(endAbsolute = polar(angle = 160 / nTeeth + helixCalc, length = tipDiameter / 2))
|
|> line(endAbsolute = polar(angle = 160 / nTeeth + helixCalc, length = tipDiameter / 2))
|
||||||
|> involuteCircular(
|
|> involuteCircular(
|
||||||
startRadius = baseDiameter / 2,
|
startDiameter = baseDiameter,
|
||||||
endRadius = tipDiameter / 2,
|
endDiameter = tipDiameter,
|
||||||
angle = -(4 * atan(segEndY(seg01) / segEndX(seg01)) - (3 * helixCalc)),
|
angle = -(4 * atan(segEndY(seg01) / segEndX(seg01)) - (3 * helixCalc)),
|
||||||
reverse = true,
|
reverse = true,
|
||||||
)
|
)
|
||||||
|
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 105 KiB |
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 126 KiB After Width: | Height: | Size: 126 KiB |
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 81 KiB |
Before Width: | Height: | Size: 216 KiB After Width: | Height: | Size: 216 KiB |
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 105 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 90 KiB |
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 93 KiB |
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 113 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 118 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 75 KiB |
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 95 KiB |
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 117 KiB |
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 88 KiB |
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 82 KiB |
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |