lib/zen/src/math/test.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const subject = @import("root.zig");
3 const Diagnostic = subject.Diagnostic;
4 const renderInline = subject.renderInline;
5 const renderDisplay = subject.renderDisplay;
6
7 test {
8 std.testing.refAllDecls(subject);
9 }
10
11 test "math renders the mean value property" {
12 var out: std.ArrayList(u8) = .empty;
13 defer out.deinit(std.testing.allocator);
14 try renderDisplay(&out, std.testing.allocator, "u(x) = \\mathbb{E}[u(x + R\\omega)]", null);
15 try std.testing.expectEqualStrings(
16 "<math display=\"block\"><mrow><mi>u</mi><mo stretchy=\"false\">(</mo><mi>x</mi><mo stretchy=\"false\">)</mo><mo>=</mo>" ++
17 "<mi>𝔼</mi><mo stretchy=\"false\">[</mo><mi>u</mi><mo stretchy=\"false\">(</mo><mi>x</mi><mo>+</mo><mi>R</mi><mi>ω</mi>" ++
18 "<mo stretchy=\"false\">)</mo><mo stretchy=\"false\">]</mo></mrow></math>",
19 out.items,
20 );
21 }
22
23 test "math renders fractions integrals and stretchy fences" {
24 var out: std.ArrayList(u8) = .empty;
25 defer out.deinit(std.testing.allocator);
26 try renderInline(&out, std.testing.allocator, "\\int_0^1 \\left( \\frac{x}{2} \\right) dx", null);
27 try std.testing.expectEqualStrings(
28 "<math><mrow><msubsup><mo>∫</mo><mn>0</mn><mn>1</mn></msubsup>" ++
29 "<mrow><mo stretchy=\"true\">(</mo><mfrac><mi>x</mi><mn>2</mn></mfrac>" ++
30 "<mo stretchy=\"true\">)</mo></mrow><mi>d</mi><mi>x</mi></mrow></math>",
31 out.items,
32 );
33 }
34
35 test "math renders accents movable words and spacing" {
36 var out: std.ArrayList(u8) = .empty;
37 defer out.deinit(std.testing.allocator);
38 try renderInline(&out, std.testing.allocator, "\\lim_{n \\to \\infty} \\, \\hat{f}(n)", null);
39 try std.testing.expectEqualStrings(
40 "<math><mrow><munder><mo movablelimits=\"true\">lim</mo>" ++
41 "<mrow><mi>n</mi><mo>→</mo><mi mathvariant=\"normal\">∞</mi></mrow></munder>" ++
42 "<mspace width=\"0.167em\"/>" ++
43 "<mover accent=\"true\"><mi>f</mi><mo>ˆ</mo></mover>" ++
44 "<mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow></math>",
45 out.items,
46 );
47 }
48
49 test "math renders the boundary condition as cases" {
50 var out: std.ArrayList(u8) = .empty;
51 defer out.deinit(std.testing.allocator);
52 try renderDisplay(
53 &out,
54 std.testing.allocator,
55 "u(x) = \\begin{cases} g(x) & x \\in \\partial\\Omega \\\\ \\mathbb{E}[u] & x \\in \\Omega \\end{cases}",
56 null,
57 );
58 try std.testing.expectEqualStrings(
59 "<math display=\"block\"><mrow><mi>u</mi><mo stretchy=\"false\">(</mo><mi>x</mi><mo stretchy=\"false\">)</mo><mo>=</mo>" ++
60 "<mrow><mo stretchy=\"true\">{</mo><mtable class=\"zen-cases\">" ++
61 "<mtr><mtd><mi>g</mi><mo stretchy=\"false\">(</mo><mi>x</mi><mo stretchy=\"false\">)</mo></mtd>" ++
62 "<mtd><mi>x</mi><mo>∈</mo><mi>∂</mi><mi mathvariant=\"normal\">Ω</mi></mtd></mtr>" ++
63 "<mtr><mtd><mi>𝔼</mi><mo stretchy=\"false\">[</mo><mi>u</mi><mo stretchy=\"false\">]</mo></mtd>" ++
64 "<mtd><mi>x</mi><mo>∈</mo><mi mathvariant=\"normal\">Ω</mi></mtd></mtr>" ++
65 "</mtable></mrow></mrow></math>",
66 out.items,
67 );
68 }
69
70 test "math propagates invalid equations with diagnostics" {
71 var out: std.ArrayList(u8) = .empty;
72 defer out.deinit(std.testing.allocator);
73 var diagnostic: Diagnostic = .{};
74 try std.testing.expectError(error.InvalidEquation, renderInline(&out, std.testing.allocator, "\\frac{1}", &diagnostic));
75 try std.testing.expectEqualStrings("missing argument", diagnostic.reason);
76 try std.testing.expectEqual(@as(usize, 8), diagnostic.offset);
77 try std.testing.expectError(error.InvalidEquation, renderDisplay(&out, std.testing.allocator, "", &diagnostic));
78 try std.testing.expectEqualStrings("empty equation", diagnostic.reason);
79 try std.testing.expectEqual(@as(usize, 0), diagnostic.offset);
80 }