ui: plan 01-27 done #1
@@ -0,0 +1,145 @@
|
||||
name: ui-release
|
||||
|
||||
# Tier 2 (release) workflow. Runs on tag push.
|
||||
#
|
||||
# Currently mirrors the Tier 1 step set. Visual regression baseline
|
||||
# checks and the macOS-runner iOS smoke job are landed in later phases
|
||||
# of ui/PLAN.md and live as commented sections at the end of this file
|
||||
# until those phases ship.
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go.work
|
||||
cache: true
|
||||
|
||||
- name: Run Go tests
|
||||
# client/ is the deprecated Fyne client; excluded from CI per
|
||||
# ui/PLAN.md §74. -count=1 disables Go's test cache so a green
|
||||
# run never depends on a previous runner's cached state. The
|
||||
# backend suite is run with -p 1 because most backend packages
|
||||
# spawn their own Postgres testcontainer, and parallel
|
||||
# Postgres bootstraps starve each other on a constrained
|
||||
# runner. pkg modules are listed one by one because ./pkg/...
|
||||
# does not recurse across the independent go.work modules
|
||||
# under pkg/.
|
||||
run: |
|
||||
go test -count=1 -p 1 ./backend/...
|
||||
go test -count=1 \
|
||||
./gateway/... \
|
||||
./game/... \
|
||||
./pkg/calc/... \
|
||||
./pkg/connector/... \
|
||||
./pkg/cronutil/... \
|
||||
./pkg/error/... \
|
||||
./pkg/geoip/... \
|
||||
./pkg/model/... \
|
||||
./pkg/postgres/... \
|
||||
./pkg/redisconn/... \
|
||||
./pkg/schema/... \
|
||||
./pkg/storage/... \
|
||||
./pkg/transcoder/... \
|
||||
./pkg/util/...
|
||||
|
||||
- name: Set up pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 11.0.7
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: pnpm
|
||||
cache-dependency-path: ui/pnpm-lock.yaml
|
||||
|
||||
- name: Install npm dependencies
|
||||
working-directory: ui
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Install Playwright browsers
|
||||
working-directory: ui/frontend
|
||||
run: pnpm exec playwright install --with-deps
|
||||
|
||||
- name: Run Vitest
|
||||
working-directory: ui/frontend
|
||||
run: pnpm test
|
||||
|
||||
- name: Run Playwright
|
||||
working-directory: ui/frontend
|
||||
run: pnpm exec playwright test
|
||||
|
||||
- name: Upload Playwright report on failure
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: playwright-report
|
||||
path: ui/frontend/playwright-report/
|
||||
retention-days: 14
|
||||
|
||||
- name: Upload Playwright traces on failure
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: playwright-traces
|
||||
path: ui/frontend/test-results/
|
||||
retention-days: 14
|
||||
|
||||
# visual-regression: enabled in Phase 33 of ui/PLAN.md, once the PWA
|
||||
# shell and service worker land and a snapshot baseline is committed
|
||||
# under ui/frontend/tests/__snapshots__/.
|
||||
#
|
||||
# visual-regression:
|
||||
# runs-on: ubuntu-latest
|
||||
# needs: test
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
# - uses: pnpm/action-setup@v4
|
||||
# with: { version: 11.0.7 }
|
||||
# - uses: actions/setup-node@v4
|
||||
# with:
|
||||
# node-version: 22
|
||||
# cache: pnpm
|
||||
# cache-dependency-path: ui/pnpm-lock.yaml
|
||||
# - working-directory: ui
|
||||
# run: pnpm install --frozen-lockfile
|
||||
# - working-directory: ui/frontend
|
||||
# run: pnpm exec playwright install --with-deps
|
||||
# - working-directory: ui/frontend
|
||||
# run: pnpm exec playwright test --grep @visual
|
||||
|
||||
# ios-smoke: enabled in Phase 32 of ui/PLAN.md, once the Capacitor
|
||||
# wrapper lands. Runs a Capacitor + Appium smoke against an iOS
|
||||
# simulator on a macOS runner.
|
||||
#
|
||||
# ios-smoke:
|
||||
# runs-on: macos-13
|
||||
# needs: test
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
# - uses: pnpm/action-setup@v4
|
||||
# with: { version: 11.0.7 }
|
||||
# - uses: actions/setup-node@v4
|
||||
# with:
|
||||
# node-version: 22
|
||||
# cache: pnpm
|
||||
# cache-dependency-path: ui/pnpm-lock.yaml
|
||||
# - working-directory: ui
|
||||
# run: pnpm install --frozen-lockfile
|
||||
# - working-directory: ui/mobile
|
||||
# run: pnpm exec cap sync ios && pnpm exec appium-smoke ios
|
||||
@@ -0,0 +1,119 @@
|
||||
name: ui-test
|
||||
|
||||
# Tier 1 (per-PR) workflow. Runs Vitest + Playwright for the UI client and
|
||||
# the monorepo Go service tests (everything except the integration suite,
|
||||
# which lives behind `make -C integration integration` and needs a Docker
|
||||
# daemon set up for testcontainers).
|
||||
#
|
||||
# The path filter is intentionally broad until a dedicated go-test
|
||||
# workflow is introduced; this is the only CI gate today.
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'ui/**'
|
||||
- 'backend/**'
|
||||
- 'gateway/**'
|
||||
- 'game/**'
|
||||
- 'pkg/**'
|
||||
- 'go.work'
|
||||
- 'go.work.sum'
|
||||
- '.gitea/workflows/ui-test.yaml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'ui/**'
|
||||
- 'backend/**'
|
||||
- 'gateway/**'
|
||||
- 'game/**'
|
||||
- 'pkg/**'
|
||||
- 'go.work'
|
||||
- 'go.work.sum'
|
||||
- '.gitea/workflows/ui-test.yaml'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go.work
|
||||
cache: true
|
||||
|
||||
- name: Run Go tests
|
||||
# client/ is the deprecated Fyne client; excluded from CI per
|
||||
# ui/PLAN.md §74. -count=1 disables Go's test cache so a green
|
||||
# run never depends on a previous runner's cached state. The
|
||||
# backend suite is run with -p 1 because most backend packages
|
||||
# spawn their own Postgres testcontainer, and parallel
|
||||
# Postgres bootstraps starve each other on a constrained
|
||||
# runner. pkg modules are listed one by one because ./pkg/...
|
||||
# does not recurse across the independent go.work modules
|
||||
# under pkg/.
|
||||
run: |
|
||||
go test -count=1 -p 1 ./backend/...
|
||||
go test -count=1 \
|
||||
./gateway/... \
|
||||
./game/... \
|
||||
./pkg/calc/... \
|
||||
./pkg/connector/... \
|
||||
./pkg/cronutil/... \
|
||||
./pkg/error/... \
|
||||
./pkg/geoip/... \
|
||||
./pkg/model/... \
|
||||
./pkg/postgres/... \
|
||||
./pkg/redisconn/... \
|
||||
./pkg/schema/... \
|
||||
./pkg/storage/... \
|
||||
./pkg/transcoder/... \
|
||||
./pkg/util/...
|
||||
|
||||
- name: Set up pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 11.0.7
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: pnpm
|
||||
cache-dependency-path: ui/pnpm-lock.yaml
|
||||
|
||||
- name: Install npm dependencies
|
||||
working-directory: ui
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Install Playwright browsers
|
||||
working-directory: ui/frontend
|
||||
run: pnpm exec playwright install --with-deps
|
||||
|
||||
- name: Run Vitest
|
||||
working-directory: ui/frontend
|
||||
run: pnpm test
|
||||
|
||||
- name: Run Playwright
|
||||
working-directory: ui/frontend
|
||||
run: pnpm exec playwright test
|
||||
|
||||
- name: Upload Playwright report on failure
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: playwright-report
|
||||
path: ui/frontend/playwright-report/
|
||||
retention-days: 14
|
||||
|
||||
- name: Upload Playwright traces on failure
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: playwright-traces
|
||||
path: ui/frontend/test-results/
|
||||
retention-days: 14
|
||||
@@ -0,0 +1 @@
|
||||
.env
|
||||
@@ -0,0 +1,42 @@
|
||||
.PHONY: help up down logs status clean push
|
||||
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
COMPOSE := docker compose
|
||||
GITEA_USER := galaxy
|
||||
GITEA_PASS := galaxy-dev
|
||||
REPO_NAME := galaxy
|
||||
REMOTE_NAME := local-gitea
|
||||
REPO_ROOT := $(realpath $(CURDIR)/../..)
|
||||
GIT := git -C $(REPO_ROOT)
|
||||
REMOTE_URL := http://$(GITEA_USER):$(GITEA_PASS)@localhost:3000/$(GITEA_USER)/$(REPO_NAME).git
|
||||
|
||||
help:
|
||||
@echo "Local Gitea CI for galaxy:"
|
||||
@echo " make up Bring up Gitea + runner (idempotent)"
|
||||
@echo " make down Stop both containers"
|
||||
@echo " make logs Tail logs"
|
||||
@echo " make status Show container status"
|
||||
@echo " make push Push current branch to local Gitea"
|
||||
@echo " make clean Stop and wipe all local state"
|
||||
|
||||
up:
|
||||
@./bootstrap.sh
|
||||
|
||||
down:
|
||||
$(COMPOSE) down
|
||||
|
||||
logs:
|
||||
$(COMPOSE) logs -f --tail=50
|
||||
|
||||
status:
|
||||
$(COMPOSE) ps
|
||||
|
||||
push:
|
||||
@$(GIT) remote get-url $(REMOTE_NAME) >/dev/null 2>&1 || \
|
||||
$(GIT) remote add $(REMOTE_NAME) $(REMOTE_URL)
|
||||
$(GIT) push $(REMOTE_NAME) HEAD
|
||||
|
||||
clean:
|
||||
$(COMPOSE) down -v
|
||||
rm -f .env
|
||||
@@ -0,0 +1,98 @@
|
||||
# Local Gitea CI
|
||||
|
||||
Self-contained Gitea + Actions runner for verifying
|
||||
`.gitea/workflows/*` honestly before pushing to a real Gitea instance.
|
||||
Runs natively on arm64 (Apple Silicon) — every image below has an
|
||||
arm64 variant, so Docker pulls the right architecture and the runner
|
||||
executes workflow steps without QEMU emulation.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker (Colima or Docker Desktop)
|
||||
- `python3`, `curl`, `bash` — all built into macOS
|
||||
|
||||
## First time
|
||||
|
||||
```sh
|
||||
make -C tools/local-ci up
|
||||
```
|
||||
|
||||
This:
|
||||
|
||||
1. brings up the Gitea container;
|
||||
2. creates an admin user (`galaxy` / `galaxy-dev`);
|
||||
3. creates the `galaxy/galaxy` repo;
|
||||
4. fetches a runner registration token from the Gitea API;
|
||||
5. brings up the runner with that token (the runner persists its
|
||||
credentials in a Docker volume and ignores the token on subsequent
|
||||
restarts).
|
||||
|
||||
The script is idempotent — re-running it is safe.
|
||||
|
||||
## Pushing a branch
|
||||
|
||||
```sh
|
||||
make -C tools/local-ci push
|
||||
```
|
||||
|
||||
This adds a `local-gitea` remote on the first run and then pushes the
|
||||
current `HEAD`. Equivalent manual flow:
|
||||
|
||||
```sh
|
||||
git remote add local-gitea \
|
||||
http://galaxy:galaxy-dev@localhost:3000/galaxy/galaxy.git
|
||||
git push local-gitea HEAD
|
||||
```
|
||||
|
||||
The Tier 1 workflow fires on `push` to any branch and the Tier 2
|
||||
workflow fires on tags matching `v*`. Watch runs at:
|
||||
|
||||
<http://localhost:3000/galaxy/galaxy/actions>
|
||||
|
||||
## Operational targets
|
||||
|
||||
| Target | What it does |
|
||||
| ---------------- | -------------------------------------------- |
|
||||
| `make up` | Bring up Gitea + runner (idempotent) |
|
||||
| `make down` | Stop both containers (state preserved) |
|
||||
| `make logs` | Tail logs from both containers |
|
||||
| `make status` | Show container status |
|
||||
| `make push` | Push current `HEAD` to local Gitea |
|
||||
| `make clean` | Stop and wipe all local state (full reset) |
|
||||
|
||||
## What's in the box
|
||||
|
||||
| Component | Image | Role |
|
||||
| ---------- | ---------------------------------- | ------------------------------------------- |
|
||||
| Gitea | `gitea/gitea:1.23` | Server with SQLite backend |
|
||||
| act_runner | `gitea/act_runner:0.6.1` | Single-capacity runner registered on boot |
|
||||
| Workflow | `catthehacker/ubuntu:act-latest` | Image spawned per job (multi-arch) |
|
||||
|
||||
The runner mounts the host Docker socket and spawns workflow
|
||||
containers on the same Docker network as Gitea, so
|
||||
`actions/checkout` reaches the server at `http://gitea:3000` from
|
||||
inside spawned containers.
|
||||
|
||||
## Caveats
|
||||
|
||||
- Gitea's `ROOT_URL` is set to `http://gitea:3000/` so spawned
|
||||
workflow containers reach the server through the compose network.
|
||||
The web UI works at `http://localhost:3000` via port mapping, but
|
||||
copy-paste URLs in the UI may show `gitea:3000` instead of
|
||||
`localhost:3000`. Harmless for local dev; switch the host part by
|
||||
hand when copying.
|
||||
- The runner is single-capacity (`runner.capacity: 1` in
|
||||
`config.yaml`). Concurrent jobs queue. Bump if you need parallel
|
||||
jobs.
|
||||
- First push from a fresh checkout uploads the full repo history
|
||||
(~tens of MB). Subsequent pushes are deltas.
|
||||
- `actions/upload-artifact@v4` requires Gitea ≥ 1.21 — we pin
|
||||
`1.23` to stay above the cutoff.
|
||||
- Workflow steps run as `root` inside the spawned container; this
|
||||
matches the upstream catthehacker behaviour. Keep that in mind if
|
||||
you add steps that touch host-mounted directories.
|
||||
- On Apple Silicon the runner image and its catthehacker child run
|
||||
natively as arm64. Some pre-built tools that ship in the image are
|
||||
amd64-only and would fall back to QEMU; `setup-go`, `setup-node`,
|
||||
and `pnpm/action-setup` all download arm64 binaries themselves, so
|
||||
the workflow steps we care about stay native.
|
||||
Executable
+86
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env bash
|
||||
# Bring up Gitea, create the admin user and the galaxy/galaxy repo,
|
||||
# fetch a runner registration token, bring up the runner.
|
||||
# Idempotent — re-runnable.
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
GITEA_USER=galaxy
|
||||
GITEA_PASS=galaxy-dev
|
||||
GITEA_EMAIL=galaxy@local
|
||||
REPO_NAME=galaxy
|
||||
GITEA_URL=http://localhost:3000
|
||||
|
||||
echo ">>> Bringing up Gitea..."
|
||||
docker compose up -d gitea
|
||||
|
||||
echo ">>> Waiting for Gitea API..."
|
||||
for _ in $(seq 1 120); do
|
||||
if curl -fsS "${GITEA_URL}/api/v1/version" >/dev/null 2>&1; then
|
||||
echo "Gitea is up."
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
if ! curl -fsS "${GITEA_URL}/api/v1/version" >/dev/null 2>&1; then
|
||||
echo "Gitea did not come up within 120 seconds." >&2
|
||||
docker compose logs gitea | tail -30 >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ">>> Creating admin user (idempotent)..."
|
||||
docker compose exec -T gitea su git -c "
|
||||
gitea admin user create \
|
||||
--username ${GITEA_USER} \
|
||||
--password ${GITEA_PASS} \
|
||||
--email ${GITEA_EMAIL} \
|
||||
--admin \
|
||||
--must-change-password=false 2>&1 || true
|
||||
"
|
||||
|
||||
echo ">>> Creating repo (idempotent)..."
|
||||
HTTP_CODE=$(curl -s -o /dev/null -w '%{http_code}' \
|
||||
-u "${GITEA_USER}:${GITEA_PASS}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"name\":\"${REPO_NAME}\",\"private\":true,\"auto_init\":false}" \
|
||||
"${GITEA_URL}/api/v1/user/repos")
|
||||
case "${HTTP_CODE}" in
|
||||
201) echo "Repo created." ;;
|
||||
409) echo "Repo already exists." ;;
|
||||
*)
|
||||
echo "Unexpected response (${HTTP_CODE}) creating repo." >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo ">>> Fetching runner registration token..."
|
||||
RUNNER_TOKEN=$(curl -fsS \
|
||||
-u "${GITEA_USER}:${GITEA_PASS}" \
|
||||
"${GITEA_URL}/api/v1/admin/runners/registration-token" \
|
||||
| python3 -c "import json, sys; print(json.load(sys.stdin)['token'])")
|
||||
|
||||
# act_runner uses RUNNER_TOKEN only on the first boot. After registration
|
||||
# it persists credentials in the named runner-data volume (/data/.runner)
|
||||
# and ignores the env token on subsequent restarts. Writing a fresh token
|
||||
# every time is harmless.
|
||||
echo "RUNNER_TOKEN=${RUNNER_TOKEN}" > .env
|
||||
|
||||
echo ">>> Bringing up runner..."
|
||||
docker compose up -d runner
|
||||
|
||||
cat <<EOF
|
||||
|
||||
Done.
|
||||
|
||||
Push the current branch and watch a run:
|
||||
|
||||
cd $(cd ../.. && pwd)
|
||||
git remote add local-gitea http://${GITEA_USER}:${GITEA_PASS}@localhost:3000/${GITEA_USER}/${REPO_NAME}.git 2>/dev/null || true
|
||||
git push local-gitea HEAD
|
||||
|
||||
open http://localhost:3000/${GITEA_USER}/${REPO_NAME}/actions
|
||||
|
||||
Or use \`make push\` from this directory.
|
||||
EOF
|
||||
@@ -0,0 +1,35 @@
|
||||
# act_runner configuration.
|
||||
#
|
||||
# The `ubuntu-latest` label is mapped to catthehacker/ubuntu:act-latest,
|
||||
# which is multi-arch — Docker on Apple Silicon pulls the arm64 variant
|
||||
# and runs it natively (no QEMU). The same image is what `act` uses
|
||||
# locally, so workflows behave the same.
|
||||
|
||||
log:
|
||||
level: info
|
||||
|
||||
runner:
|
||||
file: /data/.runner
|
||||
capacity: 1
|
||||
fetch_timeout: 5s
|
||||
fetch_interval: 2s
|
||||
labels:
|
||||
- "ubuntu-latest:docker://catthehacker/ubuntu:act-latest"
|
||||
|
||||
cache:
|
||||
enabled: true
|
||||
dir: /data/cache
|
||||
|
||||
container:
|
||||
# Spawned workflow containers join the same network as Gitea so
|
||||
# actions/checkout and other steps can reach the server at
|
||||
# http://gitea:3000.
|
||||
network: galaxy-local-gitea-net
|
||||
privileged: false
|
||||
options: ""
|
||||
workdir_parent: ""
|
||||
valid_volumes: []
|
||||
force_pull: false
|
||||
|
||||
host:
|
||||
workdir_parent: ""
|
||||
@@ -0,0 +1,78 @@
|
||||
# Local Gitea + Actions runner for verifying .gitea/workflows/*.
|
||||
# Runs natively on arm64 (Apple Silicon) — every image below is multi-arch.
|
||||
#
|
||||
# Browser: http://localhost:3000
|
||||
# API: http://localhost:3000/api/v1
|
||||
# Push URL: http://galaxy:galaxy-dev@localhost:3000/galaxy/galaxy.git
|
||||
# Actions: http://localhost:3000/galaxy/galaxy/actions
|
||||
#
|
||||
# `bootstrap.sh` (or `make up`) brings everything up and registers the
|
||||
# runner. State persists in named Docker volumes; `make clean` wipes them.
|
||||
|
||||
services:
|
||||
gitea:
|
||||
image: gitea/gitea:1.23
|
||||
container_name: galaxy-local-gitea
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
USER_UID: "1000"
|
||||
USER_GID: "1000"
|
||||
GITEA__database__DB_TYPE: sqlite3
|
||||
GITEA__database__PATH: /data/gitea/gitea.db
|
||||
# ROOT_URL uses the in-network hostname so the runner and spawned
|
||||
# workflow containers reach Gitea through the compose network.
|
||||
# The browser still works at http://localhost:3000 via the port
|
||||
# mapping below; UI-generated copy URLs may show "gitea:3000",
|
||||
# which is harmless for local dev.
|
||||
GITEA__server__ROOT_URL: http://gitea:3000/
|
||||
GITEA__server__SSH_PORT: "2222"
|
||||
GITEA__actions__ENABLED: "true"
|
||||
GITEA__security__INSTALL_LOCK: "true"
|
||||
GITEA__service__DISABLE_REGISTRATION: "true"
|
||||
ports:
|
||||
- "3000:3000"
|
||||
- "2222:22"
|
||||
volumes:
|
||||
- gitea-data:/data
|
||||
networks:
|
||||
- gitea-net
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD-SHELL
|
||||
- wget -q -O- http://localhost:3000/api/v1/version >/dev/null || exit 1
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 30
|
||||
start_period: 5s
|
||||
|
||||
runner:
|
||||
image: gitea/act_runner:0.6.1
|
||||
container_name: galaxy-local-runner
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
gitea:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
CONFIG_FILE: /config/config.yaml
|
||||
GITEA_INSTANCE_URL: http://gitea:3000
|
||||
# Provided by bootstrap.sh in the .env file. After the first
|
||||
# successful registration, act_runner persists credentials in
|
||||
# /data/.runner and ignores this token on subsequent restarts.
|
||||
GITEA_RUNNER_REGISTRATION_TOKEN: ${RUNNER_TOKEN:-}
|
||||
GITEA_RUNNER_NAME: galaxy-local
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- runner-data:/data
|
||||
- ./config.yaml:/config/config.yaml:ro
|
||||
networks:
|
||||
- gitea-net
|
||||
|
||||
networks:
|
||||
gitea-net:
|
||||
name: galaxy-local-gitea-net
|
||||
|
||||
volumes:
|
||||
gitea-data:
|
||||
name: galaxy-local-gitea-data
|
||||
runner-data:
|
||||
name: galaxy-local-runner-data
|
||||
+39
-14
@@ -287,9 +287,9 @@ Targeted tests:
|
||||
- a single Vitest smoke test that mounts the landing component and
|
||||
asserts the rendered version string is non-empty.
|
||||
|
||||
## Phase 2. Testing Infrastructure
|
||||
## ~~Phase 2. Testing Infrastructure~~
|
||||
|
||||
Status: pending.
|
||||
Status: done.
|
||||
|
||||
Goal: install and configure the test toolchain that every later phase
|
||||
depends on, including Tier 1 (per-PR) and Tier 2 (release) targets.
|
||||
@@ -299,17 +299,37 @@ Artifacts:
|
||||
- `ui/frontend/package.json` dev-dependencies (added on top of the
|
||||
Phase 1 minimum of `vitest`, `jsdom`, `@testing-library/svelte`):
|
||||
`@testing-library/jest-dom`, `playwright`, `@playwright/test`
|
||||
- `ui/frontend/vitest.config.ts` extended for `@testing-library/jest-dom`
|
||||
matchers (the JSDOM environment itself is wired in Phase 1)
|
||||
- `ui/frontend/playwright.config.ts` with three projects:
|
||||
- `ui/frontend/vitest.config.ts` extended with `setupFiles:
|
||||
["./tests/setup.ts"]` to wire `@testing-library/jest-dom` matchers
|
||||
into Vitest (the JSDOM environment itself is wired in Phase 1)
|
||||
- `ui/frontend/tests/setup.ts` registering `jest-dom` matchers
|
||||
- `ui/frontend/tests/e2e/landing.spec.ts` placeholder Playwright test
|
||||
asserting the version footer renders
|
||||
- `ui/frontend/playwright.config.ts` with four projects:
|
||||
`chromium-desktop`, `webkit-desktop`, `chromium-mobile-iphone-13`,
|
||||
`chromium-mobile-pixel-5`; tracing and screenshots enabled on failure
|
||||
- `ui/.gitea/workflows/test.yaml` running Tier 1 on every push and PR
|
||||
on a Linux runner: `go test ./...`, `pnpm test`, `pnpm exec
|
||||
playwright install --with-deps`, `pnpm exec playwright test`
|
||||
- `ui/.gitea/workflows/release.yaml` running Tier 2 on tag push:
|
||||
visual regression baseline check, optional macOS runner block for
|
||||
iOS smoke (Phase 32+ only)
|
||||
`chromium-mobile-pixel-5`; tracing and screenshots enabled on
|
||||
failure; `webServer: pnpm run dev` on port 5173
|
||||
- `.gitea/workflows/ui-test.yaml` running Tier 1 on every push and PR
|
||||
on a Linux runner: monorepo Go service tests for `backend/`,
|
||||
`gateway/`, `game/`, and every `pkg/<name>/` module (each pkg
|
||||
module is enumerated explicitly because they sit as independent
|
||||
go.work modules under a shared `pkg/` directory, and `./pkg/...`
|
||||
does not recurse across module boundaries). All Go tests run with
|
||||
`-count=1` so the cache never masks a failing run; backend tests
|
||||
additionally run with `-p 1` because most backend packages spawn
|
||||
their own Postgres testcontainer and parallel bootstraps starve
|
||||
each other on the runner. The integration suite stays gated behind
|
||||
`make -C integration integration` and lives outside Tier 1; the
|
||||
deprecated `client/` Fyne client (see §74) is also excluded — its
|
||||
tests, code, and documentation are frozen and CI must not run
|
||||
them. Then `pnpm install --frozen-lockfile` from `ui/`,
|
||||
`pnpm exec playwright install --with-deps`, `pnpm test`,
|
||||
`pnpm exec playwright test`; Playwright reports and traces
|
||||
uploaded as artefacts on failure
|
||||
- `.gitea/workflows/ui-release.yaml` running Tier 2 on tag push (`v*`):
|
||||
same Tier 1 step set today; visual-regression and macOS-runner
|
||||
iOS-smoke jobs live as commented sections marked with the phase
|
||||
number that re-enables them (Phase 33 and Phase 32 respectively)
|
||||
- `ui/docs/testing.md` topic doc naming the two tiers, the tools
|
||||
per tier, and the rule that visual regression baselines live in
|
||||
`ui/frontend/tests/__snapshots__/` until shifted to Argos
|
||||
@@ -322,7 +342,9 @@ Acceptance criteria:
|
||||
- a placeholder Playwright test passes in `chromium-desktop` and
|
||||
`webkit-desktop` projects locally;
|
||||
- the Gitea Actions Tier 1 workflow runs end-to-end against a clean
|
||||
clone of the repo on a Linux runner.
|
||||
clone of the repo on a Linux runner. Until the Gitea runner is
|
||||
provisioned, the workflow is exercised locally with
|
||||
`act -W .gitea/workflows/ui-test.yaml`.
|
||||
|
||||
Targeted tests:
|
||||
|
||||
@@ -342,6 +364,9 @@ implementation. No network, no UI.
|
||||
Artifacts:
|
||||
|
||||
- `ui/core/go.mod` module declared in the project Go workspace
|
||||
- `.gitea/workflows/ui-test.yaml` and `.gitea/workflows/ui-release.yaml`
|
||||
extended to add `./ui/core/...` to the Tier 1 / Tier 2 `go test`
|
||||
command list introduced in Phase 2
|
||||
- `ui/core/canon/` canonical bytes for `galaxy-request-v1`,
|
||||
`galaxy-response-v1`, and `galaxy-event-v1`, matching
|
||||
`docs/ARCHITECTURE.md` §15 byte-for-byte
|
||||
@@ -1702,7 +1727,7 @@ Artifacts:
|
||||
follow-up issue to switch to self-hosted Argos
|
||||
- Appium harness for iOS Simulator and Android Emulator covering the
|
||||
login flow, push-event flow, and at least one full turn loop;
|
||||
`.gitea/workflows/release.yaml` extended with macOS-runner Appium
|
||||
`.gitea/workflows/ui-release.yaml` extended with macOS-runner Appium
|
||||
job (mandatory pre-release gate)
|
||||
|
||||
Dependencies: Phases 1 through 35.
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
# UI Testing Tiers
|
||||
|
||||
UI client test toolchain. Project-wide testing layers (service /
|
||||
inter-service / system) live in [`../../docs/TESTING.md`](../../docs/TESTING.md);
|
||||
this doc only covers the UI-specific tiers added in Phase 2 of
|
||||
[`../PLAN.md`](../PLAN.md).
|
||||
|
||||
## Tier 1 — per-PR
|
||||
|
||||
Triggered by `.gitea/workflows/ui-test.yaml` on every push and pull
|
||||
request that touches `ui/**`, `backend/**`, `gateway/**`, `game/**`,
|
||||
`pkg/**`, `client/**`, `go.work`, or `go.work.sum`. Linux runner only.
|
||||
|
||||
Runs:
|
||||
|
||||
- `go test` over the monorepo Go modules, excluding two areas:
|
||||
- `integration/` — needs Docker + testcontainers and is the
|
||||
project's `make -C integration integration` gate.
|
||||
- `client/` — the deprecated Fyne client (see `../PLAN.md` §74) is
|
||||
frozen; its tests are not run in CI.
|
||||
|
||||
The `pkg/<name>/` modules are listed one by one in the workflow
|
||||
because they are independent go.work modules and `./pkg/...` does
|
||||
not recurse into separate modules. The exact command lives in
|
||||
`.gitea/workflows/ui-test.yaml`.
|
||||
- `pnpm test` (Vitest + `@testing-library/svelte` +
|
||||
`@testing-library/jest-dom`) — component / unit tests under
|
||||
`ui/frontend/tests/**/*.test.ts`.
|
||||
- `pnpm exec playwright test` — end-to-end smoke against `pnpm run
|
||||
dev` on port 5173. Four projects:
|
||||
- `chromium-desktop` (Desktop Chrome)
|
||||
- `webkit-desktop` (Desktop Safari)
|
||||
- `chromium-mobile-iphone-13` (iPhone 13 viewport, Chromium engine)
|
||||
- `chromium-mobile-pixel-5` (Pixel 5 viewport, Chromium engine)
|
||||
|
||||
Playwright traces and screenshots are retained on failure and uploaded
|
||||
as Gitea Actions artefacts (`playwright-report` and `playwright-traces`,
|
||||
14-day retention).
|
||||
|
||||
## Tier 2 — release
|
||||
|
||||
Triggered by `.gitea/workflows/ui-release.yaml` on tag push (`v*`).
|
||||
Currently mirrors the Tier 1 step set; the dedicated release-only
|
||||
checks land in later phases:
|
||||
|
||||
- **Visual regression baseline check** — Phase 33. Snapshots live in
|
||||
`ui/frontend/tests/__snapshots__/` until the project shifts to
|
||||
Argos or another visual-diff service.
|
||||
- **iOS smoke (Capacitor + Appium)** — Phase 32. Runs on a `macos-13`
|
||||
runner once the Capacitor mobile wrapper exists.
|
||||
|
||||
Both blocks are present as commented sections in
|
||||
`.gitea/workflows/ui-release.yaml` with the phase number that
|
||||
re-enables them.
|
||||
|
||||
## Local execution
|
||||
|
||||
From `ui/frontend/`:
|
||||
|
||||
```sh
|
||||
pnpm test # Vitest
|
||||
pnpm exec playwright install # one-time
|
||||
pnpm exec playwright test # all projects
|
||||
pnpm exec playwright test --project=chromium-desktop
|
||||
pnpm exec playwright show-report # open last HTML report
|
||||
```
|
||||
|
||||
From the repository root, the same scope CI uses (backend serially
|
||||
because most packages spawn their own Postgres testcontainer and
|
||||
parallel bootstraps starve each other on constrained runners):
|
||||
|
||||
```sh
|
||||
go test -count=1 -p 1 ./backend/...
|
||||
go test -count=1 \
|
||||
./gateway/... ./game/... \
|
||||
./pkg/calc/... ./pkg/connector/... ./pkg/cronutil/... \
|
||||
./pkg/error/... ./pkg/geoip/... ./pkg/model/... \
|
||||
./pkg/postgres/... ./pkg/redisconn/... ./pkg/schema/... \
|
||||
./pkg/storage/... ./pkg/transcoder/... ./pkg/util/...
|
||||
```
|
||||
|
||||
## CI dry-run with `act`
|
||||
|
||||
Until the Gitea Actions runner is wired up, the workflow is exercised
|
||||
locally with [`act`](https://github.com/nektos/act):
|
||||
|
||||
```sh
|
||||
act -W .gitea/workflows/ui-test.yaml --container-architecture linux/amd64
|
||||
```
|
||||
|
||||
`act` reads the workflow as GitHub Actions; the format is
|
||||
intentionally compatible.
|
||||
@@ -8,15 +8,19 @@
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||
"test": "vitest run"
|
||||
"test": "vitest run",
|
||||
"test:e2e": "playwright test"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.59.1",
|
||||
"@sveltejs/adapter-static": "^3.0.0",
|
||||
"@sveltejs/kit": "^2.59.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^7.0.0",
|
||||
"@testing-library/jest-dom": "^6.9.1",
|
||||
"@testing-library/svelte": "^5.2.0",
|
||||
"@types/node": "^22.0.0",
|
||||
"jsdom": "^25.0.0",
|
||||
"playwright": "^1.59.1",
|
||||
"svelte": "^5.0.0",
|
||||
"svelte-check": "^4.0.0",
|
||||
"tslib": "^2.6.0",
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { defineConfig, devices } from "@playwright/test";
|
||||
|
||||
export default defineConfig({
|
||||
testDir: "tests/e2e",
|
||||
fullyParallel: true,
|
||||
forbidOnly: !!process.env.CI,
|
||||
retries: process.env.CI ? 1 : 0,
|
||||
reporter: [["list"], ["html", { open: "never" }]],
|
||||
use: {
|
||||
baseURL: "http://localhost:5173",
|
||||
trace: "retain-on-failure",
|
||||
screenshot: "only-on-failure",
|
||||
},
|
||||
projects: [
|
||||
{ name: "chromium-desktop", use: { ...devices["Desktop Chrome"] } },
|
||||
{ name: "webkit-desktop", use: { ...devices["Desktop Safari"] } },
|
||||
// devices["iPhone 13"] picks WebKit by default; the project name
|
||||
// here claims a Chromium engine on a mobile viewport, so the
|
||||
// browser is explicitly overridden. WebKit on a desktop viewport
|
||||
// is already covered by webkit-desktop.
|
||||
{
|
||||
name: "chromium-mobile-iphone-13",
|
||||
use: { ...devices["iPhone 13"], browserName: "chromium" },
|
||||
},
|
||||
{ name: "chromium-mobile-pixel-5", use: { ...devices["Pixel 5"] } },
|
||||
],
|
||||
webServer: {
|
||||
command: "pnpm run dev",
|
||||
url: "http://localhost:5173",
|
||||
reuseExistingServer: !process.env.CI,
|
||||
timeout: 120_000,
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test("landing page renders the version string", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
const footer = page.getByTestId("app-version");
|
||||
await expect(footer).toBeVisible();
|
||||
await expect(footer).toContainText(/version\s+\S+/);
|
||||
});
|
||||
@@ -6,6 +6,7 @@ describe("landing page", () => {
|
||||
it("renders a non-empty version string in the footer", () => {
|
||||
const { getByTestId } = render(Page);
|
||||
const footer = getByTestId("app-version");
|
||||
expect(footer).toBeInTheDocument();
|
||||
expect(footer.textContent?.trim()).not.toBe("");
|
||||
expect(footer.textContent).toMatch(/version\s+\S+/);
|
||||
});
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
import "@testing-library/jest-dom/vitest";
|
||||
@@ -12,6 +12,7 @@ export default mergeConfig(
|
||||
environment: "jsdom",
|
||||
include: ["tests/**/*.test.ts"],
|
||||
globals: true,
|
||||
setupFiles: ["./tests/setup.ts"],
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
Generated
+101
@@ -8,6 +8,9 @@ importers:
|
||||
|
||||
frontend:
|
||||
devDependencies:
|
||||
'@playwright/test':
|
||||
specifier: ^1.59.1
|
||||
version: 1.59.1
|
||||
'@sveltejs/adapter-static':
|
||||
specifier: ^3.0.0
|
||||
version: 3.0.10(@sveltejs/kit@2.59.1(@sveltejs/vite-plugin-svelte@7.1.1(svelte@5.55.5)(vite@8.0.10(@types/node@22.19.17)))(svelte@5.55.5)(typescript@5.9.3)(vite@8.0.10(@types/node@22.19.17)))
|
||||
@@ -17,6 +20,9 @@ importers:
|
||||
'@sveltejs/vite-plugin-svelte':
|
||||
specifier: ^7.0.0
|
||||
version: 7.1.1(svelte@5.55.5)(vite@8.0.10(@types/node@22.19.17))
|
||||
'@testing-library/jest-dom':
|
||||
specifier: ^6.9.1
|
||||
version: 6.9.1
|
||||
'@testing-library/svelte':
|
||||
specifier: ^5.2.0
|
||||
version: 5.3.1(svelte@5.55.5)(vite@8.0.10(@types/node@22.19.17))(vitest@4.1.5(@types/node@22.19.17)(jsdom@25.0.1)(vite@8.0.10(@types/node@22.19.17)))
|
||||
@@ -26,6 +32,9 @@ importers:
|
||||
jsdom:
|
||||
specifier: ^25.0.0
|
||||
version: 25.0.1
|
||||
playwright:
|
||||
specifier: ^1.59.1
|
||||
version: 1.59.1
|
||||
svelte:
|
||||
specifier: ^5.0.0
|
||||
version: 5.55.5
|
||||
@@ -47,6 +56,9 @@ importers:
|
||||
|
||||
packages:
|
||||
|
||||
'@adobe/css-tools@4.4.4':
|
||||
resolution: {integrity: sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==}
|
||||
|
||||
'@asamuzakjp/css-color@3.2.0':
|
||||
resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==}
|
||||
|
||||
@@ -124,6 +136,11 @@ packages:
|
||||
'@oxc-project/types@0.127.0':
|
||||
resolution: {integrity: sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ==}
|
||||
|
||||
'@playwright/test@1.59.1':
|
||||
resolution: {integrity: sha512-PG6q63nQg5c9rIi4/Z5lR5IVF7yU5MqmKaPOe0HSc0O2cX1fPi96sUQu5j7eo4gKCkB2AnNGoWt7y4/Xx3Kcqg==}
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
'@polka/url@1.0.0-next.29':
|
||||
resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==}
|
||||
|
||||
@@ -265,6 +282,10 @@ packages:
|
||||
resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@testing-library/jest-dom@6.9.1':
|
||||
resolution: {integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==}
|
||||
engines: {node: '>=14', npm: '>=6', yarn: '>=1'}
|
||||
|
||||
'@testing-library/svelte-core@1.0.0':
|
||||
resolution: {integrity: sha512-VkUePoLV6oOYwSUvX6ShA8KLnJqZiYMIbP2JW2t0GLWLkJxKGvuH5qrrZBV/X7cXFnLGuFQEC7RheYiZOW68KQ==}
|
||||
engines: {node: '>=16'}
|
||||
@@ -399,6 +420,9 @@ packages:
|
||||
resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
css.escape@1.5.1:
|
||||
resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==}
|
||||
|
||||
cssstyle@4.6.0:
|
||||
resolution: {integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -441,6 +465,9 @@ packages:
|
||||
dom-accessibility-api@0.5.16:
|
||||
resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==}
|
||||
|
||||
dom-accessibility-api@0.6.3:
|
||||
resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==}
|
||||
|
||||
dunder-proto@1.0.1:
|
||||
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -499,6 +526,11 @@ packages:
|
||||
resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
fsevents@2.3.2:
|
||||
resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
|
||||
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
||||
os: [darwin]
|
||||
|
||||
fsevents@2.3.3:
|
||||
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
|
||||
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
||||
@@ -547,6 +579,10 @@ packages:
|
||||
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
indent-string@4.0.0:
|
||||
resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
is-potential-custom-element-name@1.0.1:
|
||||
resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==}
|
||||
|
||||
@@ -668,6 +704,10 @@ packages:
|
||||
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
min-indent@1.0.1:
|
||||
resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
mri@1.2.0:
|
||||
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
|
||||
engines: {node: '>=4'}
|
||||
@@ -703,6 +743,16 @@ packages:
|
||||
resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
playwright-core@1.59.1:
|
||||
resolution: {integrity: sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==}
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
playwright@1.59.1:
|
||||
resolution: {integrity: sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==}
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
postcss@8.5.14:
|
||||
resolution: {integrity: sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
@@ -722,6 +772,10 @@ packages:
|
||||
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
|
||||
engines: {node: '>= 14.18.0'}
|
||||
|
||||
redent@3.0.0:
|
||||
resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
rolldown@1.0.0-rc.17:
|
||||
resolution: {integrity: sha512-ZrT53oAKrtA4+YtBWPQbtPOxIbVDbxT0orcYERKd63VJTF13zPcgXTvD4843L8pcsI7M6MErt8QtON6lrB9tyA==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
@@ -764,6 +818,10 @@ packages:
|
||||
std-env@4.1.0:
|
||||
resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==}
|
||||
|
||||
strip-indent@3.0.0:
|
||||
resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
svelte-check@4.4.8:
|
||||
resolution: {integrity: sha512-67adfgBox5eNSNIvIIwgFizKGdcRrGpiMoNO2obHcYuLz7iTa8Xgm/NGU3ntMFnNm8K1grFOIG6HhMLX/vcN8w==}
|
||||
engines: {node: '>= 18.0.0'}
|
||||
@@ -966,6 +1024,8 @@ packages:
|
||||
|
||||
snapshots:
|
||||
|
||||
'@adobe/css-tools@4.4.4': {}
|
||||
|
||||
'@asamuzakjp/css-color@3.2.0':
|
||||
dependencies:
|
||||
'@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
|
||||
@@ -1048,6 +1108,10 @@ snapshots:
|
||||
|
||||
'@oxc-project/types@0.127.0': {}
|
||||
|
||||
'@playwright/test@1.59.1':
|
||||
dependencies:
|
||||
playwright: 1.59.1
|
||||
|
||||
'@polka/url@1.0.0-next.29': {}
|
||||
|
||||
'@rolldown/binding-android-arm64@1.0.0-rc.17':
|
||||
@@ -1151,6 +1215,15 @@ snapshots:
|
||||
picocolors: 1.1.1
|
||||
pretty-format: 27.5.1
|
||||
|
||||
'@testing-library/jest-dom@6.9.1':
|
||||
dependencies:
|
||||
'@adobe/css-tools': 4.4.4
|
||||
aria-query: 5.3.1
|
||||
css.escape: 1.5.1
|
||||
dom-accessibility-api: 0.6.3
|
||||
picocolors: 1.1.1
|
||||
redent: 3.0.0
|
||||
|
||||
'@testing-library/svelte-core@1.0.0(svelte@5.55.5)':
|
||||
dependencies:
|
||||
svelte: 5.55.5
|
||||
@@ -1270,6 +1343,8 @@ snapshots:
|
||||
|
||||
cookie@0.6.0: {}
|
||||
|
||||
css.escape@1.5.1: {}
|
||||
|
||||
cssstyle@4.6.0:
|
||||
dependencies:
|
||||
'@asamuzakjp/css-color': 3.2.0
|
||||
@@ -1298,6 +1373,8 @@ snapshots:
|
||||
|
||||
dom-accessibility-api@0.5.16: {}
|
||||
|
||||
dom-accessibility-api@0.6.3: {}
|
||||
|
||||
dunder-proto@1.0.1:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.2
|
||||
@@ -1347,6 +1424,9 @@ snapshots:
|
||||
hasown: 2.0.3
|
||||
mime-types: 2.1.35
|
||||
|
||||
fsevents@2.3.2:
|
||||
optional: true
|
||||
|
||||
fsevents@2.3.3:
|
||||
optional: true
|
||||
|
||||
@@ -1404,6 +1484,8 @@ snapshots:
|
||||
dependencies:
|
||||
safer-buffer: 2.1.2
|
||||
|
||||
indent-string@4.0.0: {}
|
||||
|
||||
is-potential-custom-element-name@1.0.1: {}
|
||||
|
||||
is-reference@3.0.3:
|
||||
@@ -1509,6 +1591,8 @@ snapshots:
|
||||
dependencies:
|
||||
mime-db: 1.52.0
|
||||
|
||||
min-indent@1.0.1: {}
|
||||
|
||||
mri@1.2.0: {}
|
||||
|
||||
mrmime@2.0.1: {}
|
||||
@@ -1531,6 +1615,14 @@ snapshots:
|
||||
|
||||
picomatch@4.0.4: {}
|
||||
|
||||
playwright-core@1.59.1: {}
|
||||
|
||||
playwright@1.59.1:
|
||||
dependencies:
|
||||
playwright-core: 1.59.1
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.2
|
||||
|
||||
postcss@8.5.14:
|
||||
dependencies:
|
||||
nanoid: 3.3.12
|
||||
@@ -1549,6 +1641,11 @@ snapshots:
|
||||
|
||||
readdirp@4.1.2: {}
|
||||
|
||||
redent@3.0.0:
|
||||
dependencies:
|
||||
indent-string: 4.0.0
|
||||
strip-indent: 3.0.0
|
||||
|
||||
rolldown@1.0.0-rc.17:
|
||||
dependencies:
|
||||
'@oxc-project/types': 0.127.0
|
||||
@@ -1600,6 +1697,10 @@ snapshots:
|
||||
|
||||
std-env@4.1.0: {}
|
||||
|
||||
strip-indent@3.0.0:
|
||||
dependencies:
|
||||
min-indent: 1.0.1
|
||||
|
||||
svelte-check@4.4.8(picomatch@4.0.4)(svelte@5.55.5)(typescript@5.9.3):
|
||||
dependencies:
|
||||
'@jridgewell/trace-mapping': 0.3.31
|
||||
|
||||
Reference in New Issue
Block a user