-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathjson_path_access_property_test.exs
102 lines (83 loc) · 2.64 KB
/
json_path_access_property_test.exs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
defmodule JsonPathAccessPropertyTest do
use ExUnit.Case, async: true
use ExUnitProperties
property "passing a dot selector returns the list of fields" do
check all fields <- list_of(dot_selector(), min_length: 1) do
path = "$#{Enum.join(fields)}"
expected_fields = Enum.map(fields, fn "." <> name -> name end)
assert expected_fields == JsonPathAccess.to_access(path)
end
end
property "all dot wildcards selectors are returned as Access.all/1" do
check all fields <- list_of(one_of([dot_selector(), dot_wild_selector()]), min_length: 1) do
path = "$#{Enum.join(fields)}"
expected_fields =
Enum.map(fields, fn
".*" -> Access.all()
"." <> name -> name
end)
assert expected_fields == JsonPathAccess.to_access(path)
end
end
property "element index selector is returned as Access.at/1" do
check all fields <- list_of(one_of([dot_selector(), index_selector()]), min_length: 1) do
path = "$#{Enum.join(fields)}"
expected_fields =
Enum.map(fields, fn
"[" <> _rest = index_str ->
to_index_access(index_str)
"." <> name ->
name
end)
assert expected_fields == JsonPathAccess.to_access(path)
end
end
# dot-selector = "." dot-member-name
# dot-member-name = name-first *name-char
# name-first =
# ALPHA /
# "_" / ; _
# %x80-10FFFF ; any non-ASCII Unicode character
# name-char = DIGIT / name-first
# DIGIT = %x30-39 ; 0-9
# ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
defp dot_selector do
gen all name_first <- name_first(),
name_first != "",
name_char <- name_char() do
".#{name_first}#{name_char}"
end
end
defp name_first do
one_of([alpha(), constant("_"), unicode()])
end
defp name_char do
one_of([digit(), name_first()])
end
defp alpha do
string([?a..?z, ?A..?Z])
end
defp unicode do
string([0x80..0x9FFF, 0x10000..0x10FFFF])
end
defp digit do
string(?0..?9)
end
# dot-wild-selector = "." "*" ; dot followed by asterisk
defp dot_wild_selector do
constant(".*")
end
# index-selector = "[" S (quoted-member-name / element-index) S "]"
defp index_selector do
gen all index <- one_of([integer()]) do
"[#{index}]"
end
end
@element_index_re ~r/\[(?<index>[-+]?\d*)\]/
defp to_index_access(text) do
%{"index" => index} = Regex.named_captures(@element_index_re, text)
index
|> String.to_integer()
|> Access.at()
end
end