~theo/gql

d2570766a6963f00418ba5c17497a08cdb2cac73 — Theodor Thornhill 7 months ago 281c95e
Resolve union members

Fixes: https://todo.sr.ht/~theo/gql/29
2 files changed, 54 insertions(+), 6 deletions(-)

M src/execution.lisp
M t/execution-tests.lisp
M src/execution.lisp => src/execution.lisp +8 -6
@@ 259,13 259,15 @@

(defun resolve-abstract-type (abstract-type object-value)
  ;; TODO: https://spec.graphql.org/draft/#ResolveAbstractType()
  ;; TODO: #29
  (check-type object-value gql-object)
  (etypecase abstract-type
    (interface-type-definition
     ;; TODO: Should this error handle somehow?
     (gethash (type-name object-value) *all-types*))
    (union-type-definition nil)))
  (let* ((type-name (type-name object-value))
         (object-definition (gethash type-name *all-types*)))
    (etypecase abstract-type
      (interface-type-definition object-definition)
      (union-type-definition
       (let ((union-member
               (find type-name (union-members abstract-type) :key #'nameof :test #'string=)))
         (gethash (nameof union-member) *all-types*))))))

(defun execute-field (object-type object-value field-type fields variable-values)
  ;; TODO: https://spec.graphql.org/draft/#sec-Executing-Fields

M t/execution-tests.lisp => t/execution-tests.lisp +46 -0
@@ 216,6 216,52 @@
               (command (gethash "doesKnowCommand" dog)))
          (ok (string= command "false")))))))

(deftest abstract-type-resolvers
  (testing "Getting object-type-definition from union or interface"
    (defclass pet (gql-object)
      ((name :initarg :name :accessor name)))

    (defclass dog (pet)
      ((owner :initarg :owner :accessor owner)
       (nickname :initarg :nickname :accessor nickname)))

    (defclass cat (pet)
      ((nickname :initarg :nickname :accessor nickname)))

    (defclass sentient (gql-object)
      ((name :initarg :name :accessor name)))

    (defclass human (sentient)
      ((pets :initarg :pets :accessor pets)))

    (defparameter *doggo*
      (make-instance
       'dog
       :name "Bingo-Bongo"
       :type-name "Dog"
       :nickname "Hund!"
       :owner (make-instance
               'human
               :name "Wingle Wangle"
               :type-name "Human"
               :pets `(,(make-instance
                         'dog
                         :name "Bingo-Bongo"
                         :nickname "Hund!"
                         :type-name "Dog")
                       ,(make-instance
                         'cat
                         :name "Bango-Wango"
                         :nickname "Mjausig"
                         :type-name "Cat")))))

    (with-schema (build-schema (asdf:system-relative-pathname 'gql-tests #p"t/test-files/validation-schema.graphql"))
      ;; We want to know if we did get the actual same reference.
      (ok (eq (gql::resolve-abstract-type (gethash "CatOrDog" gql::*all-types*) *doggo*)
              (gethash "Dog" gql::*all-types*)))
      (ok (eq (gql::resolve-abstract-type (gethash "Pet" gql::*all-types*) *doggo*)
              (gethash "Dog" gql::*all-types*))))))

(deftest doggo-test
  (testing "Doggo-testing"
    (defclass pet (gql-object)