diff --git a/frontend/src/app/main/data/viewer.cljs b/frontend/src/app/main/data/viewer.cljs index fc03e684b8..c2d42d680c 100644 --- a/frontend/src/app/main/data/viewer.cljs +++ b/frontend/src/app/main/data/viewer.cljs @@ -304,6 +304,7 @@ index (some-> (:index params) parse-long) frames (dm/get-in state [:viewer :pages page-id :frames]) + index (min (or index 0) (max 0 (dec (count frames)))) srect (-> (nth frames index) (get :selrect)) osize (dm/get-in state [:viewer-local :viewport-size]) @@ -327,6 +328,7 @@ index (some-> (:index params) parse-long) frames (dm/get-in state [:viewer :pages page-id :frames]) + index (min (or index 0) (max 0 (dec (count frames)))) srect (-> (nth frames index) (get :selrect)) diff --git a/frontend/test/frontend_tests/data/viewer_test.cljs b/frontend/test/frontend_tests/data/viewer_test.cljs new file mode 100644 index 0000000000..1af06766f2 --- /dev/null +++ b/frontend/test/frontend_tests/data/viewer_test.cljs @@ -0,0 +1,69 @@ +;; This Source Code Form is subject to the terms of the Mozilla Public +;; License, v. 2.0. If a copy of the MPL was not distributed with this +;; file, You can obtain one at http://mozilla.org/MPL/2.0/. +;; +;; Copyright (c) KALEIDOS INC + +(ns frontend-tests.data.viewer-test + (:require + [app.common.uuid :as uuid] + [app.main.data.viewer :as dv] + [cljs.test :as t] + [potok.v2.core :as ptk])) + +(def ^:private page-id + (uuid/custom 1 1)) + +(defn- base-state + "Build a minimal viewer state with the given frames and query-params." + [{:keys [frames index]}] + {:route {:params {:query {:page-id (str page-id) + :index (str index)}}} + :viewer {:pages {page-id {:frames frames}}} + :viewer-local {:viewport-size {:width 1000 :height 800}}}) + +(t/deftest zoom-to-fit-clamps-out-of-bounds-index + (t/testing "index exceeds frame count" + (let [state (base-state {:frames [{:selrect {:width 100 :height 100}}] + :index 1}) + result (ptk/update dv/zoom-to-fit state)] + (t/is (= (get-in result [:viewer-local :zoom-type]) :fit)) + (t/is (number? (get-in result [:viewer-local :zoom]))))) + + (t/testing "index is zero with single frame (normal case)" + (let [state (base-state {:frames [{:selrect {:width 100 :height 100}}] + :index 0}) + result (ptk/update dv/zoom-to-fit state)] + (t/is (= (get-in result [:viewer-local :zoom-type]) :fit)) + (t/is (number? (get-in result [:viewer-local :zoom]))))) + + (t/testing "index within valid range with multiple frames" + (let [state (base-state {:frames [{:selrect {:width 100 :height 100}} + {:selrect {:width 200 :height 200}}] + :index 1}) + result (ptk/update dv/zoom-to-fit state)] + (t/is (= (get-in result [:viewer-local :zoom-type]) :fit)) + (t/is (number? (get-in result [:viewer-local :zoom])))))) + +(t/deftest zoom-to-fill-clamps-out-of-bounds-index + (t/testing "index exceeds frame count" + (let [state (base-state {:frames [{:selrect {:width 100 :height 100}}] + :index 1}) + result (ptk/update dv/zoom-to-fill state)] + (t/is (= (get-in result [:viewer-local :zoom-type]) :fill)) + (t/is (number? (get-in result [:viewer-local :zoom]))))) + + (t/testing "index is zero with single frame (normal case)" + (let [state (base-state {:frames [{:selrect {:width 100 :height 100}}] + :index 0}) + result (ptk/update dv/zoom-to-fill state)] + (t/is (= (get-in result [:viewer-local :zoom-type]) :fill)) + (t/is (number? (get-in result [:viewer-local :zoom]))))) + + (t/testing "index within valid range with multiple frames" + (let [state (base-state {:frames [{:selrect {:width 100 :height 100}} + {:selrect {:width 200 :height 200}}] + :index 1}) + result (ptk/update dv/zoom-to-fill state)] + (t/is (= (get-in result [:viewer-local :zoom-type]) :fill)) + (t/is (number? (get-in result [:viewer-local :zoom])))))) diff --git a/frontend/test/frontend_tests/runner.cljs b/frontend/test/frontend_tests/runner.cljs index 1d189cbafe..fe709f8a2f 100644 --- a/frontend/test/frontend_tests/runner.cljs +++ b/frontend/test/frontend_tests/runner.cljs @@ -3,6 +3,7 @@ [cljs.test :as t] [frontend-tests.basic-shapes-test] [frontend-tests.data.repo-test] + [frontend-tests.data.viewer-test] [frontend-tests.data.workspace-colors-test] [frontend-tests.data.workspace-texts-test] [frontend-tests.helpers-shapes-test] @@ -39,6 +40,7 @@ (t/run-tests 'frontend-tests.basic-shapes-test 'frontend-tests.data.repo-test + 'frontend-tests.data.viewer-test 'frontend-tests.data.workspace-colors-test 'frontend-tests.data.workspace-texts-test 'frontend-tests.helpers-shapes-test @@ -56,9 +58,9 @@ 'frontend-tests.tokens.logic.token-remapping-test 'frontend-tests.tokens.style-dictionary-test 'frontend-tests.tokens.token-errors-test + 'frontend-tests.tokens.workspace-tokens-remap-test 'frontend-tests.ui.ds-controls-numeric-input-test 'frontend-tests.util-object-test 'frontend-tests.util-range-tree-test 'frontend-tests.util-simple-math-test - 'frontend-tests.tokens.workspace-tokens-remap-test 'frontend-tests.worker-snap-test))