Skip to content

Commit

Permalink
Fix parser bug with sequential selection sets (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
ilmoraunio authored May 22, 2024
1 parent 5633c5c commit e784eec
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 15 deletions.
3 changes: 2 additions & 1 deletion src/oksa/alpha/api.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@
- keyword (representing a naked field)
- `oksa.alpha.api/fragment-spread`
- `oksa.alpha.api/inline-fragment`
- `oksa.alpha.api/select` (but only directly after a field)
Tolerates nil entries.
Expand Down Expand Up @@ -321,7 +322,7 @@
(-selection-set? %)
(-fragment-spread? %)
(-inline-fragment? %)) selections*))
"invalid selections, expected `oksa.alpha.api/field`, keyword (naked field), `oksa.alpha.api/fragment-spread`, or `oksa.alpha.api/inline-fragment`")
"invalid selections, expected `oksa.alpha.api/field`, keyword (naked field), `oksa.alpha.api/select`, `oksa.alpha.api/fragment-spread`, or `oksa.alpha.api/inline-fragment`")
(oksa.parse/-selection-set selections*)))

(defn field
Expand Down
26 changes: 21 additions & 5 deletions src/oksa/parse.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,21 @@
[:? [:schema [:ref ::TypeOpts]]]
[:schema [:ref ::Type]]]
::SelectionSet [:orn
[::SelectionSet [:+ [:catn
[::node [:schema [:ref ::Selection]]]
[::children [:? [:schema [:ref ::SelectionSet]]]]]]]]
[::SelectionSet [:+ [:alt
[:catn
[::node [:schema [:ref ::Selection]]]
[::children [:? [:schema [:ref ::SelectionSet]]]]]
[:catn
[::node [:schema [:ref ::WrappedField]]]]
;; Special case where subsequent selection set is allowed
[:catn
[::node [:schema [:ref ::BareField]]]
[::children [:? [:schema [:ref ::SelectionSet]]]]]]]]]
::WrappedField [:orn [::WrappedField [:schema [:ref ::Field]]]]
::Selection [:orn
[::FragmentSpread [:schema [:ref ::FragmentSpread]]]
[::InlineFragment [:schema [:ref ::InlineFragment]]]
[::NakedField [:schema [:ref ::NakedField]]]
[::WrappedField [:schema [:ref ::Field]]]]
[::NakedField [:schema [:ref ::NakedField]]]]
::Field [:orn [::Field [:cat
[:schema [:ref ::FieldName]]
[:map
Expand All @@ -116,6 +123,14 @@
[:directives {:optional true}
[:ref ::Directives]]]
[:? [:schema [:ref ::SelectionSet]]]]]]
::BareField [:orn [::Field [:cat
[:schema [:ref ::FieldName]]
[:map
[:alias {:optional true} [:ref ::Alias]]
[:arguments {:optional true}
[:ref ::Arguments]]
[:directives {:optional true}
[:ref ::Directives]]]]]]
::NakedField [:schema [:ref ::FieldName]]
::FieldName [:and
[:schema [:ref ::Name]]
Expand Down Expand Up @@ -947,6 +962,7 @@
(let [[selection-type value] node]
(cond-> (into []
[(case selection-type
:oksa.parse/Field (oksa.util/transform-malli-ast -transform-map node)
:oksa.parse/NakedField (oksa.util/transform-malli-ast -transform-map [:oksa.parse/Field [value {}]])
:oksa.parse/WrappedField (oksa.util/transform-malli-ast -transform-map value)
:oksa.parse/FragmentSpread (oksa.util/transform-malli-ast -transform-map value)
Expand Down
19 changes: 17 additions & 2 deletions test/oksa/alpha/api_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
(:require [camel-snake-kebab.core :as csk]
[#?(:clj clojure.test
:cljs cljs.test) :as t]
[oksa.core :as oksa]
[oksa.alpha.api :as api])
#?(:clj (:import [graphql.parser Parser])))

Expand Down Expand Up @@ -100,7 +101,7 @@
(t/is (= "{bar{qux{baz}}}"
(unparse-and-validate (api/select :bar
(api/select :qux
(api/select :baz))))
(api/select :baz))))
(unparse-and-validate (api/select (api/field :bar)
(api/select (api/field :qux)
(api/select (api/field :baz)))))
Expand Down Expand Up @@ -482,7 +483,21 @@
(t/is (= "query ($foo:Bar @fooDirective(fooArg:123)){fooField}"
(unparse-and-validate (api/query (api/opts (api/variable :foo (api/opts (api/directive :fooDirective {:fooArg 123}))
:Bar))
(api/select :fooField)))))))
(api/select :fooField))))))
(t/testing "sequentiality"
(t/is (= "{foo{bar}}"
(unparse-and-validate
(api/select
(api/field :foo)
(api/select :bar))))
"field w/o selection-set + sequential selection-set parses correctly")
(t/testing "sequential selection sets should throw an exception"
(t/is (thrown? #?(:clj Exception :cljs js/Error)
(unparse-and-validate
(api/select
(api/field :foo
(api/select :qux :baz))
(api/select :basho))))))))

