import { changeSketchArguments, addTagForSketchOnFace, addNewSketchLn, getYComponent, getXComponent, addCloseToPipe, getConstraintInfo, } from './sketch' import { assertParse, recast, initPromise, SourceRange, CallExpression, } from '../wasm' import { getNodeFromPath, getNodePathFromSourceRange } from '../queryAst' 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 = 'lineTo([-1.59, -1.54], %)' const lineAfterChange = 'lineTo([2, 3], %)' test('changeSketchArguments', async () => { // Enable rotations #152 const genCode = (line: string) => `mySketch001 = startSketchOn('XY') |> startProfileAt([0, 0], %) |> ${line} |> lineTo([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.memory, { type: 'sourceRange', sourceRange: [sourceStart, sourceStart + lineToChange.length, true], }, { 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 = 'lineTo([-1.59, -1.54], %)' test('addNewSketchLn', async () => { // Enable rotations #152 const code = ` mySketch001 = startSketchOn('XY') |> startProfileAt([0, 0], %) // |> rx(45, %) |> lineTo([-1.59, -1.54], %) |> lineTo([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, programMemory: execState.memory, 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, %) |> lineTo([-1.59, -1.54], %) |> lineTo([0.46, -5.82], %) |> lineTo([2, 3], %) ` const { modifiedAst } = newSketchLnRetVal expect(recast(modifiedAst)).toBe(expectedCode) const modifiedAst2 = addCloseToPipe({ node: ast, programMemory: execState.memory, pathToNode: [ ['body', ''], [0, 'index'], ['declaration', 'VariableDeclaration'], ['init', 'VariableDeclarator'], ], }) if (err(modifiedAst2)) return modifiedAst2 expectedCode = `mySketch001 = startSketchOn('XY') |> startProfileAt([0, 0], %) // |> rx(45, %) |> lineTo([-1.59, -1.54], %) |> lineTo([0.46, -5.82], %) |> close(%) ` expect(recast(modifiedAst2)).toBe(expectedCode) }) }) describe('testing addTagForSketchOnFace', () => { it('needs to be in it', async () => { const originalLine = 'lineTo([-1.59, -1.54], %)' // Enable rotations #152 const genCode = (line: string) => `mySketch001 = startSketchOn('XY') |> startProfileAt([0, 0], %) // |> rx(45, %) |> ${line} |> lineTo([0.46, -5.82], %) ` const code = genCode(originalLine) const ast = assertParse(code) await enginelessExecutor(ast) const sourceStart = code.indexOf(originalLine) const sourceRange: [number, number, boolean] = [ sourceStart, sourceStart + originalLine.length, true, ] 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('lineTo([-1.59, -1.54], %, $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)] }, %, $seg03) |> chamfer({ length = 30, tags = [seg01] }, %)`, }, { desc: 'chamfer with its own variable', originalChamfer: `chamf = chamfer({ length = 30, tags = [seg01, getOppositeEdge(seg01)] }, extrude001)`, expectedChamfer: `chamf = chamfer({ length = 30, tags = [getOppositeEdge(seg01)] }, extrude001, $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) ], %) |> lineTo([profileStartX(%), profileStartY(%)], %, $seg02) |> close(%) extrude001 = extrude(100, sketch001) ${insertCode} ` const code = genCode(originalChamfer) const ast = assertParse(code) await enginelessExecutor(ast) const sourceStart = code.indexOf(originalChamfer) const extraChars = originalChamfer.indexOf('chamfer') const sourceRange: [number, number, boolean] = [ sourceStart + extraChars, sourceStart + originalChamfer.length - extraChars, true, ] 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([3, 4], %) |> angledLine({ angle = 3.14, length = 3.14, }, %) |> lineTo([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], %)` const ast = assertParse(code) test.each([ [ 'line', [ { type: 'xRelative', isConstrained: false, value: '3', sourceRange: [78, 79, true], argPosition: { type: 'arrayItem', index: 0 }, pathToNode: expect.any(Array), stdLibFnName: 'line', }, { type: 'yRelative', isConstrained: false, value: '4', sourceRange: [81, 82, true], argPosition: { type: 'arrayItem', index: 1 }, pathToNode: expect.any(Array), stdLibFnName: 'line', }, ], ], [ `angledLine(`, [ { type: 'angle', isConstrained: false, value: '3.14', sourceRange: [118, 122, true], argPosition: { type: 'objectProperty', key: 'angle' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLine', }, { type: 'length', isConstrained: false, value: '3.14', sourceRange: [137, 141, true], argPosition: { type: 'objectProperty', key: 'length' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLine', }, ], ], [ 'lineTo', [ { type: 'xAbsolute', isConstrained: false, value: '6.14', sourceRange: [164, 168, true], argPosition: { type: 'arrayItem', index: 0 }, pathToNode: expect.any(Array), stdLibFnName: 'lineTo', }, { type: 'yAbsolute', isConstrained: false, value: '3.14', sourceRange: [170, 174, true], argPosition: { type: 'arrayItem', index: 1 }, pathToNode: expect.any(Array), stdLibFnName: 'lineTo', }, ], ], [ 'xLineTo', [ { type: 'horizontal', isConstrained: true, value: 'xLineTo', sourceRange: [185, 192, true], argPosition: undefined, pathToNode: expect.any(Array), stdLibFnName: 'xLineTo', }, { type: 'xAbsolute', isConstrained: false, value: '8', sourceRange: [193, 194, true], argPosition: { type: 'singleValue' }, pathToNode: expect.any(Array), stdLibFnName: 'xLineTo', }, ], ], [ 'yLineTo', [ { type: 'vertical', isConstrained: true, value: 'yLineTo', sourceRange: [204, 211, true], argPosition: undefined, pathToNode: expect.any(Array), stdLibFnName: 'yLineTo', }, { type: 'yAbsolute', isConstrained: false, value: '5', sourceRange: [212, 213, true], argPosition: { type: 'singleValue' }, pathToNode: expect.any(Array), stdLibFnName: 'yLineTo', }, ], ], [ 'yLine(', [ { type: 'vertical', isConstrained: true, value: 'yLine', sourceRange: [223, 228, true], argPosition: undefined, pathToNode: expect.any(Array), stdLibFnName: 'yLine', }, { type: 'yRelative', isConstrained: false, value: '3.14', sourceRange: [229, 233, true], argPosition: { type: 'singleValue' }, pathToNode: expect.any(Array), stdLibFnName: 'yLine', }, ], ], [ 'xLine(', [ { type: 'horizontal', isConstrained: true, value: 'xLine', sourceRange: [247, 252, true], argPosition: undefined, pathToNode: expect.any(Array), stdLibFnName: 'xLine', }, { type: 'xRelative', isConstrained: false, value: '3.14', sourceRange: [253, 257, true], argPosition: { type: 'singleValue' }, pathToNode: expect.any(Array), stdLibFnName: 'xLine', }, ], ], [ 'angledLineOfXLength', [ { type: 'angle', isConstrained: false, value: '3.14', sourceRange: [301, 305, true], argPosition: { type: 'objectProperty', key: 'angle' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineOfXLength', }, { type: 'xRelative', isConstrained: false, value: '3.14', sourceRange: [320, 324, true], argPosition: { type: 'objectProperty', key: 'length' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineOfXLength', }, ], ], [ 'angledLineOfYLength', [ { type: 'angle', isConstrained: false, value: '30', sourceRange: [373, 375, true], argPosition: { type: 'objectProperty', key: 'angle' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineOfYLength', }, { type: 'yRelative', isConstrained: false, value: '3', sourceRange: [390, 391, true], argPosition: { type: 'objectProperty', key: 'length' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineOfYLength', }, ], ], [ 'angledLineToX', [ { type: 'angle', isConstrained: false, value: '12.14', sourceRange: [434, 439, true], argPosition: { type: 'objectProperty', key: 'angle' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineToX', }, { type: 'xAbsolute', isConstrained: false, value: '12', sourceRange: [450, 452, true], argPosition: { type: 'objectProperty', key: 'to' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineToX', }, ], ], [ 'angledLineToY', [ { type: 'angle', isConstrained: false, value: '30', sourceRange: [495, 497, true], argPosition: { type: 'objectProperty', key: 'angle' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineToY', }, { type: 'yAbsolute', isConstrained: false, value: '10.14', sourceRange: [508, 513, true], argPosition: { type: 'objectProperty', key: 'to' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineToY', }, ], ], [ 'angledLineThatIntersects', [ { type: 'angle', isConstrained: false, value: '3.14', sourceRange: [567, 571, true], argPosition: { type: 'objectProperty', key: 'angle' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineThatIntersects', }, { type: 'intersectionOffset', isConstrained: false, value: '0', sourceRange: [608, 609, true], argPosition: { type: 'objectProperty', key: 'offset' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineThatIntersects', }, { type: 'intersectionTag', isConstrained: false, value: 'a', sourceRange: [592, 593, true], argPosition: { key: 'intersectTag', type: 'objectProperty', }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineThatIntersects', }, ], ], [ 'tangentialArcTo', [ { type: 'tangentialWithPrevious', isConstrained: true, value: 'tangentialArcTo', sourceRange: [623, 638, true], argPosition: undefined, pathToNode: expect.any(Array), stdLibFnName: 'tangentialArcTo', }, { type: 'xAbsolute', isConstrained: false, value: '3.14', sourceRange: [640, 644, true], argPosition: { type: 'arrayItem', index: 0 }, pathToNode: expect.any(Array), stdLibFnName: 'tangentialArcTo', }, { type: 'yAbsolute', isConstrained: false, value: '13.14', sourceRange: [646, 651, true], argPosition: { type: 'arrayItem', index: 1 }, pathToNode: expect.any(Array), stdLibFnName: 'tangentialArcTo', }, ], ], ])('testing %s when inputs are unconstrained', (functionName, expected) => { const sourceRange: SourceRange = [ code.indexOf(functionName), code.indexOf(functionName) + functionName.length, true, ] if (err(ast)) return ast const pathToNode = getNodePathFromSourceRange(ast, sourceRange) const callExp = getNodeFromPath>( ast, pathToNode, 'CallExpression' ) if (err(callExp)) return callExp const result = getConstraintInfo(callExp.node, code, pathToNode) expect(result).toEqual(expected) }) }) describe('array notation', () => { const code = `const part001 = startSketchOn('-XZ') |> startProfileAt([0, 0], %) |> line([3, 4], %) |> angledLine([3.14, 3.14], %) |> lineTo([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], %)` const ast = assertParse(code) test.each([ [ `angledLine(`, [ { type: 'angle', isConstrained: false, value: '3.14', sourceRange: [112, 116, true], argPosition: { type: 'arrayItem', index: 0 }, pathToNode: expect.any(Array), stdLibFnName: 'angledLine', }, { type: 'length', isConstrained: false, value: '3.14', sourceRange: [118, 122, true], argPosition: { type: 'arrayItem', index: 1 }, pathToNode: expect.any(Array), stdLibFnName: 'angledLine', }, ], ], [ 'angledLineOfXLength', [ { type: 'angle', isConstrained: false, value: '3.14', sourceRange: [277, 281, true], argPosition: { type: 'arrayItem', index: 0 }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineOfXLength', }, { type: 'xRelative', isConstrained: false, value: '3.14', sourceRange: [283, 287, true], argPosition: { type: 'arrayItem', index: 1 }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineOfXLength', }, ], ], [ 'angledLineOfYLength', [ { type: 'angle', isConstrained: false, value: '30', sourceRange: [321, 323, true], argPosition: { type: 'arrayItem', index: 0 }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineOfYLength', }, { type: 'yRelative', isConstrained: false, value: '3', sourceRange: [325, 326, true], argPosition: { type: 'arrayItem', index: 1 }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineOfYLength', }, ], ], [ 'angledLineToX', [ { type: 'angle', isConstrained: false, value: '12', sourceRange: [354, 356, true], argPosition: { type: 'arrayItem', index: 0 }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineToX', }, { type: 'xAbsolute', isConstrained: false, value: '12', sourceRange: [358, 360, true], argPosition: { type: 'arrayItem', index: 1 }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineToX', }, ], ], [ 'angledLineToY', [ { type: 'angle', isConstrained: false, value: '30', sourceRange: [388, 390, true], argPosition: { type: 'arrayItem', index: 0 }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineToY', }, { type: 'yAbsolute', isConstrained: false, value: '10', sourceRange: [392, 394, true], argPosition: { type: 'arrayItem', index: 1 }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineToY', }, ], ], ])('testing %s when inputs are unconstrained', (functionName, expected) => { const sourceRange: SourceRange = [ code.indexOf(functionName), code.indexOf(functionName) + functionName.length, true, ] if (err(ast)) return ast const pathToNode = getNodePathFromSourceRange(ast, sourceRange) const callExp = getNodeFromPath>( ast, pathToNode, 'CallExpression' ) if (err(callExp)) return callExp const result = getConstraintInfo(callExp.node, code, pathToNode) expect(result).toEqual(expected) }) }) describe('constrained', () => { const code = `const part001 = startSketchOn('-XZ') |> startProfileAt([0, 0], %) |> line([3 + 0, 4 + 0], %) |> angledLine({ angle = 3.14 + 0, length = 3.14 + 0 }, %) |> lineTo([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], %)` const ast = assertParse(code) test.each([ [ 'line', [ { type: 'xRelative', isConstrained: true, value: '3 + 0', sourceRange: [83, 88, true], argPosition: { type: 'arrayItem', index: 0 }, pathToNode: expect.any(Array), stdLibFnName: 'line', }, { type: 'yRelative', isConstrained: true, value: '4 + 0', sourceRange: [90, 95, true], argPosition: { type: 'arrayItem', index: 1 }, pathToNode: expect.any(Array), stdLibFnName: 'line', }, ], ], [ `angledLine(`, [ { type: 'angle', isConstrained: true, value: '3.14 + 0', sourceRange: [129, 137, true], argPosition: { type: 'objectProperty', key: 'angle' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLine', }, { type: 'length', isConstrained: true, value: '3.14 + 0', sourceRange: [148, 156, true], argPosition: { type: 'objectProperty', key: 'length' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLine', }, ], ], [ 'lineTo', [ { type: 'xAbsolute', isConstrained: true, value: '6.14 + 0', sourceRange: [178, 186, true], argPosition: { type: 'arrayItem', index: 0 }, pathToNode: expect.any(Array), stdLibFnName: 'lineTo', }, { type: 'yAbsolute', isConstrained: true, value: '3.14 + 0', sourceRange: [188, 196, true], argPosition: { type: 'arrayItem', index: 1 }, pathToNode: expect.any(Array), stdLibFnName: 'lineTo', }, ], ], [ 'xLineTo', [ { type: 'horizontal', isConstrained: true, value: 'xLineTo', sourceRange: [209, 216, true], argPosition: undefined, pathToNode: expect.any(Array), stdLibFnName: 'xLineTo', }, { type: 'xAbsolute', isConstrained: true, value: '8 + 0', sourceRange: [217, 222, true], argPosition: { type: 'singleValue' }, pathToNode: expect.any(Array), stdLibFnName: 'xLineTo', }, ], ], [ 'yLineTo', [ { type: 'vertical', isConstrained: true, value: 'yLineTo', sourceRange: [234, 241, true], argPosition: undefined, pathToNode: expect.any(Array), stdLibFnName: 'yLineTo', }, { type: 'yAbsolute', isConstrained: true, value: '5 + 0', sourceRange: [242, 247, true], argPosition: { type: 'singleValue' }, pathToNode: expect.any(Array), stdLibFnName: 'yLineTo', }, ], ], [ 'yLine(', [ { type: 'vertical', isConstrained: true, value: 'yLine', sourceRange: [259, 264, true], argPosition: undefined, pathToNode: expect.any(Array), stdLibFnName: 'yLine', }, { type: 'yRelative', isConstrained: true, value: '3.14 + 0', sourceRange: [265, 273, true], argPosition: { type: 'singleValue' }, pathToNode: expect.any(Array), stdLibFnName: 'yLine', }, ], ], [ 'xLine(', [ { type: 'horizontal', isConstrained: true, value: 'xLine', sourceRange: [289, 294, true], argPosition: undefined, pathToNode: expect.any(Array), stdLibFnName: 'xLine', }, { type: 'xRelative', isConstrained: true, value: '3.14 + 0', sourceRange: [295, 303, true], argPosition: { type: 'singleValue' }, pathToNode: expect.any(Array), stdLibFnName: 'xLine', }, ], ], [ 'angledLineOfXLength', [ { type: 'angle', isConstrained: true, value: '3.14 + 0', sourceRange: [345, 353, true], argPosition: { type: 'objectProperty', key: 'angle' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineOfXLength', }, { type: 'xRelative', isConstrained: true, value: '3.14 + 0', sourceRange: [364, 372, true], argPosition: { type: 'objectProperty', key: 'length' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineOfXLength', }, ], ], [ 'angledLineOfYLength', [ { type: 'angle', isConstrained: true, value: '30 + 0', sourceRange: [416, 422, true], argPosition: { type: 'objectProperty', key: 'angle' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineOfYLength', }, { type: 'yRelative', isConstrained: true, value: '3 + 0', sourceRange: [433, 438, true], argPosition: { type: 'objectProperty', key: 'length' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineOfYLength', }, ], ], [ 'angledLineToX', [ { type: 'angle', isConstrained: true, value: '12.14 + 0', sourceRange: [476, 485, true], argPosition: { type: 'objectProperty', key: 'angle' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineToX', }, { type: 'xAbsolute', isConstrained: true, value: '12 + 0', sourceRange: [492, 498, true], argPosition: { type: 'objectProperty', key: 'to' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineToX', }, ], ], [ 'angledLineToY', [ { type: 'angle', isConstrained: true, value: '30 + 0', sourceRange: [536, 542, true], argPosition: { type: 'objectProperty', key: 'angle' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineToY', }, { type: 'yAbsolute', isConstrained: true, value: '10.14 + 0', sourceRange: [549, 558, true], argPosition: { type: 'objectProperty', key: 'to' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineToY', }, ], ], [ 'angledLineThatIntersects', [ { type: 'angle', isConstrained: true, value: '3.14 + 0', sourceRange: [616, 624, true], argPosition: { type: 'objectProperty', key: 'angle' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineThatIntersects', }, { type: 'intersectionOffset', isConstrained: true, value: '0 + 0', sourceRange: [671, 676, true], argPosition: { type: 'objectProperty', key: 'offset' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineThatIntersects', }, { type: 'intersectionTag', isConstrained: false, value: 'a', sourceRange: [650, 651, true], argPosition: { key: 'intersectTag', type: 'objectProperty' }, pathToNode: expect.any(Array), stdLibFnName: 'angledLineThatIntersects', }, ], ], [ 'tangentialArcTo', [ { type: 'tangentialWithPrevious', isConstrained: true, value: 'tangentialArcTo', sourceRange: [697, 712, true], argPosition: undefined, pathToNode: expect.any(Array), stdLibFnName: 'tangentialArcTo', }, { type: 'xAbsolute', isConstrained: true, value: '3.14 + 0', sourceRange: [714, 722, true], argPosition: { type: 'arrayItem', index: 0 }, pathToNode: expect.any(Array), stdLibFnName: 'tangentialArcTo', }, { type: 'yAbsolute', isConstrained: true, value: '13.14 + 0', sourceRange: [724, 733, true], argPosition: { type: 'arrayItem', index: 1 }, pathToNode: expect.any(Array), stdLibFnName: 'tangentialArcTo', }, ], ], ])('testing %s when inputs are unconstrained', (functionName, expected) => { const sourceRange: SourceRange = [ code.indexOf(functionName), code.indexOf(functionName) + functionName.length, true, ] if (err(ast)) return ast const pathToNode = getNodePathFromSourceRange(ast, sourceRange) const callExp = getNodeFromPath>( ast, pathToNode, 'CallExpression' ) if (err(callExp)) return callExp const result = getConstraintInfo(callExp.node, code, pathToNode) expect(result).toEqual(expected) }) }) })