fix out of range error (#4931)
* fix out of range error Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * remove console logs Signed-off-by: Jess Frazelle <github@jessfraz.com> * add a regression test Signed-off-by: Jess Frazelle <github@jessfraz.com> --------- Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
@ -1323,3 +1323,85 @@ test.describe(`Sketching with offset planes`, () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Regression test for https://github.com/KittyCAD/modeling-app/issues/4891
|
||||||
|
test.describe(`Click based selection don't brick the app when clicked out of range after format using cache`, () => {
|
||||||
|
test(`Can select a line that reformmed after entering sketch mode`, async ({
|
||||||
|
context,
|
||||||
|
page,
|
||||||
|
scene,
|
||||||
|
toolbar,
|
||||||
|
editor,
|
||||||
|
homePage,
|
||||||
|
}) => {
|
||||||
|
// We seed the scene with a single offset plane
|
||||||
|
await context.addInitScript(() => {
|
||||||
|
localStorage.setItem(
|
||||||
|
'persistCode',
|
||||||
|
`sketch001 = startSketchOn('XZ')
|
||||||
|
|> startProfileAt([0, 0], %)
|
||||||
|
|> line([3.14, 3.14], %)
|
||||||
|
|> arcTo({
|
||||||
|
end = [4, 2],
|
||||||
|
interior = [1, 2]
|
||||||
|
}, %)
|
||||||
|
`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
await homePage.goToModelingScene()
|
||||||
|
await scene.waitForExecutionDone()
|
||||||
|
|
||||||
|
await test.step(`format the code`, async () => {
|
||||||
|
// doesn't contain condensed version
|
||||||
|
await editor.expectEditor.not.toContain(
|
||||||
|
`arcTo({ end = [4, 2], interior = [1, 2] }, %)`
|
||||||
|
)
|
||||||
|
// click the code to enter sketch mode
|
||||||
|
await page.getByText(`arcTo`).click()
|
||||||
|
// Format the code.
|
||||||
|
await page.locator('#code-pane button:first-child').click()
|
||||||
|
await page.locator('button:has-text("Format code")').click()
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step(`Ensure the code reformatted`, async () => {
|
||||||
|
await editor.expectEditor.toContain(
|
||||||
|
`arcTo({ end = [4, 2], interior = [1, 2] }, %)`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const [arcClick, arcHover] = scene.makeMouseHelpers(699, 337)
|
||||||
|
await test.step('Ensure we can hover the arc', async () => {
|
||||||
|
await arcHover()
|
||||||
|
|
||||||
|
// Check that the code is highlighted
|
||||||
|
await editor.expectState({
|
||||||
|
activeLines: ["sketch001=startSketchOn('XZ')"],
|
||||||
|
diagnostics: [],
|
||||||
|
highlightedCode: 'arcTo({end = [4, 2], interior = [1, 2]}, %)',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('reset the selection', async () => {
|
||||||
|
// Move the mouse out of the way
|
||||||
|
await page.mouse.move(655, 337)
|
||||||
|
|
||||||
|
await editor.expectState({
|
||||||
|
activeLines: ["sketch001=startSketchOn('XZ')"],
|
||||||
|
diagnostics: [],
|
||||||
|
highlightedCode: '',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('Ensure we can click the arc', async () => {
|
||||||
|
await arcClick()
|
||||||
|
|
||||||
|
// Check that the code is highlighted
|
||||||
|
await editor.expectState({
|
||||||
|
activeLines: [],
|
||||||
|
diagnostics: [],
|
||||||
|
highlightedCode: 'arcTo({end = [4, 2], interior = [1, 2]}, %)',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
@ -97,6 +97,7 @@ export const KclEditorPane = () => {
|
|||||||
if (!editorIsMounted || !lastSelectionEvent || !editorManager.editorView) {
|
if (!editorIsMounted || !lastSelectionEvent || !editorManager.editorView) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
editorManager.editorView.dispatch({
|
editorManager.editorView.dispatch({
|
||||||
selection: lastSelectionEvent.codeMirrorSelection,
|
selection: lastSelectionEvent.codeMirrorSelection,
|
||||||
annotations: [modelingMachineEvent, Transaction.addToHistory.of(false)],
|
annotations: [modelingMachineEvent, Transaction.addToHistory.of(false)],
|
||||||
|
@ -129,6 +129,21 @@ export default class EditorManager {
|
|||||||
this._isShiftDown = isShiftDown
|
this._isShiftDown = isShiftDown
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private selectionsWithSafeEnds(
|
||||||
|
selection: Array<Selection['codeRef']['range']>
|
||||||
|
): Array<[number, number]> {
|
||||||
|
if (!this._editorView) {
|
||||||
|
return selection.map((s): [number, number] => {
|
||||||
|
return [s[0], s[1]]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return selection.map((s): [number, number] => {
|
||||||
|
const safeEnd = Math.min(s[1], this._editorView?.state.doc.length || s[1])
|
||||||
|
return [s[0], safeEnd]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
set selectionRanges(selectionRanges: Selections) {
|
set selectionRanges(selectionRanges: Selections) {
|
||||||
this._selectionRanges = selectionRanges
|
this._selectionRanges = selectionRanges
|
||||||
}
|
}
|
||||||
@ -154,14 +169,9 @@ export default class EditorManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setHighlightRange(range: Array<Selection['codeRef']['range']>): void {
|
setHighlightRange(range: Array<Selection['codeRef']['range']>): void {
|
||||||
this._highlightRange = range.map((s): [number, number] => {
|
const selectionsWithSafeEnds = this.selectionsWithSafeEnds(range)
|
||||||
return [s[0], s[1]]
|
|
||||||
})
|
|
||||||
|
|
||||||
const selectionsWithSafeEnds = range.map((s): [number, number] => {
|
this._highlightRange = selectionsWithSafeEnds
|
||||||
const safeEnd = Math.min(s[1], this._editorView?.state.doc.length || s[1])
|
|
||||||
return [s[0], safeEnd]
|
|
||||||
})
|
|
||||||
|
|
||||||
if (this._editorView) {
|
if (this._editorView) {
|
||||||
this._editorView.dispatch({
|
this._editorView.dispatch({
|
||||||
@ -302,20 +312,20 @@ export default class EditorManager {
|
|||||||
}
|
}
|
||||||
let codeBasedSelections = []
|
let codeBasedSelections = []
|
||||||
for (const selection of selections.graphSelections) {
|
for (const selection of selections.graphSelections) {
|
||||||
codeBasedSelections.push(
|
const safeEnd = Math.min(
|
||||||
EditorSelection.range(
|
selection.codeRef.range[1],
|
||||||
selection.codeRef.range[0],
|
this._editorView?.state.doc.length || selection.codeRef.range[1]
|
||||||
selection.codeRef.range[1]
|
|
||||||
)
|
)
|
||||||
|
codeBasedSelections.push(
|
||||||
|
EditorSelection.range(selection.codeRef.range[0], safeEnd)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
codeBasedSelections.push(
|
const end =
|
||||||
EditorSelection.cursor(
|
selections.graphSelections[selections.graphSelections.length - 1].codeRef
|
||||||
selections.graphSelections[selections.graphSelections.length - 1]
|
.range[1]
|
||||||
.codeRef.range[1]
|
const safeEnd = Math.min(end, this._editorView?.state.doc.length || end)
|
||||||
)
|
codeBasedSelections.push(EditorSelection.cursor(safeEnd))
|
||||||
)
|
|
||||||
|
|
||||||
if (!this._editorView) {
|
if (!this._editorView) {
|
||||||
return
|
return
|
||||||
|
@ -323,7 +323,8 @@ export function handleSelectionBatch({
|
|||||||
resetAndSetEngineEntitySelectionCmds(selectionToEngine)
|
resetAndSetEngineEntitySelectionCmds(selectionToEngine)
|
||||||
selections.graphSelections.forEach(({ codeRef }) => {
|
selections.graphSelections.forEach(({ codeRef }) => {
|
||||||
if (codeRef.range?.[1]) {
|
if (codeRef.range?.[1]) {
|
||||||
ranges.push(EditorSelection.cursor(codeRef.range[1]))
|
const safeEnd = Math.min(codeRef.range[1], codeManager.code.length)
|
||||||
|
ranges.push(EditorSelection.cursor(safeEnd))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if (ranges.length)
|
if (ranges.length)
|
||||||
|
Reference in New Issue
Block a user