Trying to write a property based test to prove ‘js_lib.patch(json_a, elixir_lib.diff(json_a, json_b)) == json_b’
- a , b are maps and I need to check if the diff of (a,b) is equal to b.
Trying to write a property based test to prove ‘js_lib.patch(json_a, elixir_lib.diff(json_a, json_b)) == json_b’
I think something like this should probably be close to what you are looking for:
defmodule MyDiffingToolTest
use ExUnit, async: true
use ExUnitProperties
import StreamData
property "the Elixir tool works the same as the JS tool" do
check all map_a <- map_of(term(), term()),
map_b <- map_of(term(), term()) do
assert JsLib.diff(map_a, map_b) == ElixirLib.diff(map_a, map_b)
end
end
end
And then inside JsLib
you’d have some Elixir code that invokes the JS tool from within Elixir.
You might need to change term()
into something like one_of([integer(), boolean(), string(), nil])
to restrict the types to only have things that can be JSON-encoded.
Writing a generator that can generate deeply nested JSON objects/arrays is also possible, but takes a little more work. (C.f. StreamData.tree/2)
An example of generating JSON using StreamData.
(This might be cleaned up slightly, but could provide a nice starting point.)
Mix.install([
:stream_data,
:jason
])
:ok
import StreamData
# JSON 'supports' integers by secretly treating them
# as if they were 64-bit floating point numbers.
#
# This means we can (only) safely store integers that are smaller than 2**53.
# Larger integers might (implementation-dependent) result in incorrect rounding.
valid_integer = integer(-(2 ** 53)..(2 ** 53 - 1))
primitive = one_of([valid_integer, float(), string(:printable), boolean(), nil])
json_fragment_gen =
tree(primitive, fn child_gen ->
StreamData.one_of([
# A JSON array
list_of(child_gen),
# A JSON object. Only supports string keys.
map_of(string(:printable), child_gen)
])
end)
# Only valid top-level JSON are objects and arrays
json_gen = json_fragment_gen |> filter(fn val -> is_map(val) || is_list(val) end, 100)
# If you want to directly turn this into a JSON string:
json_string_gen =
StreamData.map(json_gen, &Jason.encode!(&1, escape: :javascript_safe, pretty: true))
Enum.take(json_string_gen, 10)
["{\n \"\": null\n}", "[]", "{\n \"𭘸\": null\n}", "[]", "{}", "[\n {},\n {}\n]", "[]",
"[\n [\n -1022274371879688,\n {\n \"\": -2745706130430791,\n \"\": true\n }\n ],\n {\n \"\": [\n 7941802212603036\n ],\n \"\": {\n \"\": false,\n \"\": -0.88671875\n }\n }\n]",
"{\n \"\": [\n null,\n true\n ],\n \"\": {\n \"\": null,\n \"\": \"𮝤\"\n },\n \"\": {\n \"\": false\n },\n \"\": []\n}",
"{\n \"䭦\": null\n}"]
Hi, thank you this is helpful. I am using this library for the diffing : GitHub - olafura/json_diff_ex: Diff for JSON in Elixir. I want to check if the diff(a,b) is equal to be, I might have miswrote. I believe what you wrote is checking both JS library’s diffing and the elixir diffing of a , b. First week using elixir so thank you for being patient with me.
Unless I am the one who misunderstood