Skip to content

Commit 39db031

Browse files
Improves testing (#41)
* Adds test coverage * Adds doctests * Groups predicates into module and adds doctests * Fixes bug when referencing root schema
1 parent a0bd349 commit 39db031

File tree

12 files changed

+362
-77
lines changed

12 files changed

+362
-77
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,3 +201,13 @@ that have references across files, e.g.
201201
then the corresponding Elm file, `Domain.Circle`, will import the
202202
definitions (types, encoders and decoders) from the other Elm module,
203203
`Domain/Definitions.elm`.
204+
205+
## Tests
206+
207+
Run the standard mix task
208+
209+
mix test
210+
211+
for test coverage run
212+
213+
mix coveralls.html

lib/parser.ex

Lines changed: 15 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ defmodule JS2E.Parser do
88
alias JS2E.Parsers.{ArrayParser, ObjectParser, EnumParser, PrimitiveParser,
99
DefinitionsParser, AllOfParser, AnyOfParser, OneOfParser,
1010
UnionParser, TypeReferenceParser}
11-
alias JS2E.{TypePath, Types}
11+
alias JS2E.{TypePath, Types, Predicates}
1212
alias JS2E.Types.SchemaDefinition
1313

1414
@type nodeParser :: (
@@ -77,7 +77,7 @@ defmodule JS2E.Parser do
7777

7878
@spec parse_definitions(map, URI.t) :: Types.typeDictionary
7979
defp parse_definitions(schema_root_node, schema_id) do
80-
if definitions?(schema_root_node) do
80+
if Predicates.definitions?(schema_root_node) do
8181
schema_root_node
8282
|> DefinitionsParser.parse(schema_id, nil, ["#"], "")
8383
else
@@ -92,15 +92,15 @@ defmodule JS2E.Parser do
9292
name = "#"
9393

9494
cond do
95-
ref_type?(schema_root_node) ->
95+
Predicates.ref_type?(schema_root_node) ->
9696
schema_root_node
9797
|> TypeReferenceParser.parse(schema_id, schema_id, type_path, name)
9898

99-
object_type?(schema_root_node) ->
99+
Predicates.object_type?(schema_root_node) ->
100100
schema_root_node
101101
|> parse_type(schema_id, [], name)
102102

103-
array_type?(schema_root_node) ->
103+
Predicates.array_type?(schema_root_node) ->
104104
schema_root_node
105105
|> parse_type(schema_id, [], name)
106106

@@ -161,16 +161,16 @@ defmodule JS2E.Parser do
161161
defp determine_node_parser(schema_node) do
162162

163163
predicate_node_type_pairs = [
164-
{&ref_type?/1, &TypeReferenceParser.parse/5},
165-
{&enum_type?/1, &EnumParser.parse/5},
166-
{&union_type?/1, &UnionParser.parse/5},
167-
{&all_of_type?/1, &AllOfParser.parse/5},
168-
{&any_of_type?/1, &AnyOfParser.parse/5},
169-
{&one_of_type?/1, &OneOfParser.parse/5},
170-
{&object_type?/1, &ObjectParser.parse/5},
171-
{&array_type?/1, &ArrayParser.parse/5},
172-
{&primitive_type?/1, &PrimitiveParser.parse/5},
173-
{&definitions?/1, &DefinitionsParser.parse/5}
164+
{&Predicates.ref_type?/1, &TypeReferenceParser.parse/5},
165+
{&Predicates.enum_type?/1, &EnumParser.parse/5},
166+
{&Predicates.union_type?/1, &UnionParser.parse/5},
167+
{&Predicates.all_of_type?/1, &AllOfParser.parse/5},
168+
{&Predicates.any_of_type?/1, &AnyOfParser.parse/5},
169+
{&Predicates.one_of_type?/1, &OneOfParser.parse/5},
170+
{&Predicates.object_type?/1, &ObjectParser.parse/5},
171+
{&Predicates.array_type?/1, &ArrayParser.parse/5},
172+
{&Predicates.primitive_type?/1, &PrimitiveParser.parse/5},
173+
{&Predicates.definitions?/1, &DefinitionsParser.parse/5}
174174
]
175175

176176
predicate_node_type_pairs
@@ -194,54 +194,4 @@ defmodule JS2E.Parser do
194194
end
195195
end
196196

197-
@spec definitions?(map) :: boolean
198-
defp definitions?(schema_node) do
199-
Map.has_key?(schema_node, "definitions")
200-
end
201-
202-
@spec primitive_type?(map) :: boolean
203-
defp primitive_type?(schema_node) do
204-
schema_node["type"] in ["null", "boolean", "string", "number", "integer"]
205-
end
206-
207-
@spec ref_type?(map) :: boolean
208-
defp ref_type?(schema_node) do
209-
Map.has_key?(schema_node, "$ref")
210-
end
211-
212-
@spec enum_type?(map) :: boolean
213-
defp enum_type?(schema_node) do
214-
Map.has_key?(schema_node, "enum")
215-
end
216-
217-
@spec all_of_type?(map) :: boolean
218-
defp all_of_type?(schema_node) do
219-
Map.get(schema_node, "allOf")
220-
end
221-
222-
@spec any_of_type?(map) :: boolean
223-
defp any_of_type?(schema_node) do
224-
Map.get(schema_node, "anyOf")
225-
end
226-
227-
@spec one_of_type?(map) :: boolean
228-
defp one_of_type?(schema_node) do
229-
Map.get(schema_node, "oneOf")
230-
end
231-
232-
@spec union_type?(map) :: boolean
233-
defp union_type?(schema_node) do
234-
is_list(schema_node["type"])
235-
end
236-
237-
@spec object_type?(map) :: boolean
238-
defp object_type?(schema_node) do
239-
schema_node["type"] == "object" && Map.has_key?(schema_node, "properties")
240-
end
241-
242-
@spec array_type?(map) :: boolean
243-
defp array_type?(schema_node) do
244-
schema_node["type"] == "array" && Map.has_key?(schema_node, "items")
245-
end
246-
247197
end

lib/parsers/object_parser.ex

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,20 @@ defmodule JS2E.Parsers.ObjectParser do
6363
end)
6464
end
6565

66+
@doc ~S"""
67+
Creates a property dictionary based on a type dictionary and a type path.
68+
69+
## Examples
70+
71+
iex> type_dict = %{}
72+
...> path = JS2E.TypePath.from_string("#")
73+
...> JS2E.Parsers.ObjectParser.create_property_dict(type_dict, path)
74+
%{}
75+
76+
"""
6677
@spec create_property_dict(Types.typeDictionary, TypePath.t)
6778
:: Types.propertyDictionary
68-
defp create_property_dict(type_dict, path) do
79+
def create_property_dict(type_dict, path) do
6980
type_dict
7081
|> Enum.reduce(%{}, fn({child_path, child_type}, reference_dict) ->
7182
child_type_path = TypePath.add_child(path, child_type.name)

lib/parsers/util.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ defmodule JS2E.Parsers.Util do
4747
end
4848

4949
@doc ~S"""
50-
Returns a list of type paths based when given a type dictionary.
50+
Returns a list of type paths when given a type dictionary.
5151
"""
5252
@spec create_types_list(Types.typeDictionary, TypePath.t) :: [TypePath.t]
5353
def create_types_list(type_dict, path) do

lib/predicates.ex

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
defmodule JS2E.Predicates do
2+
@moduledoc ~S"""
3+
Contains various predicate functions for working with json schemas.
4+
"""
5+
6+
@doc ~S"""
7+
Returns true if the json schema contains a 'definitions' property.
8+
9+
## Examples
10+
11+
iex> JS2E.Predicates.definitions?(%{"title" => "A fancy title"})
12+
false
13+
14+
iex> JS2E.Predicates.definitions?(%{"definitions" => %{}})
15+
true
16+
17+
"""
18+
@spec definitions?(map) :: boolean
19+
def definitions?(schema_node) do
20+
definitions = schema_node["definitions"]
21+
is_map(definitions)
22+
end
23+
24+
@doc ~S"""
25+
Returns true if the json subschema represents a primitive type.
26+
27+
## Examples
28+
29+
iex> JS2E.Predicates.primitive_type?(%{})
30+
false
31+
32+
iex> JS2E.Predicates.primitive_type?(%{"type" => "object"})
33+
false
34+
35+
iex> JS2E.Predicates.primitive_type?(%{"type" => "boolean"})
36+
true
37+
38+
iex> JS2E.Predicates.primitive_type?(%{"type" => "integer"})
39+
true
40+
41+
"""
42+
@spec primitive_type?(map) :: boolean
43+
def primitive_type?(schema_node) do
44+
type = schema_node["type"]
45+
type in ["null", "boolean", "string", "number", "integer"]
46+
end
47+
48+
@doc ~S"""
49+
Returns true if the json subschema represents a reference to another schema.
50+
51+
## Examples
52+
53+
iex> JS2E.Predicates.ref_type?(%{})
54+
false
55+
56+
iex> JS2E.Predicates.ref_type?(%{"$ref" => "#foo"})
57+
true
58+
59+
"""
60+
@spec ref_type?(map) :: boolean
61+
def ref_type?(schema_node) do
62+
ref = schema_node["$ref"]
63+
is_binary(ref)
64+
end
65+
66+
@doc ~S"""
67+
Returns true if the json subschema represents an enum type.
68+
69+
## Examples
70+
71+
iex> JS2E.Predicates.enum_type?(%{})
72+
false
73+
74+
iex> JS2E.Predicates.enum_type?(%{"enum" => ["red", "yellow", "green"]})
75+
true
76+
77+
"""
78+
@spec enum_type?(map) :: boolean
79+
def enum_type?(schema_node) do
80+
enum = schema_node["enum"]
81+
is_list(enum)
82+
end
83+
84+
@doc ~S"""
85+
Returns true if the json subschema represents an allOf type.
86+
87+
## Examples
88+
89+
iex> JS2E.Predicates.all_of_type?(%{})
90+
false
91+
92+
iex> JS2E.Predicates.all_of_type?(%{"allOf" => []})
93+
false
94+
95+
iex> JS2E.Predicates.all_of_type?(%{"allOf" => [%{"$ref" => "#foo"}]})
96+
true
97+
98+
"""
99+
@spec all_of_type?(map) :: boolean
100+
def all_of_type?(schema_node) do
101+
all_of = schema_node["allOf"]
102+
is_list(all_of) && length(all_of) > 0
103+
end
104+
105+
@doc ~S"""
106+
Returns true if the json subschema represents an anyOf type.
107+
108+
## Examples
109+
110+
iex> JS2E.Predicates.any_of_type?(%{})
111+
false
112+
113+
iex> JS2E.Predicates.any_of_type?(%{"anyOf" => []})
114+
false
115+
116+
iex> JS2E.Predicates.any_of_type?(%{"anyOf" => [%{"$ref" => "#foo"}]})
117+
true
118+
119+
"""
120+
@spec any_of_type?(map) :: boolean
121+
def any_of_type?(schema_node) do
122+
any_of = schema_node["anyOf"]
123+
is_list(any_of) && length(any_of) > 0
124+
end
125+
126+
@doc ~S"""
127+
Returns true if the json subschema represents an oneOf type.
128+
129+
## Examples
130+
131+
iex> JS2E.Predicates.one_of_type?(%{})
132+
false
133+
134+
iex> JS2E.Predicates.one_of_type?(%{"oneOf" => []})
135+
false
136+
137+
iex> JS2E.Predicates.one_of_type?(%{"oneOf" => [%{"$ref" => "#foo"}]})
138+
true
139+
140+
"""
141+
@spec one_of_type?(map) :: boolean
142+
def one_of_type?(schema_node) do
143+
one_of = schema_node["oneOf"]
144+
is_list(one_of) && length(one_of) > 0
145+
end
146+
147+
@doc ~S"""
148+
Returns true if the json subschema represents a union type.
149+
150+
## Examples
151+
152+
iex> JS2E.Predicates.union_type?(%{})
153+
false
154+
155+
iex> JS2E.Predicates.union_type?(%{"type" => ["number", "integer", "string"]})
156+
true
157+
158+
"""
159+
@spec union_type?(map) :: boolean
160+
def union_type?(schema_node) do
161+
type = schema_node["type"]
162+
is_list(type)
163+
end
164+
165+
@doc ~S"""
166+
Returns true if the json subschema represents an allOf type.
167+
168+
## Examples
169+
170+
iex> JS2E.Predicates.object_type?(%{})
171+
false
172+
173+
iex> JS2E.Predicates.object_type?(%{"type" => "object"})
174+
false
175+
176+
iex> anObject = %{"type" => "object",
177+
...> "properties" => %{"name" => %{"type" => "string"}}}
178+
iex> JS2E.Predicates.object_type?(anObject)
179+
true
180+
181+
"""
182+
@spec object_type?(map) :: boolean
183+
def object_type?(schema_node) do
184+
type = schema_node["type"]
185+
properties = schema_node["properties"]
186+
type == "object" && is_map(properties)
187+
end
188+
189+
@doc ~S"""
190+
Returns true if the json subschema represents an array type.
191+
192+
## Examples
193+
194+
iex> JS2E.Predicates.array_type?(%{})
195+
false
196+
197+
iex> JS2E.Predicates.array_type?(%{"type" => "array"})
198+
false
199+
200+
iex> anArray = %{"type" => "array", "items" => %{"$ref" => "#foo"}}
201+
iex> JS2E.Predicates.array_type?(anArray)
202+
true
203+
204+
"""
205+
@spec array_type?(map) :: boolean
206+
def array_type?(schema_node) do
207+
type = schema_node["type"]
208+
items = schema_node["items"]
209+
type == "array" && is_map(items)
210+
end
211+
212+
end

lib/printers/enum_printer.ex

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ defmodule JS2E.Printers.EnumPrinter do
152152

153153
@spec create_elm_value(String.t, String.t) :: String.t
154154
defp create_elm_value(value, type) do
155+
Logger.debug "Value: #{value}, Type: #{type}"
156+
155157
case type do
156158
"string" ->
157159
upcase_first value

0 commit comments

Comments
 (0)