mirror of
https://github.com/penpot/penpot.git
synced 2026-03-29 15:52:17 +02:00
* ♻️ Handle fetch-error gracefully with toast instead of full-page error Network-level failures (lost connectivity, DNS failure, etc.) on RPC calls were propagating as :internal/:fetch-error to the global error handler, which replaced the entire UI with a full-page error screen. Now the :internal handler distinguishes :fetch-error from other internal errors and shows a non-intrusive toast notification instead, allowing the user to continue working. * ✨ Add automatic retry with backoff for idempotent RPC requests Idempotent (GET) RPC requests are now automatically retried up to 3 times with exponential back-off (1s, 2s, 4s) when a transient error occurs. Retryable errors include: network-level failures (:fetch-error), 502 Bad Gateway, 503 Service Unavailable, and browser offline (status 0). Mutation (POST) requests are never retried to avoid unintended side-effects. Non-transient errors (4xx client errors, auth errors, validation errors) propagate immediately without retry. * ♻️ Make retry helpers public with configurable parameters Make retryable-error? and with-retry public functions, and replace private constants with a default-retry-config map. with-retry now accepts an optional config map (:max-retries, :base-delay-ms) enabling callers and tests to customize retry behavior. * ✨ Add tests for RPC retry mechanism Comprehensive tests for the retry helpers in app.main.repo: - retryable-error? predicate: covers all retryable types (fetch-error, bad-gateway, service-unavailable, offline) and non-retryable types (validation, authentication, authorization, plain errors) - with-retry observable wrapper: verifies immediate success, recovery after transient failures, max-retries exhaustion, no retry for non-retryable errors, fetch-error retry, custom config, and mixed error scenarios * ♻️ Introduce :network error type for fetch-level failures Replace the awkward {:type :internal :code :fetch-error} combination with a proper {:type :network} type in app.util.http/fetch. This makes the error taxonomy self-explanatory and removes the special-case branch in the :internal handler. Consequences: - http.cljs: emit {:type :network} instead of {:type :internal :code :fetch-error} - errors.cljs: add a dedicated ptk/handle-error :network method (toast); restore :internal handler to its original unconditional full-page error form - repo.cljs: simplify retryable-types and retryable-error? — :network replaces the former :internal special-case, no code check needed - repo_test.cljs: update tests to use {:type :network} * 📚 Add comment explaining the use of bit-shift-left
61 lines
2.3 KiB
Clojure
61 lines
2.3 KiB
Clojure
(ns frontend-tests.runner
|
|
(:require
|
|
[cljs.test :as t]
|
|
[frontend-tests.basic-shapes-test]
|
|
[frontend-tests.data.repo-test]
|
|
[frontend-tests.data.workspace-colors-test]
|
|
[frontend-tests.helpers-shapes-test]
|
|
[frontend-tests.logic.comp-remove-swap-slots-test]
|
|
[frontend-tests.logic.components-and-tokens]
|
|
[frontend-tests.logic.copying-and-duplicating-test]
|
|
[frontend-tests.logic.frame-guides-test]
|
|
[frontend-tests.logic.groups-test]
|
|
[frontend-tests.logic.pasting-in-containers-test]
|
|
[frontend-tests.plugins.context-shapes-test]
|
|
[frontend-tests.svg-fills-test]
|
|
[frontend-tests.tokens.import-export-test]
|
|
[frontend-tests.tokens.logic.token-actions-test]
|
|
[frontend-tests.tokens.logic.token-data-test]
|
|
[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.util-object-test]
|
|
[frontend-tests.util-range-tree-test]
|
|
[frontend-tests.util-simple-math-test]
|
|
[frontend-tests.worker-snap-test]))
|
|
|
|
(enable-console-print!)
|
|
|
|
(defmethod cljs.test/report [:cljs.test/default :end-run-tests] [m]
|
|
(if (cljs.test/successful? m)
|
|
(.exit js/process 0)
|
|
(.exit js/process 1)))
|
|
|
|
(defn init
|
|
[]
|
|
(t/run-tests
|
|
'frontend-tests.basic-shapes-test
|
|
'frontend-tests.data.repo-test
|
|
'frontend-tests.data.workspace-colors-test
|
|
'frontend-tests.helpers-shapes-test
|
|
'frontend-tests.logic.comp-remove-swap-slots-test
|
|
'frontend-tests.logic.components-and-tokens
|
|
'frontend-tests.logic.copying-and-duplicating-test
|
|
'frontend-tests.logic.frame-guides-test
|
|
'frontend-tests.logic.groups-test
|
|
'frontend-tests.logic.pasting-in-containers-test
|
|
'frontend-tests.plugins.context-shapes-test
|
|
'frontend-tests.svg-fills-test
|
|
'frontend-tests.tokens.import-export-test
|
|
'frontend-tests.tokens.logic.token-actions-test
|
|
'frontend-tests.tokens.logic.token-data-test
|
|
'frontend-tests.tokens.logic.token-remapping-test
|
|
'frontend-tests.tokens.style-dictionary-test
|
|
'frontend-tests.tokens.token-errors-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))
|