266 lines
11 KiB
Ruby
266 lines
11 KiB
Ruby
require "spec_helper"
|
|
|
|
describe CeleryScript::Corpus do
|
|
let(:device) { FactoryBot.create(:device) }
|
|
let(:corpus) { Sequence::Corpus }
|
|
|
|
it "handles valid move_absolute blocks" do
|
|
ok1 = CeleryScript::AstNode.new(**{
|
|
kind: "move_absolute",
|
|
args: {
|
|
location: {
|
|
kind: "coordinate",
|
|
args: {
|
|
x: 1,
|
|
y: 2,
|
|
z: 3,
|
|
},
|
|
},
|
|
offset: {
|
|
kind: "coordinate",
|
|
args: {
|
|
"x": 0,
|
|
"y": 0,
|
|
"z": 0,
|
|
},
|
|
},
|
|
speed: 100,
|
|
},
|
|
})
|
|
check1 = CeleryScript::Checker.new(ok1, corpus, device)
|
|
expect(check1.valid?).to be_truthy
|
|
|
|
ok2 = CeleryScript::AstNode.new(**{
|
|
kind: "move_absolute",
|
|
args: {
|
|
location: {
|
|
kind: "tool",
|
|
args: { tool_id: FactoryBot.create(:tool).id },
|
|
},
|
|
offset: {
|
|
kind: "coordinate",
|
|
args: {
|
|
"x": 0,
|
|
"y": 0,
|
|
"z": 0,
|
|
},
|
|
},
|
|
speed: 100,
|
|
},
|
|
})
|
|
check2 = CeleryScript::Checker.new(ok2, corpus, device)
|
|
expect(check2.valid?).to be_truthy
|
|
end
|
|
|
|
it "kicks back invalid move_absolute nodes" do
|
|
bad = CeleryScript::AstNode.new(**{
|
|
kind: "move_absolute",
|
|
args: {
|
|
location: 42,
|
|
speed: 100,
|
|
offset: {
|
|
kind: "coordinate",
|
|
args: {
|
|
"x": 0,
|
|
"y": 0,
|
|
"z": 0,
|
|
},
|
|
},
|
|
},
|
|
})
|
|
check = CeleryScript::Checker.new(bad, corpus, device)
|
|
expect(check.valid?).to be_falsey
|
|
expect(check.error.message).to include("but got Integer")
|
|
expect(check.error.message).to include("'location' within 'move_absolute'")
|
|
end
|
|
|
|
it "finds problems with nested nodes" do
|
|
bad = CeleryScript::AstNode.new(**{
|
|
kind: "move_absolute",
|
|
args: {
|
|
location: {
|
|
kind: "tool",
|
|
args: { tool_id: "PROBLEM!" }, # <= Invalid:
|
|
},
|
|
offset: {
|
|
kind: "coordinate",
|
|
args: { "x": 0, "y": 0, "z": 0 },
|
|
},
|
|
speed: 100,
|
|
},
|
|
})
|
|
check = CeleryScript::Checker.new(bad, corpus, device)
|
|
expect(check.valid?).to be_falsey
|
|
expect(check.error.message).to include("but got String")
|
|
end
|
|
|
|
it "serializes into JSON" do
|
|
result = JSON.parse(corpus.to_json)
|
|
|
|
expect(result["version"]).to eq(Sequence::LATEST_VERSION)
|
|
expect(result["args"]).to be_kind_of(Array)
|
|
expect(result["nodes"]).to be_kind_of(Array)
|
|
keys = result["nodes"].sample.keys.sort.map(&:to_sym)
|
|
expect(keys).to eq([:allowed_args, :allowed_body_types, :docs, :name, :tags])
|
|
expect(result["args"].sample.keys.sort).to eq(["allowed_values",
|
|
"name"])
|
|
end
|
|
|
|
it "Handles message_type validations for version 1" do
|
|
# This test is __ONLY__ relevant for version 1.
|
|
# Change / delete / update as needed.
|
|
tree = CeleryScript::AstNode.new(**{
|
|
"kind": "send_message",
|
|
"args": {
|
|
"message": "Hello, world!",
|
|
"message_type": "wrong",
|
|
},
|
|
"body": [],
|
|
})
|
|
checker = CeleryScript::Checker.new(tree, corpus, device)
|
|
expect(checker.error.message).to include("not a valid message_type")
|
|
end
|
|
|
|
it "Handles channel_name validations" do
|
|
tree = CeleryScript::AstNode.new(**{
|
|
"kind": "send_message",
|
|
"args": {
|
|
"message": "Hello, world!",
|
|
"message_type": "fun",
|
|
},
|
|
"body": [
|
|
{
|
|
"kind": "channel",
|
|
"args": { "channel_name": "wrong" },
|
|
},
|
|
],
|
|
})
|
|
checker = CeleryScript::Checker.new(tree, corpus, device)
|
|
expect(checker.error.message).to include("not a valid channel_name")
|
|
end
|
|
|
|
it "validates tool_ids" do
|
|
ast = { "kind": "tool", "args": { "tool_id": 0 } }
|
|
checker = CeleryScript::Checker.new(CeleryScript::AstNode.new(**ast),
|
|
corpus,
|
|
device)
|
|
expect(checker.valid?).to be(false)
|
|
expect(checker.error.message).to include("Tool #0 does not exist.")
|
|
end
|
|
|
|
it "Validates update_resource nodes" do
|
|
ast = {
|
|
kind: "update_resource",
|
|
args: {
|
|
"resource" => {
|
|
kind: "resource",
|
|
args: {
|
|
"resource_type" => "Device",
|
|
"resource_id" => 23, # Mutated to "0" later..
|
|
},
|
|
},
|
|
},
|
|
body: [
|
|
{
|
|
kind: "pair",
|
|
args: {
|
|
"label" => "mounted_tool_id",
|
|
"value" => 1,
|
|
},
|
|
},
|
|
],
|
|
}
|
|
checker = CeleryScript::Checker
|
|
.new(CeleryScript::AstNode.new(**ast), corpus, device)
|
|
expect(checker.valid?).to be(true)
|
|
device_id = checker.tree.args[:resource].args[:resource_id].value
|
|
expect(device_id).to eq(device.id)
|
|
end
|
|
|
|
it "deprecates resource_updates" do
|
|
fake_id = FactoryBot.create(:plant).id + 1
|
|
expect(Plant.exists?(fake_id)).to be(false)
|
|
ast = { "kind": "resource_update",
|
|
"args": { "resource_type" => "Plant",
|
|
"resource_id" => fake_id,
|
|
"label" => "foo",
|
|
"value" => "Should Fail" } }
|
|
hmm = CeleryScript::AstNode.new(**ast)
|
|
expect(hmm.args.fetch(:resource_id).value).to eq(fake_id)
|
|
checker = CeleryScript::Checker.new(hmm, corpus, device)
|
|
expect(checker.valid?).to be(false)
|
|
msg = "Deprecated `mark_as` detected. Delete it and re-add"
|
|
expect(checker.error.message).to eq(msg)
|
|
end
|
|
|
|
it "has enums" do
|
|
args = [name = :foo, list = ["bar", "baz"], tpl = ["foo: %s bar: %s"]]
|
|
c = CeleryScript::Corpus.new.enum(*args)
|
|
json = c.as_json
|
|
enums = json.fetch(:enums)
|
|
expect(enums.length).to eq(1)
|
|
expect(enums.first.fetch("name")).to eq(name)
|
|
expect(enums.first.fetch("allowed_values")).to eq(list)
|
|
end
|
|
|
|
it "has values" do
|
|
args = [name = :whatever, list = [Symbol, Hash]]
|
|
c = CeleryScript::Corpus.new.value(*args)
|
|
json = c.as_json
|
|
values = json.fetch(:values)
|
|
expect(values.length).to eq(1)
|
|
expect(values.first.fetch("name")).to eq(name)
|
|
expect(values.first.keys.length).to eq(1)
|
|
end
|
|
|
|
it "assigns tags and documentation to nodes" do
|
|
c = CeleryScript::Corpus.new.node("wonderful",
|
|
args: [],
|
|
body: [],
|
|
tags: ["great"],
|
|
docs: "spectacular")
|
|
json = c.as_json
|
|
values = json.fetch(:nodes)
|
|
expect(values.length).to eq(1)
|
|
value = values.first
|
|
expect(value.fetch("tags").first).to eq("great")
|
|
expect(value.fetch("docs")).to eq("spectacular")
|
|
end
|
|
|
|
it "sets a MAX_WAIT_MS limit for `wait` nodes" do
|
|
bad = CeleryScript::AstNode.new(**{
|
|
kind: "wait",
|
|
args: { milliseconds: CeleryScriptSettingsBag::MAX_WAIT_MS + 10 },
|
|
})
|
|
check = CeleryScript::Checker.new(bad, corpus, device)
|
|
expect(check.valid?).to be_falsey
|
|
expect(check.error.message).to include("cannot exceed 3 minutes")
|
|
end
|
|
|
|
it "allows valid `point_group` nodes" do
|
|
device.auto_sync_transaction do
|
|
pg = PointGroups::Create.run!(device: device,
|
|
name: "cs checks",
|
|
point_ids: [])
|
|
bad = CeleryScript::AstNode.new(**{
|
|
kind: "point_group",
|
|
args: { point_group_id: pg.id },
|
|
})
|
|
check = CeleryScript::Checker.new(bad, corpus, device)
|
|
expect(check.valid?).to be true
|
|
end
|
|
end
|
|
|
|
it "disallows invalid `point_group` nodes" do
|
|
device.auto_sync_transaction do
|
|
bad = CeleryScript::AstNode.new(**{
|
|
kind: "point_group",
|
|
args: { point_group_id: -1 },
|
|
})
|
|
check = CeleryScript::Checker.new(bad, corpus, device)
|
|
expect(check.valid?).to be false
|
|
expect(check.error.message).to eq("Can't find PointGroup with id of -1")
|
|
end
|
|
end
|
|
end
|