prosody/spec/util_datamapper_spec.lua
Kim Alvefur 965c49b92d util.datamapper: Simplify test schema
Don't need the function, more compact to just reference the same
reference table.
2022-12-20 18:55:47 +01:00

243 lines
6.8 KiB
Lua

local st
local xml
local map
setup(function()
st = require "util.stanza";
xml = require "util.xml";
map = require "util.datamapper";
end);
describe("util.datamapper", function()
local s, x, d
local disco, disco_info, disco_schema
setup(function()
-- a convenience function for simple attributes, there's a few of them
local attr = {["$ref"]="#/$defs/attr"};
s = {
["$defs"] = { attr = { type = "string"; xml = { attribute = true } } };
type = "object";
xml = {name = "message"; namespace = "jabber:client"};
properties = {
to = attr;
from = attr;
type = attr;
id = attr;
body = true; -- should be assumed to be a string
lang = {type = "string"; xml = {attribute = true; prefix = "xml"}};
delay = {
type = "object";
xml = {namespace = "urn:xmpp:delay"; name = "delay"};
properties = {stamp = attr; from = attr; reason = {type = "string"; xml = {text = true}}};
};
state = {
type = "string";
enum = {
"active",
"inactive",
"gone",
"composing",
"paused",
};
xml = {x_name_is_value = true; namespace = "http://jabber.org/protocol/chatstates"};
};
fallback = {
type = "boolean";
xml = {x_name_is_value = true; name = "fallback"; namespace = "urn:xmpp:fallback:0"};
};
origin_id = {
type = "string";
xml = {name = "origin-id"; namespace = "urn:xmpp:sid:0"; x_single_attribute = "id"};
};
react = {
type = "object";
xml = {namespace = "urn:xmpp:reactions:0"; name = "reactions"};
properties = {
to = {type = "string"; xml = {attribute = true; name = "id"}};
-- should be assumed to be array since it has 'items'
reactions = { items = { xml = { name = "reaction" } } };
};
};
stanza_ids = {
type = "array";
items = {
xml = {name = "stanza-id"; namespace = "urn:xmpp:sid:0"};
type = "object";
properties = {
id = attr;
by = attr;
};
};
};
};
};
x = xml.parse [[
<message xmlns="jabber:client" xml:lang="en" to="a@test" from="b@test" type="chat" id="1">
<body>Hello</body>
<delay xmlns='urn:xmpp:delay' from='test' stamp='2021-03-07T15:59:08+00:00'>Because</delay>
<UNRELATED xmlns='http://jabber.org/protocol/chatstates'/>
<active xmlns='http://jabber.org/protocol/chatstates'/>
<fallback xmlns='urn:xmpp:fallback:0'/>
<origin-id xmlns='urn:xmpp:sid:0' id='qgkmMdPB'/>
<stanza-id xmlns='urn:xmpp:sid:0' id='abc1' by='muc'/>
<stanza-id xmlns='urn:xmpp:sid:0' id='xyz2' by='host'/>
<reactions id='744f6e18-a57a-11e9-a656-4889e7820c76' xmlns='urn:xmpp:reactions:0'>
<reaction>👋</reaction>
<reaction>🐢</reaction>
</reactions>
</message>
]];
d = {
to = "a@test";
from = "b@test";
type = "chat";
id = "1";
lang = "en";
body = "Hello";
delay = {from = "test"; stamp = "2021-03-07T15:59:08+00:00"; reason = "Because"};
state = "active";
fallback = true;
origin_id = "qgkmMdPB";
stanza_ids = {{id = "abc1"; by = "muc"}; {id = "xyz2"; by = "host"}};
react = {
to = "744f6e18-a57a-11e9-a656-4889e7820c76";
reactions = {
"👋",
"🐢",
};
};
};
disco_schema = {
["$defs"] = { attr = { type = "string"; xml = { attribute = true } } };
type = "object";
xml = {
name = "iq";
namespace = "jabber:client"
};
properties = {
to = attr;
from = attr;
type = attr;
id = attr;
disco = {
type = "object";
xml = {
name = "query";
namespace = "http://jabber.org/protocol/disco#info"
};
properties = {
features = {
type = "array";
items = {
type = "string";
xml = {
name = "feature";
x_single_attribute = "var";
};
};
};
};
};
};
};
disco_info = xml.parse[[
<iq type="result" id="disco1" from="example.com">
<query xmlns="http://jabber.org/protocol/disco#info">
<feature var="urn:example:feature:1">wrong</feature>
<feature var="urn:example:feature:2"/>
<feature var="urn:example:feature:3"/>
<unrelated var="urn:example:feature:not"/>
</query>
</iq>
]];
disco = {
type="result";
id="disco1";
from="example.com";
disco = {
features = {
"urn:example:feature:1";
"urn:example:feature:2";
"urn:example:feature:3";
};
};
};
end);
describe("parse", function()
it("works", function()
assert.same(d, map.parse(s, x));
end);
it("handles arrays", function ()
assert.same(disco, map.parse(disco_schema, disco_info));
end);
it("deals with locally built stanzas", function()
-- FIXME this could also be argued to be a util.stanza problem
local ver_schema = {
type = "object";
xml = {name = "iq"};
properties = {
type = {type = "string"; xml = {attribute = true}};
id = {type = "string"; xml = {attribute = true}};
version = {
type = "object";
xml = {name = "query"; namespace = "jabber:iq:version"};
-- properties should be assumed to be strings
properties = {name = true; version = {}; os = {}};
};
};
};
local ver_st = st.iq({type = "result"; id = "v1"})
:query("jabber:iq:version")
:text_tag("name", "Prosody")
:text_tag("version", "trunk")
:text_tag("os", "Lua 5.3")
:reset();
local data = {type = "result"; id = "v1"; version = {name = "Prosody"; version = "trunk"; os = "Lua 5.3"}}
assert.same(data, map.parse(ver_schema, ver_st));
end);
end);
describe("unparse", function()
it("works", function()
local u = map.unparse(s, d);
assert.equal("message", u.name);
assert.same(x.attr, u.attr);
assert.equal(x:get_child_text("body"), u:get_child_text("body"));
assert.equal(x:get_child_text("delay", "urn:xmpp:delay"), u:get_child_text("delay", "urn:xmpp:delay"));
assert.same(x:get_child("delay", "urn:xmpp:delay").attr, u:get_child("delay", "urn:xmpp:delay").attr);
assert.same(x:get_child("origin-id", "urn:xmpp:sid:0").attr, u:get_child("origin-id", "urn:xmpp:sid:0").attr);
assert.same(x:get_child("reactions", "urn:xmpp:reactions:0").attr, u:get_child("reactions", "urn:xmpp:reactions:0").attr);
assert.same(2, #u:get_child("reactions", "urn:xmpp:reactions:0").tags);
for _, tag in ipairs(x.tags) do
if tag.name ~= "UNRELATED" then
assert.truthy(u:get_child(tag.name, tag.attr.xmlns) or u:get_child(tag.name), tag:top_tag())
end
end
assert.equal(#x.tags-1, #u.tags)
end);
it("handles arrays", function ()
local u = map.unparse(disco_schema, disco);
assert.equal("urn:example:feature:1", u:find("{http://jabber.org/protocol/disco#info}query/feature/@var"))
local n = 0;
for child in u:get_child("query", "http://jabber.org/protocol/disco#info"):childtags("feature") do
n = n + 1;
assert.equal(string.format("urn:example:feature:%d", n), child.attr.var);
end
end);
end);
end)