A world-class math input for the web
at main 147 lines 4.7 kB view raw
1import { describe, expect, test } from "vitest"; 2import { 3 AddNode, 4 DecimalNode, 5 DivideNode, 6 EquationNode, 7 ExponentNode, 8 FunctionCallNode, 9 MultiplyNode, 10 RadicalNode, 11 toText, 12 VariableNode, 13} from "."; 14 15test("Convert x to text", () => { 16 expect(toText(VariableNode.from("x"))).toStrictEqual("x"); 17}); 18 19test("Convert 3 to text", () => { 20 expect(toText(DecimalNode.from("3"))).toStrictEqual("3"); 21}); 22 23test("Convert x+2.5 to text", () => { 24 expect( 25 toText(AddNode.from([VariableNode.from("x"), DecimalNode.from("2.5")])), 26 ).toStrictEqual("x plus 2.5"); 27}); 28 29test("Convert a^2 + b^2 = c^2 to text", () => { 30 expect( 31 toText( 32 EquationNode.from([ 33 AddNode.from([ 34 ExponentNode.from(VariableNode.from("a"), DecimalNode.from("2")), 35 ExponentNode.from(VariableNode.from("b"), DecimalNode.from("2")), 36 ]), 37 ExponentNode.from(VariableNode.from("c"), DecimalNode.from("2")), 38 ]), 39 ), 40 ).toStrictEqual("a squared plus b squared equals c squared"); // TODO: Find a better output that pronounces 'a' as "aye" rather than "uh" 41}); 42 43test("Convert sqrt(x+1) to text", () => { 44 expect( 45 toText( 46 RadicalNode.from( 47 AddNode.from([VariableNode.from("x"), DecimalNode.from("1")]), 48 ), 49 ), 50 ).toStrictEqual("square root of x plus 1"); 51}); 52 53test("Convert sqrt(x)+1 to text", () => { 54 expect( 55 toText( 56 AddNode.from([ 57 RadicalNode.from(VariableNode.from("x")), 58 DecimalNode.from("1"), 59 ]), 60 ), 61 ).toStrictEqual("square root of x, plus 1"); 62}); 63 64test("Convert f(x+1)+1 to text", () => { 65 expect( 66 toText( 67 AddNode.from([ 68 FunctionCallNode.from("f", [ 69 AddNode.from([VariableNode.from("x"), DecimalNode.from("1")]), 70 ]), 71 DecimalNode.from("1"), 72 ]), 73 ), 74 ).toStrictEqual("f of x plus 1, plus 1"); 75}); 76 77test("Convert f(a)*b to text", () => { 78 expect( 79 toText( 80 MultiplyNode.from([ 81 FunctionCallNode.from("f", [VariableNode.from("a")]), 82 VariableNode.from("b"), 83 ]), 84 ), 85 ).toStrictEqual("f of a, times b"); 86}); 87 88test("Convert (a+b)*c to text", () => { 89 expect( 90 toText( 91 MultiplyNode.from([ 92 AddNode.from([VariableNode.from("a"), VariableNode.from("b")]), 93 VariableNode.from("c"), 94 ]), 95 ), 96 ).toStrictEqual("a plus b, times c"); 97}); 98 99describe("Convert fractions to text", () => { 100 const fracText = (num: string, den: string) => { 101 return toText( 102 DivideNode.from(DecimalNode.from(num), DecimalNode.from(den)), 103 ); 104 }; 105 106 test("0/0", () => void expect(fracText("0", "0")).toBe("0 over 0")); 107 108 test("0/1", () => void expect(fracText("0", "1")).toBe("0 over 1")); 109 test("1/1", () => void expect(fracText("1", "1")).toBe("1 over 1")); 110 111 test("0/2", () => void expect(fracText("0", "2")).toBe("0 halves")); 112 test("1/2", () => void expect(fracText("1", "2")).toBe("1 half")); 113 test("2/2", () => void expect(fracText("2", "2")).toBe("2 halves")); 114 test("0/3", () => void expect(fracText("0", "3")).toBe("0 thirds")); 115 116 test("1/3", () => void expect(fracText("1", "3")).toBe("1 third")); 117 test("2/3", () => void expect(fracText("2", "3")).toBe("2 thirds")); 118 test("3/3", () => void expect(fracText("3", "3")).toBe("3 thirds")); 119 test("4/3", () => void expect(fracText("4", "3")).toBe("4 thirds")); 120 121 test("1/4", () => void expect(fracText("1", "4")).toBe("1 fourth")); 122 test("2/4", () => void expect(fracText("2", "4")).toBe("2 fourths")); 123 124 test("1/5", () => void expect(fracText("1", "5")).toBe("1 fifth")); 125 test("2/5", () => void expect(fracText("2", "5")).toBe("2 fifths")); 126 127 test("1/6", () => void expect(fracText("1", "6")).toBe("1 sixth")); 128 test("2/6", () => void expect(fracText("2", "6")).toBe("2 sixths")); 129 130 test("1/7", () => void expect(fracText("1", "7")).toBe("1 seventh")); 131 test("2/7", () => void expect(fracText("2", "7")).toBe("2 sevenths")); 132 133 test("1/8", () => void expect(fracText("1", "8")).toBe("1 eighth")); 134 test("2/8", () => void expect(fracText("2", "8")).toBe("2 eighths")); 135 136 test("1/9", () => void expect(fracText("1", "9")).toBe("1 ninth")); 137 test("2/9", () => void expect(fracText("2", "9")).toBe("2 ninths")); 138 139 test("1/10", () => void expect(fracText("1", "10")).toBe("1 tenth")); 140 test("2/10", () => void expect(fracText("2", "10")).toBe("2 tenths")); 141 142 test("1/11", () => void expect(fracText("1", "11")).toBe("1 eleventh")); 143 test("2/11", () => void expect(fracText("2", "11")).toBe("2 elevenths")); 144 145 test("1/12", () => void expect(fracText("1", "12")).toBe("1 twelfth")); 146 test("2/12", () => void expect(fracText("2", "12")).toBe("2 twelfths")); 147});