import { changeSketchArguments, addTagForSketchOnFace, addNewSketchLn, getYComponent, getXComponent, addCloseToPipe, getConstraintInfo, getConstraintInfoKw, } from './sketch' import { assertParse, recast, initPromise, CallExpression, topLevelRange, CallExpressionKw, } from '../wasm' import { getNodeFromPath } from '../queryAst' import { getNodePathFromSourceRange } from 'lang/queryAstNodePathUtils' import { enginelessExecutor } from '../../lib/testHelpers' import { err } from 'lib/trap' import { Node } from 'wasm-lib/kcl/bindings/Node' const eachQuad: [number, [number, number]][] = [ [-315, [1, 1]], [-225, [-1, 1]], [-135, [-1, -1]], [-45, [1, -1]], [45, [1, 1]], [135, [-1, 1]], [225, [-1, -1]], [315, [1, -1]], [405, [1, 1]], [495, [-1, 1]], [585, [-1, -1]], [675, [1, -1]], ] beforeAll(async () => { await initPromise }) describe('testing getYComponent', () => { it('should return the vertical component of a vector correctly when given angles in each quadrant (and with angles < 0, or > 360)', () => { const expected: [number, number][] = [] const results: [number, number][] = [] eachQuad.forEach(([angle, expectedResult]) => { results.push( getYComponent(angle, 1).map((a) => Math.round(a)) as [number, number] ) expected.push(expectedResult) }) expect(results).toEqual(expected) }) it('return extreme values on the extremes', () => { let result: [number, number] result = getYComponent(0, 1) expect(result[0]).toBe(1) expect(result[1]).toBe(0) result = getYComponent(90, 1) expect(result[0]).toBe(1) expect(result[1]).toBeGreaterThan(100000) result = getYComponent(180, 1) expect(result[0]).toBe(-1) expect(result[1]).toBeCloseTo(0) result = getYComponent(270, 1) expect(result[0]).toBe(-1) expect(result[1]).toBeLessThan(100000) }) }) describe('testing getXComponent', () => { it('should return the horizontal component of a vector correctly when given angles in each quadrant (and with angles < 0, or > 360)', () => { const expected: [number, number][] = [] const results: [number, number][] = [] eachQuad.forEach(([angle, expectedResult]) => { results.push( getXComponent(angle, 1).map((a) => Math.round(a)) as [number, number] ) expected.push(expectedResult) }) expect(results).toEqual(expected) }) it('return extreme values on the extremes', () => { let result: [number, number] result = getXComponent(0, 1) expect(result[0]).toBeGreaterThan(100000) expect(result[1]).toBe(1) result = getXComponent(90, 1) expect(result[0]).toBeCloseTo(0) expect(result[1]).toBe(1) result = getXComponent(180, 1) expect(result[0]).toBeLessThan(100000) expect(result[1]).toBe(1) result = getXComponent(270, 1) expect(result[0]).toBeCloseTo(0) expect(result[1]).toBe(-1) }) }) describe('testing changeSketchArguments', () => { const lineToChange = 'line(endAbsolute = [-1.59, -1.54])' const lineAfterChange = 'line(endAbsolute = [2, 3])' test('changeSketchArguments', async () => { // Enable rotations #152 const genCode = (line: string) => `mySketch001 = startSketchOn('XY') |> startProfileAt([0, 0], %) |> ${line} |> line(endAbsolute = [0.46, -5.82]) // |> rx(45, %) ` const code = genCode(lineToChange) const expectedCode = genCode(lineAfterChange) const ast = assertParse(code) const execState = await enginelessExecutor(ast) const sourceStart = code.indexOf(lineToChange) const changeSketchArgsRetVal = changeSketchArguments( ast, execState.variables, { type: 'sourceRange', sourceRange: topLevelRange( sourceStart, sourceStart + lineToChange.length ), }, { type: 'straight-segment', from: [0, 0], to: [2, 3], } ) if (err(changeSketchArgsRetVal)) return changeSketchArgsRetVal expect(recast(changeSketchArgsRetVal.modifiedAst)).toBe(expectedCode) }) }) describe('testing addNewSketchLn', () => { const lineToChange = 'line(endAbsolute = [-1.59, -1.54])' test('addNewSketchLn', async () => { // Enable rotations #152 const code = ` mySketch001 = startSketchOn('XY') |> startProfileAt([0, 0], %) // |> rx(45, %) |> line(endAbsolute = [-1.59, -1.54]) |> line(endAbsolute = [0.46, -5.82])` const ast = assertParse(code) const execState = await enginelessExecutor(ast) const sourceStart = code.indexOf(lineToChange) expect(sourceStart).toBe(89) const newSketchLnRetVal = addNewSketchLn({ node: ast, variables: execState.variables, input: { type: 'straight-segment', from: [0, 0], to: [2, 3], }, fnName: 'lineTo', pathToNode: [ ['body', ''], [0, 'index'], ['declaration', 'VariableDeclaration'], ['init', 'VariableDeclarator'], ], }) if (err(newSketchLnRetVal)) return newSketchLnRetVal // Enable rotations #152 let expectedCode = `mySketch001 = startSketchOn('XY') |> startProfileAt([0, 0], %) // |> rx(45, %) |> line(endAbsolute = [-1.59, -1.54]) |> line(endAbsolute = [0.46, -5.82]) |> line(endAbsolute = [2, 3]) ` const { modifiedAst } = newSketchLnRetVal expect(recast(modifiedAst)).toBe(expectedCode) const modifiedAst2 = addCloseToPipe({ node: ast, variables: execState.variables, pathToNode: [ ['body', ''], [0, 'index'], ['declaration', 'VariableDeclaration'], ['init', 'VariableDeclarator'], ], }) if (err(modifiedAst2)) return modifiedAst2 expectedCode = `mySketch001 = startSketchOn('XY') |> startProfileAt([0, 0], %) // |> rx(45, %) |> line(endAbsolute = [-1.59, -1.54]) |> line(endAbsolute = [0.46, -5.82]) |> close() ` expect(recast(modifiedAst2)).toBe(expectedCode) }) }) describe('testing addTagForSketchOnFace', () => { it('needs to be in it', async () => { const originalLine = 'line(endAbsolute = [-1.59, -1.54])' // Enable rotations #152 const genCode = (line: string) => `mySketch001 = startSketchOn('XY') |> startProfileAt([0, 0], %) // |> rx(45, %) |> ${line} |> line(endAbsolute = [0.46, -5.82]) ` const code = genCode(originalLine) const ast = assertParse(code) await enginelessExecutor(ast) const sourceStart = code.indexOf(originalLine) const sourceRange = topLevelRange( sourceStart, sourceStart + originalLine.length ) if (err(ast)) return ast const pathToNode = getNodePathFromSourceRange(ast, sourceRange) const sketchOnFaceRetVal = addTagForSketchOnFace( { // previousProgramMemory: execState.memory, // redundant? pathToNode, node: ast, }, 'lineTo', null ) if (err(sketchOnFaceRetVal)) return sketchOnFaceRetVal const { modifiedAst } = sketchOnFaceRetVal const expectedCode = genCode( 'line(endAbsolute = [-1.59, -1.54], tag = $seg01)' ) expect(recast(modifiedAst)).toBe(expectedCode) }) const chamferTestCases = [ { desc: 'chamfer in pipeExpr', originalChamfer: ` |> chamfer(length = 30, tags = [seg01, getOppositeEdge(seg01)])`, expectedChamfer: ` |> chamfer(length = 30, tags = [getOppositeEdge(seg01)], tag = $seg03) |> chamfer(length = 30, tags = [seg01])`, }, { desc: 'chamfer with its own variable', originalChamfer: `chamf = chamfer( extrude001, length = 30, tags = [seg01, getOppositeEdge(seg01)], )`, expectedChamfer: `chamf = chamfer( extrude001, length = 30, tags = [getOppositeEdge(seg01)], tag = $seg03, ) |> chamfer(length = 30, tags = [seg01])`, }, // Add more test cases here if needed ] as const chamferTestCases.forEach(({ originalChamfer, expectedChamfer, desc }) => { it(`can break up chamfers in order to add tags - ${desc}`, async () => { const genCode = (insertCode: string) => `sketch001 = startSketchOn('XZ') |> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag] |> angledLine([0, 268.43], %, $rectangleSegmentA001) |> angledLine([ segAng(rectangleSegmentA001) - 90, 217.26 ], %, $seg01) |> angledLine([ segAng(rectangleSegmentA001), -segLen(rectangleSegmentA001) ], %) |> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg02) |> close() extrude001 = extrude(sketch001, length = 100) ${insertCode} ` const code = genCode(originalChamfer) const ast = assertParse(code) await enginelessExecutor(ast) const sourceStart = code.indexOf(originalChamfer) const extraChars = originalChamfer.indexOf('chamfer') const sourceRange = topLevelRange( sourceStart + extraChars, sourceStart + originalChamfer.length - extraChars ) if (err(ast)) throw ast const pathToNode = getNodePathFromSourceRange(ast, sourceRange) console.log('pathToNode', pathToNode) const sketchOnFaceRetVal = addTagForSketchOnFace( { pathToNode, node: ast, }, 'chamfer', { type: 'edgeCut', subType: 'opposite', tagName: 'seg01', } ) if (err(sketchOnFaceRetVal)) throw sketchOnFaceRetVal expect(recast(sketchOnFaceRetVal.modifiedAst)).toBe( genCode(expectedChamfer) ) }) }) }) describe('testing getConstraintInfo', () => { describe('object notation', () => { const code = `const part001 = startSketchOn('-XZ') |> startProfileAt([0,0], %) |> line(end = [3, 4]) |> angledLine({ angle = 3.14, length = 3.14, }, %) |> line(endAbsolute = [6.14, 3.14]) |> xLineTo(8, %) |> yLineTo(5, %) |> yLine(3.14, %, $a) |> xLine(3.14, %) |> angledLineOfXLength({ angle = 3.14, length = 3.14, }, %) |> angledLineOfYLength({ angle = 30, length = 3, }, %) |> angledLineToX({ angle = 12.14, to = 12, }, %) |> angledLineToY({ angle = 30, to = 10.14, }, %) |> angledLineThatIntersects({ angle = 3.14, intersectTag = a, offset = 0 }, %) |> tangentialArcTo([3.14, 13.14], %)` test.each([ [ 'line', [ { type: 'xRelative', isConstrained: false, value: '3', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'arrayItem', index: 0 }, pathToNode: expect.any(Array), stdLibFnName: 'line', }, { type: 'yRelative', isConstrained: false, value: '4', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'arrayItem', index: 1 }, pathToNode: expect.any(Array), stdLibFnName: 'line', }, ], ], [ `angledLine(`, [ { type: 'angle', isConstrained: false, value: '3.14', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'objectProperty', key: 'angle' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLine', }, { type: 'length', isConstrained: false, value: '3.14', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'objectProperty', key: 'length' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLine', }, ], ], [ 'line(endAbsolute', [ { type: 'xAbsolute', isConstrained: false, value: '6.14', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'arrayItem', index: 0 }, pathToNode: expect.any(Array), stdLibFnName: 'line', }, { type: 'yAbsolute', isConstrained: false, value: '3.14', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'arrayItem', index: 1 }, pathToNode: expect.any(Array), stdLibFnName: 'line', }, ], ], [ 'xLineTo', [ { type: 'horizontal', isConstrained: true, value: 'xLineTo', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: undefined, pathToNode: expect.any(Array), stdLibFnName: 'xLineTo', }, { type: 'xAbsolute', isConstrained: false, value: '8', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'singleValue' }, pathToNode: expect.any(Array), stdLibFnName: 'xLineTo', }, ], ], [ 'yLineTo', [ { type: 'vertical', isConstrained: true, value: 'yLineTo', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: undefined, pathToNode: expect.any(Array), stdLibFnName: 'yLineTo', }, { type: 'yAbsolute', isConstrained: false, value: '5', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'singleValue' }, pathToNode: expect.any(Array), stdLibFnName: 'yLineTo', }, ], ], [ 'yLine(', [ { type: 'vertical', isConstrained: true, value: 'yLine', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: undefined, pathToNode: expect.any(Array), stdLibFnName: 'yLine', }, { type: 'yRelative', isConstrained: false, value: '3.14', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'singleValue' }, pathToNode: expect.any(Array), stdLibFnName: 'yLine', }, ], ], [ 'xLine(', [ { type: 'horizontal', isConstrained: true, value: 'xLine', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: undefined, pathToNode: expect.any(Array), stdLibFnName: 'xLine', }, { type: 'xRelative', isConstrained: false, value: '3.14', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'singleValue' }, pathToNode: expect.any(Array), stdLibFnName: 'xLine', }, ], ], [ 'angledLineOfXLength', [ { type: 'angle', isConstrained: false, value: '3.14', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'objectProperty', key: 'angle' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineOfXLength', }, { type: 'xRelative', isConstrained: false, value: '3.14', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'objectProperty', key: 'length' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineOfXLength', }, ], ], [ 'angledLineOfYLength', [ { type: 'angle', isConstrained: false, value: '30', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'objectProperty', key: 'angle' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineOfYLength', }, { type: 'yRelative', isConstrained: false, value: '3', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'objectProperty', key: 'length' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineOfYLength', }, ], ], [ 'angledLineToX', [ { type: 'angle', isConstrained: false, value: '12.14', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'objectProperty', key: 'angle' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineToX', }, { type: 'xAbsolute', isConstrained: false, value: '12', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'objectProperty', key: 'to' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineToX', }, ], ], [ 'angledLineToY', [ { type: 'angle', isConstrained: false, value: '30', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'objectProperty', key: 'angle' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineToY', }, { type: 'yAbsolute', isConstrained: false, value: '10.14', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'objectProperty', key: 'to' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineToY', }, ], ], [ 'angledLineThatIntersects', [ { type: 'angle', isConstrained: false, value: '3.14', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'objectProperty', key: 'angle' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineThatIntersects', }, { type: 'intersectionOffset', isConstrained: false, value: '0', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'objectProperty', key: 'offset' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineThatIntersects', }, { type: 'intersectionTag', isConstrained: false, value: 'a', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { key: 'intersectTag', type: 'objectProperty', }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineThatIntersects', }, ], ], [ 'tangentialArcTo', [ { type: 'tangentialWithPrevious', isConstrained: true, value: 'tangentialArcTo', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: undefined, pathToNode: expect.any(Array), stdLibFnName: 'tangentialArcTo', }, { type: 'xAbsolute', isConstrained: false, value: '3.14', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'arrayItem', index: 0 }, pathToNode: expect.any(Array), stdLibFnName: 'tangentialArcTo', }, { type: 'yAbsolute', isConstrained: false, value: '13.14', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'arrayItem', index: 1 }, pathToNode: expect.any(Array), stdLibFnName: 'tangentialArcTo', }, ], ], ])('testing %s when inputs are unconstrained', (functionName, expected) => { const ast = assertParse(code) const sourceRange = topLevelRange( code.indexOf(functionName), code.indexOf(functionName) + functionName.length ) if (err(ast)) return ast const pathToNode = getNodePathFromSourceRange(ast, sourceRange) const callExp = getNodeFromPath>( ast, pathToNode, ['CallExpression', 'CallExpressionKw'] ) if (err(callExp)) return callExp const result = callExp.node.type === 'CallExpression' ? getConstraintInfo(callExp.node, code, pathToNode) : getConstraintInfoKw(callExp.node, code, pathToNode) expect(result).toEqual(expected) }) }) describe('array notation', () => { const code = `const part001 = startSketchOn('-XZ') |> startProfileAt([0, 0], %) |> line(end = [3, 4]) |> angledLine([3.14, 3.14], %) |> line(endAbsolute = [6.14, 3.14]) |> xLineTo(8, %) |> yLineTo(5, %) |> yLine(3.14, %, $a) |> xLine(3.14, %) |> angledLineOfXLength([3.14, 3.14], %) |> angledLineOfYLength([30, 3], %) |> angledLineToX([12, 12], %) |> angledLineToY([30, 10], %) |> angledLineThatIntersects({ angle = 3.14, intersectTag = a, offset = 0 }, %) |> tangentialArcTo([3.14, 13.14], %)` test.each([ [ `angledLine(`, [ { type: 'angle', isConstrained: false, value: '3.14', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'arrayItem', index: 0 }, pathToNode: expect.any(Array), stdLibFnName: 'angledLine', }, { type: 'length', isConstrained: false, value: '3.14', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'arrayItem', index: 1 }, pathToNode: expect.any(Array), stdLibFnName: 'angledLine', }, ], ], [ 'angledLineOfXLength', [ { type: 'angle', isConstrained: false, value: '3.14', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'arrayItem', index: 0 }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineOfXLength', }, { type: 'xRelative', isConstrained: false, value: '3.14', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'arrayItem', index: 1 }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineOfXLength', }, ], ], [ 'angledLineOfYLength', [ { type: 'angle', isConstrained: false, value: '30', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'arrayItem', index: 0 }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineOfYLength', }, { type: 'yRelative', isConstrained: false, value: '3', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'arrayItem', index: 1 }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineOfYLength', }, ], ], [ 'angledLineToX', [ { type: 'angle', isConstrained: false, value: '12', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'arrayItem', index: 0 }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineToX', }, { type: 'xAbsolute', isConstrained: false, value: '12', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'arrayItem', index: 1 }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineToX', }, ], ], [ 'angledLineToY', [ { type: 'angle', isConstrained: false, value: '30', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'arrayItem', index: 0 }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineToY', }, { type: 'yAbsolute', isConstrained: false, value: '10', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'arrayItem', index: 1 }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineToY', }, ], ], ])('testing %s when inputs are unconstrained', (functionName, expected) => { const ast = assertParse(code) const sourceRange = topLevelRange( code.indexOf(functionName), code.indexOf(functionName) + functionName.length ) if (err(ast)) return ast const pathToNode = getNodePathFromSourceRange(ast, sourceRange) const callExp = getNodeFromPath>( ast, pathToNode, ['CallExpression', 'CallExpressionKw'] ) if (err(callExp)) return callExp const result = callExp.node.type === 'CallExpression' ? getConstraintInfo(callExp.node, code, pathToNode) : getConstraintInfoKw(callExp.node, code, pathToNode) expect(result).toEqual(expected) }) }) describe('constrained', () => { const code = `const part001 = startSketchOn('-XZ') |> startProfileAt([0, 0], %) |> line(end = [3 + 0, 4 + 0]) |> angledLine({ angle = 3.14 + 0, length = 3.14 + 0 }, %) |> line(endAbsolute = [6.14 + 0, 3.14 + 0]) |> xLineTo(8 + 0, %) |> yLineTo(5 + 0, %) |> yLine(3.14 + 0, %, $a) |> xLine(3.14 + 0, %) |> angledLineOfXLength({ angle = 3.14 + 0, length = 3.14 + 0 }, %) |> angledLineOfYLength({ angle = 30 + 0, length = 3 + 0 }, %) |> angledLineToX({ angle = 12.14 + 0, to = 12 + 0 }, %) |> angledLineToY({ angle = 30 + 0, to = 10.14 + 0 }, %) |> angledLineThatIntersects({ angle = 3.14 + 0, intersectTag = a, offset = 0 + 0 }, %) |> tangentialArcTo([3.14 + 0, 13.14 + 0], %)` test.each([ [ 'line', [ { type: 'xRelative', isConstrained: true, value: '3 + 0', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'arrayItem', index: 0 }, pathToNode: expect.any(Array), stdLibFnName: 'line', }, { type: 'yRelative', isConstrained: true, value: '4 + 0', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'arrayItem', index: 1 }, pathToNode: expect.any(Array), stdLibFnName: 'line', }, ], ], [ `angledLine(`, [ { type: 'angle', isConstrained: true, value: '3.14 + 0', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'objectProperty', key: 'angle' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLine', }, { type: 'length', isConstrained: true, value: '3.14 + 0', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'objectProperty', key: 'length' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLine', }, ], ], [ 'line(endAbsolute', [ { type: 'xAbsolute', isConstrained: true, value: '6.14 + 0', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'arrayItem', index: 0 }, pathToNode: expect.any(Array), stdLibFnName: 'line', }, { type: 'yAbsolute', isConstrained: true, value: '3.14 + 0', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'arrayItem', index: 1 }, pathToNode: expect.any(Array), stdLibFnName: 'line', }, ], ], [ 'xLineTo', [ { type: 'horizontal', isConstrained: true, value: 'xLineTo', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: undefined, pathToNode: expect.any(Array), stdLibFnName: 'xLineTo', }, { type: 'xAbsolute', isConstrained: true, value: '8 + 0', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'singleValue' }, pathToNode: expect.any(Array), stdLibFnName: 'xLineTo', }, ], ], [ 'yLineTo', [ { type: 'vertical', isConstrained: true, value: 'yLineTo', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: undefined, pathToNode: expect.any(Array), stdLibFnName: 'yLineTo', }, { type: 'yAbsolute', isConstrained: true, value: '5 + 0', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'singleValue' }, pathToNode: expect.any(Array), stdLibFnName: 'yLineTo', }, ], ], [ 'yLine(', [ { type: 'vertical', isConstrained: true, value: 'yLine', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: undefined, pathToNode: expect.any(Array), stdLibFnName: 'yLine', }, { type: 'yRelative', isConstrained: true, value: '3.14 + 0', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'singleValue' }, pathToNode: expect.any(Array), stdLibFnName: 'yLine', }, ], ], [ 'xLine(', [ { type: 'horizontal', isConstrained: true, value: 'xLine', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: undefined, pathToNode: expect.any(Array), stdLibFnName: 'xLine', }, { type: 'xRelative', isConstrained: true, value: '3.14 + 0', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'singleValue' }, pathToNode: expect.any(Array), stdLibFnName: 'xLine', }, ], ], [ 'angledLineOfXLength', [ { type: 'angle', isConstrained: true, value: '3.14 + 0', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'objectProperty', key: 'angle' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineOfXLength', }, { type: 'xRelative', isConstrained: true, value: '3.14 + 0', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'objectProperty', key: 'length' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineOfXLength', }, ], ], [ 'angledLineOfYLength', [ { type: 'angle', isConstrained: true, value: '30 + 0', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'objectProperty', key: 'angle' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineOfYLength', }, { type: 'yRelative', isConstrained: true, value: '3 + 0', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'objectProperty', key: 'length' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineOfYLength', }, ], ], [ 'angledLineToX', [ { type: 'angle', isConstrained: true, value: '12.14 + 0', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'objectProperty', key: 'angle' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineToX', }, { type: 'xAbsolute', isConstrained: true, value: '12 + 0', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'objectProperty', key: 'to' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineToX', }, ], ], [ 'angledLineToY', [ { type: 'angle', isConstrained: true, value: '30 + 0', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'objectProperty', key: 'angle' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineToY', }, { type: 'yAbsolute', isConstrained: true, value: '10.14 + 0', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'objectProperty', key: 'to' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineToY', }, ], ], [ 'angledLineThatIntersects', [ { type: 'angle', isConstrained: true, value: '3.14 + 0', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'objectProperty', key: 'angle' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineThatIntersects', }, { type: 'intersectionOffset', isConstrained: true, value: '0 + 0', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'objectProperty', key: 'offset' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineThatIntersects', }, { type: 'intersectionTag', isConstrained: false, value: 'a', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { key: 'intersectTag', type: 'objectProperty' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineThatIntersects', }, ], ], [ 'tangentialArcTo', [ { type: 'tangentialWithPrevious', isConstrained: true, value: 'tangentialArcTo', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: undefined, pathToNode: expect.any(Array), stdLibFnName: 'tangentialArcTo', }, { type: 'xAbsolute', isConstrained: true, value: '3.14 + 0', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'arrayItem', index: 0 }, pathToNode: expect.any(Array), stdLibFnName: 'tangentialArcTo', }, { type: 'yAbsolute', isConstrained: true, value: '13.14 + 0', sourceRange: [expect.any(Number), expect.any(Number), 0], argPosition: { type: 'arrayItem', index: 1 }, pathToNode: expect.any(Array), stdLibFnName: 'tangentialArcTo', }, ], ], ])('testing %s when inputs are unconstrained', (functionName, expected) => { const ast = assertParse(code) const sourceRange = topLevelRange( code.indexOf(functionName), code.indexOf(functionName) + functionName.length ) if (err(ast)) return ast const pathToNode = getNodePathFromSourceRange(ast, sourceRange) const callExp = getNodeFromPath>( ast, pathToNode, ['CallExpression', 'CallExpressionKw'] ) if (err(callExp)) return callExp const result = callExp.node.type === 'CallExpression' ? getConstraintInfo(callExp.node, code, pathToNode) : getConstraintInfoKw(callExp.node, code, pathToNode) expect(result).toEqual(expected) }) }) })