From 732162e720ef0aba4672da4fd656cdc2864444ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Barrag=C3=A1n=20Merino?= Date: Tue, 11 Aug 2026 19:02:13 +0200 Subject: [PATCH 1/4] :wrench: Report flaky e2e tests in integration workflow Enable Playwright's JSON reporter alongside `list` and publish a summary of flaky tests to the job step summary. The JSON report is kept as an artifact for 30 days so flakiness rates can be aggregated over time. CI already runs with `retries: 2`, so unstable tests have been passing silently on retry. This only surfaces what the suite already absorbs; no test behaviour changes. The reporter in `frontend/scripts/test-e2e` becomes overridable via `PLAYWRIGHT_REPORTER` so the local developer default stays untouched. --- .github/workflows/tests-integration.yml | 31 +++++++++++++++++++++++++ frontend/scripts/test-e2e | 3 ++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests-integration.yml b/.github/workflows/tests-integration.yml index b028676aa7..61e9c6932e 100644 --- a/.github/workflows/tests-integration.yml +++ b/.github/workflows/tests-integration.yml @@ -80,9 +80,40 @@ jobs: - name: Run Tests working-directory: ./frontend + env: + PLAYWRIGHT_REPORTER: list,json + PLAYWRIGHT_JSON_OUTPUT_NAME: report.json run: | ./scripts/test-e2e + - name: Flaky summary + if: always() + working-directory: ./frontend + run: | + if [ ! -f report.json ]; then + echo "No report.json produced (the run failed early)." >> "$GITHUB_STEP_SUMMARY" + exit 0 + fi + + jq -r ' + [ .. | objects + | select(has("tests") and has("file")) + | select(any(.tests[]; .status == "flaky")) + | "- `\(.file):\(.line)` — \(.title)" + ] as $f + | "## Flaky tests: \($f | length)\n" + + (if ($f | length) == 0 then "_none_" else ($f | join("\n")) end) + ' report.json >> "$GITHUB_STEP_SUMMARY" + + - name: Upload JSON report + uses: actions/upload-artifact@v7 + if: always() + with: + name: integration-json-report + path: frontend/report.json + overwrite: true + retention-days: 30 + - name: Upload test result uses: actions/upload-artifact@v7 if: always() diff --git a/frontend/scripts/test-e2e b/frontend/scripts/test-e2e index fca7cf941e..f4511b53e7 100755 --- a/frontend/scripts/test-e2e +++ b/frontend/scripts/test-e2e @@ -1,8 +1,9 @@ #!/usr/bin/env bash SCRIPT_DIR=$(dirname $0); +REPORTER=${PLAYWRIGHT_REPORTER:-list}; set -ex $SCRIPT_DIR/setup; -pnpm run test:e2e -x --workers=1 --reporter=list "$@"; +pnpm run test:e2e -x --workers=1 --reporter="$REPORTER" "$@"; From e5c80edbf301ea580028f4142dc7247ed2820690 Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Wed, 12 Aug 2026 13:20:07 +0200 Subject: [PATCH 2/4] :bug: Fix libraries grid layout (#11226) --- frontend/src/app/main/ui/dashboard/grid.cljs | 3 ++- frontend/src/app/main/ui/dashboard/grid.scss | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/main/ui/dashboard/grid.cljs b/frontend/src/app/main/ui/dashboard/grid.cljs index 0b19614858..59442337f8 100644 --- a/frontend/src/app/main/ui/dashboard/grid.cljs +++ b/frontend/src/app/main/ui/dashboard/grid.cljs @@ -480,7 +480,8 @@ [:li {:class (stl/css-case :grid-item true :project-thumbnail true :library-item library-view?)} - [:div {:class (stl/css-case :is-selected selected?) + [:div {:class (stl/css-case :is-selected selected? + :grid-item-button true) :ref node-ref :role "button" :title (:name file) diff --git a/frontend/src/app/main/ui/dashboard/grid.scss b/frontend/src/app/main/ui/dashboard/grid.scss index 448600c835..97291f6002 100644 --- a/frontend/src/app/main/ui/dashboard/grid.scss +++ b/frontend/src/app/main/ui/dashboard/grid.scss @@ -180,6 +180,12 @@ $thumbnail-default-height: px2rem(168); } } +.grid-item-button { + inline-size: 100%; + block-size: 100%; + padding: 0 px2rem(6); +} + .project-thumbnail-actions { align-items: center; display: flex; @@ -328,7 +334,7 @@ $thumbnail-default-height: px2rem(168); // ─── LIBRARY ─────────────────────────────────── .library-thumbnail { - border-radius: $br-4; + border-radius: $br-8; position: relative; overflow: hidden; background-color: var(--color-background-tertiary); From 986ee60cad3703ec549a2e2139c7635d019beba2 Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Wed, 12 Aug 2026 13:20:21 +0200 Subject: [PATCH 3/4] :bug: Fix invitation loop (#11223) --- frontend/src/app/main/ui/dashboard/team.cljs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/frontend/src/app/main/ui/dashboard/team.cljs b/frontend/src/app/main/ui/dashboard/team.cljs index 2baaf90d12..d9f8071981 100644 --- a/frontend/src/app/main/ui/dashboard/team.cljs +++ b/frontend/src/app/main/ui/dashboard/team.cljs @@ -19,6 +19,7 @@ [app.main.data.team :as dtm] [app.main.refs :as refs] [app.main.repo :as rp] + [app.main.router :as rt] [app.main.store :as st] [app.main.ui.alert] [app.main.ui.components.dropdown :refer [dropdown]] @@ -87,6 +88,7 @@ route (mf/deref refs/route) invite-email (-> route :query-params :invite-email) + team-id (:id team) members-section? (= section :dashboard-team-members) settings-section? (= section :dashboard-team-settings) @@ -101,15 +103,20 @@ on-invite-member (mf/use-fn - (mf/deps team invite-email) + (mf/deps team-id invite-email) (fn [] - (st/emit! (dtm/check-and-invite-members {:team-id (:id team) + (st/emit! (dtm/check-and-invite-members {:team-id team-id :origin :team :invite-email invite-email}))))] - (mf/with-effect [team invite-email] - (when invite-email - (on-invite-member))) + ;; Depend on `team-id` (stable) rather than `team` (a map whose + ;; reference changes on every teams/members fetch) and clear + ;; `invite-email` from the URL once consumed, so this can't + ;; keep re-triggering `check-and-invite-members` in a loop. + (mf/with-effect [team-id invite-email] + (when (and team-id invite-email) + (on-invite-member) + (st/emit! (rt/nav (get-in route [:data :name]) {:team-id team-id} {::rt/replace true})))) [:header {:class (stl/css :dashboard-header :team) :data-testid "dashboard-header"} [:div {:class (stl/css :dashboard-title)} From fee416d27526d78015e8a8a2d3590449e28e694d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bel=C3=A9n=20Albeza?= Date: Wed, 12 Aug 2026 15:10:23 +0200 Subject: [PATCH 4/4] :bug: Fix crash after changing typography options (v2 and v3) (#11221) --- frontend/src/app/render_wasm/text_editor.cljs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/render_wasm/text_editor.cljs b/frontend/src/app/render_wasm/text_editor.cljs index 9686889dab..b577861f62 100644 --- a/frontend/src/app/render_wasm/text_editor.cljs +++ b/frontend/src/app/render_wasm/text_editor.cljs @@ -345,10 +345,15 @@ :text-direction (sr/untranslate-text-direction (text-editor-get-style-property text-direction-state text-direction-value)) :text-decoration (sr/untranslate-text-decoration (text-editor-get-style-property text-decoration-state text-decoration-value)) :text-transform (sr/untranslate-text-transform (text-editor-get-style-property text-transform-state text-transform-value)) - :line-height (text-editor-get-style-property line-height-state line-height-value) - :letter-spacing (text-editor-get-style-property letter-spacing-state letter-spacing-value) - :font-size (text-editor-get-style-property font-size-state font-size-value) - :font-weight (text-editor-get-style-property font-weight-state font-weight-value) + ;; WASM reports size/weight as numbers, but the rest of Penpot (and the backend schema) expects strings. + :line-height (let [height (text-editor-get-style-property line-height-state line-height-value)] + (if (= height :multiple) height (str height))) + :letter-spacing (let [spacing (text-editor-get-style-property letter-spacing-state letter-spacing-value)] + (if (= spacing :multiple) spacing (str spacing))) + :font-size (let [size (text-editor-get-style-property font-size-state font-size-value)] + (if (= size :multiple) size (str size))) + :font-weight (let [weight (text-editor-get-style-property font-weight-state font-weight-value)] + (if (= weight :multiple) weight (str weight))) :font-style font-style-value :font-family (text-editor-get-style-property font-family-id-state font-id) :font-id (text-editor-get-style-property font-family-id-state font-id)