mfm-parser/test/parser_test.exs
Ilja 1bf36d1f52 Code review part 3
* <https://ilja.space/notice/ALpd6nux5hT2nsfetM>
    * Previous commit: `|> fill_props(token) after the cond` in the parser
    * Previous commit: Don't use intention-specific data in the tokens (e.g. left is reverse, x is mfm-spinX)
* <https://ilja.space/notice/ALpcK6W59UjkIUofU8>
    * This commit: Use less files
* Previous commit: Change nested if-statement in mfm.ex to `cond do`

I also added some more and better info to the README.md and moduledocs.
2022-07-25 14:13:43 +02:00

622 lines
14 KiB
Elixir

defmodule MfmParser.ParserTest do
use ExUnit.Case
alias MfmParser.Parser
doctest MfmParser.Parser
describe "single element input" do
test "it can handle an empty string as input" do
input = ""
assert Parser.parse(input) == []
end
test "it can handle text as input" do
input = "pain au chocolat"
output = [%MfmParser.Node.Text{props: %{text: "pain au chocolat"}}]
assert Parser.parse(input) == output
end
test "it can handle a newline as input" do
input = "\n"
output = [%MfmParser.Node.Newline{props: %{text: "\n"}}]
assert Parser.parse(input) == output
end
test "it can handle a flip element" do
input_default = "$[flip ]"
input_v = "$[flip.v ]"
input_hv = "$[flip.h,v ]"
output_default = [
%MfmParser.Node.MFM.Flip{
props: %{
v: false,
h: false
},
children: []
}
]
output_v = [
%MfmParser.Node.MFM.Flip{
props: %{
v: true,
h: false
},
children: []
}
]
output_hv = [
%MfmParser.Node.MFM.Flip{
props: %{
v: true,
h: true
},
children: []
}
]
assert Parser.parse(input_default) == output_default
assert Parser.parse(input_v) == output_v
assert Parser.parse(input_hv) == output_hv
end
test "it can handle a font element" do
input = "$[font.serif ]"
output = [
%MfmParser.Node.MFM.Font{
props: %{
font: "serif"
},
children: []
}
]
assert Parser.parse(input) == output
end
test "it can handle an x element" do
input2 = "$[x2 ]"
input3 = "$[x3 ]"
input4 = "$[x4 ]"
output2 = [
%MfmParser.Node.MFM.X{
props: %{
size: "200%"
},
children: []
}
]
output3 = [
%MfmParser.Node.MFM.X{
props: %{
size: "400%"
},
children: []
}
]
output4 = [
%MfmParser.Node.MFM.X{
props: %{
size: "600%"
},
children: []
}
]
assert Parser.parse(input2) == output2
assert Parser.parse(input3) == output3
assert Parser.parse(input4) == output4
end
test "it can handle a blur element" do
input = "$[blur ]"
output = [
%MfmParser.Node.MFM.Blur{
props: %{},
children: []
}
]
assert Parser.parse(input) == output
end
test "it can handle a jelly element" do
input_default = "$[jelly ]"
output_default = [
%MfmParser.Node.MFM.Jelly{
props: %{
speed: "1s"
},
children: []
}
]
input_speed = "$[jelly.speed=20s ]"
output_speed = [
%MfmParser.Node.MFM.Jelly{
props: %{
speed: "20s"
},
children: []
}
]
assert Parser.parse(input_default) == output_default
assert Parser.parse(input_speed) == output_speed
end
test "it can handle a tada element" do
input_default = "$[tada ]"
output_default = [
%MfmParser.Node.MFM.Tada{
props: %{
speed: "1s"
},
children: []
}
]
input_speed = "$[tada.speed=20s ]"
output_speed = [
%MfmParser.Node.MFM.Tada{
props: %{
speed: "20s"
},
children: []
}
]
assert Parser.parse(input_default) == output_default
assert Parser.parse(input_speed) == output_speed
end
test "it can handle a jump element" do
input_default = "$[jump ]"
output_default = [
%MfmParser.Node.MFM.Jump{
props: %{
speed: "0.75s"
},
children: []
}
]
input_speed = "$[jump.speed=20s ]"
output_speed = [
%MfmParser.Node.MFM.Jump{
props: %{
speed: "20s"
},
children: []
}
]
assert Parser.parse(input_default) == output_default
assert Parser.parse(input_speed) == output_speed
end
test "it can handle a bounce element" do
input_default = "$[bounce ]"
output_default = [
%MfmParser.Node.MFM.Bounce{
props: %{
speed: "0.75s"
},
children: []
}
]
input_speed = "$[bounce.speed=20s ]"
output_speed = [
%MfmParser.Node.MFM.Bounce{
props: %{
speed: "20s"
},
children: []
}
]
assert Parser.parse(input_default) == output_default
assert Parser.parse(input_speed) == output_speed
end
test "it can handle a spin element" do
input_default = "$[spin ]"
output_default = [
%MfmParser.Node.MFM.Spin{
props: %{
axis: "z",
direction: "normal",
speed: "1.5s"
},
children: []
}
]
input_left = "$[spin.left ]"
output_left = [
%MfmParser.Node.MFM.Spin{
props: %{
axis: "z",
direction: "left",
speed: "1.5s"
},
children: []
}
]
input_alternate = "$[spin.alternate ]"
output_alternate = [
%MfmParser.Node.MFM.Spin{
props: %{
axis: "z",
direction: "alternate",
speed: "1.5s"
},
children: []
}
]
input_x = "$[spin.x ]"
output_x = [
%MfmParser.Node.MFM.Spin{
props: %{
axis: "x",
direction: "normal",
speed: "1.5s"
},
children: []
}
]
input_x_left = "$[spin.x,left ]"
output_x_left = [
%MfmParser.Node.MFM.Spin{
props: %{
axis: "x",
direction: "left",
speed: "1.5s"
},
children: []
}
]
input_x_alternate = "$[spin.x,alternate ]"
output_x_alternate = [
%MfmParser.Node.MFM.Spin{
props: %{
axis: "x",
direction: "alternate",
speed: "1.5s"
},
children: []
}
]
input_y = "$[spin.y ]"
output_y = [
%MfmParser.Node.MFM.Spin{
props: %{
axis: "y",
direction: "normal",
speed: "1.5s"
},
children: []
}
]
input_y_left = "$[spin.y,left ]"
output_y_left = [
%MfmParser.Node.MFM.Spin{
props: %{
axis: "y",
direction: "left",
speed: "1.5s"
},
children: []
}
]
input_y_alternate = "$[spin.y,alternate ]"
output_y_alternate = [
%MfmParser.Node.MFM.Spin{
props: %{
axis: "y",
direction: "alternate",
speed: "1.5s"
},
children: []
}
]
input_speed = "$[spin.speed=20s ]"
output_speed = [
%MfmParser.Node.MFM.Spin{
props: %{
axis: "z",
direction: "normal",
speed: "20s"
},
children: []
}
]
assert Parser.parse(input_default) == output_default
assert Parser.parse(input_left) == output_left
assert Parser.parse(input_alternate) == output_alternate
assert Parser.parse(input_x) == output_x
assert Parser.parse(input_x_left) == output_x_left
assert Parser.parse(input_x_alternate) == output_x_alternate
assert Parser.parse(input_y) == output_y
assert Parser.parse(input_y_left) == output_y_left
assert Parser.parse(input_y_alternate) == output_y_alternate
assert Parser.parse(input_speed) == output_speed
end
test "it can handle a shake element" do
input_default = "$[shake ]"
output_default = [
%MfmParser.Node.MFM.Shake{
props: %{
speed: "0.5s"
},
children: []
}
]
input_speed = "$[shake.speed=20s ]"
output_speed = [
%MfmParser.Node.MFM.Shake{
props: %{
speed: "20s"
},
children: []
}
]
assert Parser.parse(input_default) == output_default
assert Parser.parse(input_speed) == output_speed
end
test "it can handle a twitch element" do
input_default = "$[twitch ]"
output_default = [
%MfmParser.Node.MFM.Twitch{
props: %{
speed: "0.5s"
},
children: []
}
]
input_speed = "$[twitch.speed=0.2s ]"
output_speed = [
%MfmParser.Node.MFM.Twitch{
props: %{
speed: "0.2s"
},
children: []
}
]
assert Parser.parse(input_default) == output_default
assert Parser.parse(input_speed) == output_speed
end
test "it can handle a rainbow element" do
input_default = "$[rainbow ]"
output_default = [
%MfmParser.Node.MFM.Rainbow{
props: %{
speed: "1s"
},
children: []
}
]
input_speed = "$[rainbow.speed=20s ]"
output_speed = [
%MfmParser.Node.MFM.Rainbow{
props: %{
speed: "20s"
},
children: []
}
]
assert Parser.parse(input_default) == output_default
assert Parser.parse(input_speed) == output_speed
end
test "it can handle a sparkle element" do
input = "$[sparkle ]"
output = [
%MfmParser.Node.MFM.Sparkle{
props: %{},
children: []
}
]
assert Parser.parse(input) == output
end
test "it can handle a rotate element" do
input = "$[rotate ]"
output = [
%MfmParser.Node.MFM.Rotate{
props: %{},
children: []
}
]
assert Parser.parse(input) == output
end
test "it can handle an undefined element" do
input = "$[blabla ]"
output = [
%MfmParser.Node.MFM.Undefined{
props: %{},
children: []
}
]
assert Parser.parse(input) == output
end
test "it doesn't crash on a lost end token" do
Parser.parse("]")
end
test "it doesn't crash on a non-closed token" do
Parser.parse("$[spi")
Parser.parse("$[spin ")
Parser.parse("$[spin chocolatine")
end
end
describe "multiple element input" do
test "it can handle multiple elements as input" do
input = "$[twitch ]chocolatine$[blabla ]\n$[jump ]"
assert Parser.parse(input) == [
%MfmParser.Node.MFM.Twitch{children: [], props: %{speed: "0.5s"}},
%MfmParser.Node.Text{props: %{text: "chocolatine"}},
%MfmParser.Node.MFM.Undefined{children: [], props: %{}},
%MfmParser.Node.Newline{props: %{text: "\n"}},
%MfmParser.Node.MFM.Jump{children: [], props: %{speed: "0.75s"}}
]
end
test "it can handle nesting" do
input = "$[twitch chocolatine]"
assert Parser.parse(input) == [
%MfmParser.Node.MFM.Twitch{
children: [%MfmParser.Node.Text{props: %{text: "chocolatine"}}],
props: %{speed: "0.5s"}
}
]
end
test "it can handle multiple nesting" do
input = "$[twitch $[spin chocolatine]]"
assert Parser.parse(input) == [
%MfmParser.Node.MFM.Twitch{
children: [
%MfmParser.Node.MFM.Spin{
children: [%MfmParser.Node.Text{props: %{text: "chocolatine"}}],
props: %{direction: "normal", axis: "z", speed: "1.5s"}
}
],
props: %{speed: "0.5s"}
}
]
end
test "it can handle a complex structure of multiple elements and nesting" do
input =
"It's not $[twitch chocolatine]\nit's $[x4 $[spin pain] $[rainbow au] $[jump chocolat]]"
assert Parser.parse(input) == [
%MfmParser.Node.Text{props: %{text: "It's not "}},
%MfmParser.Node.MFM.Twitch{
children: [%MfmParser.Node.Text{props: %{text: "chocolatine"}}],
props: %{speed: "0.5s"}
},
%MfmParser.Node.Newline{props: %{text: "\n"}},
%MfmParser.Node.Text{props: %{text: "it's "}},
%MfmParser.Node.MFM.X{
children: [
%MfmParser.Node.MFM.Spin{
children: [%MfmParser.Node.Text{props: %{text: "pain"}}],
props: %{direction: "normal", axis: "z", speed: "1.5s"}
},
%MfmParser.Node.Text{props: %{text: " "}},
%MfmParser.Node.MFM.Rainbow{
children: [%MfmParser.Node.Text{props: %{text: "au"}}],
props: %{speed: "1s"}
},
%MfmParser.Node.Text{props: %{text: " "}},
%MfmParser.Node.MFM.Jump{
children: [%MfmParser.Node.Text{props: %{text: "chocolat"}}],
props: %{speed: "0.75s"}
}
],
props: %{size: "600%"}
}
]
end
end
describe "to_props/1" do
test "it returns speed in the list of parameters" do
assert %{speed: "5s"} = Parser.to_props("$[blabla.speed=5s")
assert %{speed: "0.5s"} = Parser.to_props("$[blabla.speed=0.5s")
end
test "it returns v and h in the list of parameters" do
assert %{v: true} = Parser.to_props("$[blabla.v")
assert %{v: true, h: true} = Parser.to_props("$[blabla.h,v")
end
test "it returns fonts" do
assert %{font: "some_font"} = Parser.to_props("$[font.some_font")
end
test "it returns a size for an x element" do
assert %{size: "200%"} = Parser.to_props("$[x2")
assert %{size: "400%"} = Parser.to_props("$[x3")
assert %{size: "600%"} = Parser.to_props("$[x4")
assert %{size: "100%"} = Parser.to_props("$[xqsdfqsf")
end
test "it returns an empty list when there are no parameters" do
assert %{} = Parser.to_props("$[blabla")
end
test "it ignores unknown parameters" do
assert %{} = Parser.to_props("$[blabla.idk")
end
end
end