;;; ebox-package-tests.el --- Package contract tests -*- lexical-binding: t; -*- (require 'cl-lib) (require 'ert) (defconst ebox-test--root (expand-file-name ".." (file-name-directory (or load-file-name buffer-file-name))) "Repository root used by package contract tests.") (load-file (expand-file-name "ebox.el" ebox-test--root)) (defconst ebox-test--autoload-source-files '("ebox.el" "ebox-measure.el" "ebox-layout.el" "ebox-flex.el" "ebox-grid.el" "ebox-buffer-backend.el" "ebox-selector.el" "ebox-native-reflow.el") "Source files that currently own public autoload entry points.") (defun ebox-test--source-text () "Return combined source text for files that own public autoloads." (with-temp-buffer (dolist (file ebox-test--autoload-source-files) (insert-file-contents (expand-file-name file ebox-test--root)) (insert "\n")) (buffer-string))) (ert-deftest ebox-package-defines-custom-group-and-scroll-option () "The package exposes a real customization group and default scroll option." (should (get 'ebox 'custom-group)) (should (custom-variable-p 'ebox-scroll-step)) (should (integerp ebox-scroll-step)) (should (> ebox-scroll-step 0)) (should (custom-variable-p 'ebox-wheel-scroll-step)) (should (integerp ebox-wheel-scroll-step)) (should (> ebox-wheel-scroll-step 0)) (should (custom-variable-p 'ebox-wheel-smooth-scroll)) (should (custom-variable-p 'ebox-wheel-smooth-scroll-interval)) (should (numberp ebox-wheel-smooth-scroll-interval)) (should (> ebox-wheel-smooth-scroll-interval 0)) (should (custom-variable-p 'ebox-wheel-smooth-scroll-lines-per-tick)) (should (integerp ebox-wheel-smooth-scroll-lines-per-tick)) (should (> ebox-wheel-smooth-scroll-lines-per-tick 0))) (ert-deftest ebox-facade-loads-internal-model-modules () "The public ebox facade should load all internal foundation modules." (require 'ebox) (dolist (feature '(ebox-cache ebox-style ebox-tree ebox-measure ebox-fragment ebox-layout ebox-flex ebox-grid ebox-buffer-backend ebox-incremental ebox-surface ebox-viewport ebox-dsl ebox-selector)) (should (featurep feature)))) (ert-deftest ebox-facade-exposes-native-workflow-without-loading-it () "The two native commands should be available without native load work." (require 'ebox) (should (autoloadp (symbol-function 'ebox-native-build))) (should (autoloadp (symbol-function 'ebox-native-status))) (should-not (featurep 'ebox-native-reflow))) (ert-deftest ebox-byte-compile-is-an-interactive-public-command () "Users should be able to rebuild all active Ebox bytecode from Emacs." (should (commandp 'ebox-byte-compile)) (should (equal ebox--compile-sources '("ebox-cache.el" "ebox-style.el" "ebox-child-range.el" "ebox-tree.el" "ebox-measure.el" "ebox-fragment.el" "ebox-render-context.el" "ebox-layout.el" "ebox-flex.el" "ebox-grid.el" "ebox-buffer-backend.el" "ebox-incremental.el" "ebox-native-commit.el" "ebox-surface.el" "ebox-viewport.el" "ebox-dsl.el" "ebox-selector.el" "ebox.el" "ebox-native-reflow.el")))) (ert-deftest ebox-surface-depends-only-on-public-tp-api () "The Ebox projection boundary should never call private TP symbols." (let ((source (with-temp-buffer (insert-file-contents (expand-file-name "ebox-surface.el" ebox-test--root)) (buffer-string)))) (should-not (string-match-p "\\_" (regexp-quote (cdr entry)) (regexp-quote (car entry))) source))))) (ert-deftest ebox-public-api-includes-all-public-autoloaded-entry-points () "The facade inventory should not omit an autoloaded public entry point." (dolist (entry '(ebox-byte-compile ebox-buffer-update-report ebox-build ebox-buffer-mode ebox-call-with-render-burst ebox-candidate-begin ebox-child-range ebox-candidate-replace ebox-candidate-replace-range-ref ebox-candidate-replace-root ebox-candidate-replace-host-ref ebox-clear-cache ebox-column ebox-commit ebox-concat ebox-create ebox-display-buffer ebox-display-signature ebox-flex ebox-flex-item ebox-grid ebox-grid-fr ebox-grid-item ebox-host-ref-bounds ebox-host-ref-position ebox-native-build ebox-native-status ebox-region-ids ebox-region-resolve ebox-region-update ebox-render ebox-render-burst-begin ebox-render-burst-end ebox-render-to-buffer ebox-rerender-buffer-with-context ebox-row ebox-scroll-down ebox-scroll-page-down ebox-scroll-page-up ebox-scroll-state ebox-scroll-up ebox-selector-match-node-p ebox-selector-parse ebox-selector-query-all ebox-selector-query-buffer ebox-selector-update-buffer ebox-spacer ebox-stack ebox-string-pixel-width)) (should (memq entry ebox-public-api)))) (ert-deftest ebox-live-buffer-publication-uses-only-tp-surfaces () "The facade should expose no raw live-buffer writer beside TP surfaces." (require 'ebox) (dolist (entry '(ebox-render-to-buffer ebox-display-buffer)) (should (fboundp entry)) (should (memq entry ebox-public-api))) (dolist (entry '(ebox-pop-to-buffer ebox-switch-to-buffer)) (should-not (fboundp entry)) (should-not (memq entry ebox-public-api))) (let ((source (with-temp-buffer (insert-file-contents (expand-file-name "ebox.el" ebox-test--root)) (buffer-string)))) (dolist (definition '("ebox--to-buffer" "ebox-pop-to-buffer" "ebox-switch-to-buffer")) (should-not (string-match-p (format "(defmacro[[:space:]]+%s\\_>" (regexp-quote definition)) source))))) (ert-deftest ebox-package-exposes-buffer-report-accessor-only () "The package surface should expose buffer-owned reports, not a global API." (require 'ebox) (should (fboundp 'ebox-buffer-update-report)) (should-not (fboundp 'ebox-last-update-report)) (let ((source (ebox-test--source-text))) (should (string-match-p ";;;###autoload[[:space:]\n]+(defun ebox-buffer-update-report\\_>" source)) (should-not (string-match-p ";;;###autoload[[:space:]\n]+(defun ebox-last-update-report\\_>" source)))) (provide 'ebox-package-tests) ;;; ebox-package-tests.el ends here