shard-radix/spec/radix/node_spec.cr
Luis Lavena 9003075ec7 Introduce types for forward compiler compatiblity
After Crystal 0.15, compiler will require declare the types used
by instance variables on classes.

This require changes to the usage of `Radix::Tree` by introducing
the type of payload elements it will handle:

    # Will only support symbols as payload
    tree = Radix::Tree(Symbol).new
    tree.add "/", :root

    # Error: cannot add node with anything other than Symbol
    tree.add "/meaning-of-life", 42

The changes ensure future compatibility with Crystal and also
enforces a more declarative usage of `Radix::Tree`.

If necessary, you can combine multiple types to ensure a tree
can contain all the wide range of payloads you need:

    tree = Radix::Tree.new(Foo | Bar | Symbol).new
    tree.add "/", :root
    tree.add "/foo", foo_instance

This change includes:

- Tree, Node and Result has been updated to require types.
- Node is capable of have optional payload (from defined type).
- Documentation has been updated to reflect this change.
2016-04-16 16:53:20 -03:00

109 lines
2.9 KiB
Crystal

require "../spec_helper"
module Radix
describe Node do
describe "#key=" do
it "accepts change of key after initialization" do
node = Node(Nil).new("abc")
node.key.should eq("abc")
node.key = "xyz"
node.key.should eq("xyz")
end
end
describe "#payload" do
it "accepts any form of payload" do
node = Node.new("abc", :payload)
node.payload?.should be_truthy
node.payload.should eq(:payload)
node = Node.new("abc", 1_000)
node.payload?.should be_truthy
node.payload.should eq(1_000)
end
# This example focuses on the internal representation of `payload`
# as inferred from supplied types and default values.
#
# We cannot compare `typeof` against `property!` since it excludes `Nil`
# from the possible types.
it "makes optional to provide a payload" do
node = Node(Int32).new("abc")
node.payload?.should be_falsey
typeof(node.@payload).should eq(Int32 | Nil)
end
end
describe "#priority" do
it "calculates it based on key size" do
node = Node(Nil).new("a")
node.priority.should eq(1)
node = Node(Nil).new("abc")
node.priority.should eq(3)
end
it "returns zero for catch all (globbed) key" do
node = Node(Nil).new("*filepath")
node.priority.should eq(0)
node = Node(Nil).new("/src/*filepath")
node.priority.should eq(0)
end
it "returns one for keys with named parameters" do
node = Node(Nil).new(":query")
node.priority.should eq(1)
node = Node(Nil).new("/search/:query")
node.priority.should eq(1)
end
it "changes when key changes" do
node = Node(Nil).new("a")
node.priority.should eq(1)
node.key = "abc"
node.priority.should eq(3)
node.key = "*filepath"
node.priority.should eq(0)
node.key = ":query"
node.priority.should eq(1)
end
end
describe "#sort!" do
it "orders children by priority" do
root = Node(Int32).new("/")
node1 = Node(Int32).new("a", 1)
node2 = Node(Int32).new("bc", 2)
node3 = Node(Int32).new("def", 3)
root.children.push(node1, node2, node3)
root.sort!
root.children[0].should eq(node3)
root.children[1].should eq(node2)
root.children[2].should eq(node1)
end
it "orders catch all and named parameters lower than others" do
root = Node(Int32).new("/")
node1 = Node(Int32).new("*filepath", 1)
node2 = Node(Int32).new("abc", 2)
node3 = Node(Int32).new(":query", 3)
root.children.push(node1, node2, node3)
root.sort!
root.children[0].should eq(node2)
root.children[1].should eq(node3)
root.children[2].should eq(node1)
end
end
end
end