;;; test-pearl-api.el --- Tests for pearl core API layer -*- lexical-binding: t; -*- ;; Copyright (C) 2026 Craig Jennings ;; Author: Craig Jennings ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . ;;; Commentary: ;; Tests for the GraphQL request layer with `request' stubbed at the HTTP ;; boundary: the async entry point routes to success/error correctly and ;; balances the active-request counter; the sync wrapper returns data or nil. ;;; Code: (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) (require 'testutil-request (expand-file-name "testutil-request.el")) (ert-deftest test-pearl-graphql-request-async-success-routes-to-success-fn () "A successful response is passed to the success function." (let ((got nil)) (testutil-linear-with-response '((data (viewer (name . "Me")))) (pearl--graphql-request-async "query" nil (lambda (data) (setq got data)) (lambda (&rest _) (setq got 'error)))) (should (equal '((data (viewer (name . "Me")))) got)))) (ert-deftest test-pearl-graphql-request-async-error-routes-to-error-fn () "A transport error is passed to the error function." (let ((got nil)) (testutil-linear-with-error "boom" (pearl--graphql-request-async "query" nil (lambda (_d) (setq got 'success)) (lambda (err _r _d) (setq got err)))) (should (equal "boom" got)))) (ert-deftest test-pearl-graphql-request-async-balances-active-counter-on-success () "The active-request counter returns to its starting value after success." (let ((pearl--active-requests 0)) (testutil-linear-with-response '((data)) (pearl--graphql-request-async "q" nil #'ignore #'ignore)) (should (= 0 pearl--active-requests)))) (ert-deftest test-pearl-graphql-request-async-nil-response-does-not-error () "A transport error with a nil response routes to error-fn without throwing. The error handler logs the response status code; that read must be guarded so a nil response (some transport failures) doesn't crash inside the handler." (let ((pearl-api-key "test-key") (got nil)) (cl-letf (((symbol-function 'request) (lambda (_url &rest args) (funcall (plist-get args :error) :error-thrown "boom" :response nil :data nil)))) (pearl--graphql-request-async "q" nil #'ignore (lambda (err _r _d) (setq got err)))) (should (equal "boom" got)))) (ert-deftest test-pearl-graphql-request-async-balances-active-counter-on-error () "The active-request counter returns to its starting value after an error." (let ((pearl--active-requests 0)) (testutil-linear-with-error "boom" (pearl--graphql-request-async "q" nil #'ignore #'ignore)) (should (= 0 pearl--active-requests)))) (ert-deftest test-pearl-graphql-request-sync-returns-data () "The synchronous wrapper returns the parsed response." (testutil-linear-with-response '((data (x . 1))) (should (equal '((data (x . 1))) (pearl--graphql-request "q"))))) (ert-deftest test-pearl-graphql-request-sync-error-returns-nil () "The synchronous wrapper returns nil on a transport error." (testutil-linear-with-error "boom" (should (null (pearl--graphql-request "q"))))) (provide 'test-pearl-api) ;;; test-pearl-api.el ends here