1bf36d1f52
* <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.
622 lines
14 KiB
Elixir
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
|