(t/deftest transformers-test
(t/testing "names are transformed when transformer fn is provided"
Expand Down
30 changes: 23 additions & 7 deletions test/oksa/core_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,27 @@
(t/is (= "{subscription{subscription{baz}}}" (unparse-and-validate [:subscription [:subscription [:baz]]])))))
(t/testing "selection set"
(t/is (= "{foo}"
(unparse-and-validate [:foo])))
(unparse-and-validate [:foo])
(unparse-and-validate [[:foo {}]])))
(t/is (= "{foo bar}"
(unparse-and-validate [:foo :bar])))
(unparse-and-validate [:foo :bar])
(unparse-and-validate [[:foo {}] [:bar {}]])))
(t/is (= "{bar{qux{baz}}}"
(unparse-and-validate [:bar [:qux [:baz]]])))
(unparse-and-validate [:bar [:qux [:baz]]])
(unparse-and-validate [[:bar {}] [[:qux {}] [[:baz {}]]]])
(unparse-and-validate [[:bar {} [[:qux {} [[:baz {}]]]]]])))
(t/is (= "{foo bar{qux{baz}}}"
(unparse-and-validate [:foo :bar [:qux [:baz]]])))
(unparse-and-validate [:foo :bar [:qux [:baz]]])
(unparse-and-validate [[:foo {}] [:bar {}] [[:qux {} [[:baz {}]]]]])
(unparse-and-validate [[:foo {}] [:bar {} [[:qux {} [[:baz {}]]]]]])))
(t/is (= "{foo bar{qux baz}}"
(unparse-and-validate [:foo :bar [:qux :baz]])))
(unparse-and-validate [:foo :bar [:qux :baz]])
(unparse-and-validate [[:foo {}] [:bar {}] [[:qux {}] [:baz {}]]])
(unparse-and-validate [[:foo {}] [:bar {} [[:qux {}] [:baz {}]]]])))
(t/is (= "{foo{bar{baz qux} frob}}"
(unparse-and-validate [:foo [:bar [:baz :qux] :frob]])))
(unparse-and-validate [:foo [:bar [:baz :qux] :frob]])
(unparse-and-validate [[:foo {}] [:bar [:baz :qux] :frob]])
(unparse-and-validate [[:foo {} [:bar [:baz :qux] :frob]]])))
(t/testing "support strings as field names"
(t/is (= "{foo}"
(unparse-and-validate ["foo"])
Expand Down Expand Up @@ -296,7 +306,13 @@
[:fooField]])))
(t/is (= "query ($foo:Bar @fooDirective(fooArg:123)){fooField}"
(unparse-and-validate [:oksa/query {:variables [:foo {:directives [[:fooDirective {:arguments {:fooArg 123}}]]} :Bar]}
[:fooField]])))))
[:fooField]]))))
(t/testing "sequentiality"
(t/is (= "{foo{bar}}"
(unparse-and-validate [[:foo {}] [:bar]])) "field w/o selection-set + sequential selection-set parses correctly")
(t/testing "sequential selection sets should throw an exception"
(t/is (thrown? #?(:clj Exception :cljs js/Error)
(unparse-and-validate [[:foo {} [:qux :baz]] [:basho]]))))))

(t/deftest transformers-test
(t/testing "names are transformed when transformer fn is provided"
Expand Down

0 comments on commit e784eec

Please sign in to comment.