mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-12 10:45:19 +00:00
Merge pull request #227 from zitadel/acceptance-test-suite
test(acceptance): username password
This commit is contained in:
52
.github/workflows/test.yml
vendored
52
.github/workflows/test.yml
vendored
@@ -4,6 +4,10 @@ on: pull_request
|
||||
|
||||
jobs:
|
||||
quality:
|
||||
env:
|
||||
ZITADEL_IMAGE: ghcr.io/zitadel/zitadel:v2.63.4
|
||||
POSTGRES_IMAGE: postgres:17.0-alpine3.19
|
||||
|
||||
name: Ensure Quality
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
@@ -21,6 +25,7 @@ jobs:
|
||||
- lint
|
||||
- test:unit
|
||||
- test:integration
|
||||
- test:acceptance
|
||||
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
@@ -37,12 +42,6 @@ jobs:
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.0.0
|
||||
|
||||
- uses: pnpm/action-setup@v4.0.0
|
||||
name: Install pnpm
|
||||
id: pnpm-install
|
||||
with:
|
||||
run_install: false
|
||||
|
||||
- name: Get pnpm store directory
|
||||
id: pnpm-cache
|
||||
shell: bash
|
||||
@@ -57,17 +56,52 @@ jobs:
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pnpm-store-
|
||||
|
||||
- name: Install Dependencies
|
||||
run: CYPRESS_INSTALL_BINARY=0 pnpm install
|
||||
|
||||
- run: echo "CYPRESS_VERSION=$(pnpm list -r | grep cypress | cut -d ' ' -f 2)" >> $GITHUB_ENV
|
||||
if: ${{ matrix.command == 'test:integration' }}
|
||||
|
||||
- uses: actions/cache@v4.0.2
|
||||
name: Setup Cypress binary cache
|
||||
with:
|
||||
path: ~/.cache/Cypress
|
||||
key: ${{ runner.os }}-cypress-binary-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
key: ${{ runner.os }}-cypress-binary-${{ env.CYPRESS_VERSION }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cypress-binary-
|
||||
if: ${{ matrix.command }} == "test:integration"
|
||||
if: ${{ matrix.command == 'test:integration' }}
|
||||
|
||||
- name: Install Dependencies
|
||||
- name: Install Cypress Browsers
|
||||
run: pnpm install
|
||||
if: ${{ matrix.command == 'test:integration' }}
|
||||
|
||||
- run: echo "PLAYWRIGHT_VERSION=$(npx playwright --version | cut -d ' ' -f 2)" >> $GITHUB_ENV
|
||||
if: ${{ matrix.command == 'test:acceptance' }}
|
||||
|
||||
- uses: actions/cache@v4.0.2
|
||||
name: Setup Playwright binary cache
|
||||
with:
|
||||
path: ~/.cache/ms-playwright
|
||||
key: ${{ runner.os }}-playwright-binary-${{ env.PLAYWRIGHT_VERSION }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-playwright-binary-
|
||||
if: ${{ matrix.command == 'test:acceptance' }}
|
||||
|
||||
- name: Install Playwright Browsers
|
||||
run: pnpm exec playwright install --with-deps
|
||||
if: ${{ matrix.command == 'test:acceptance' }}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
if: ${{ matrix.command == 'test:acceptance' }}
|
||||
|
||||
- name: Run ZITADEL
|
||||
run: ZITADEL_DEV_UID=root pnpm run-zitadel
|
||||
if: ${{ matrix.command == 'test:acceptance' }}
|
||||
|
||||
- name: Install Playwright Browsers
|
||||
run: pnpm build
|
||||
if: ${{ matrix.command == 'test:acceptance' }}
|
||||
|
||||
- name: Check
|
||||
id: check
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -18,3 +18,7 @@ packages/zitadel-server/src/app/proto
|
||||
.idea
|
||||
.vercel
|
||||
.env*.local
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
/blob-report/
|
||||
/playwright/.cache/
|
||||
|
||||
53
README.md
53
README.md
@@ -178,32 +178,57 @@ To run the application make sure to install the dependencies with
|
||||
pnpm install
|
||||
```
|
||||
|
||||
then setup the environment for the login application which needs a `.env.local` in `/apps/login`.
|
||||
Go to your instance and create a service user for the application having the `IAM_OWNER` manager role.
|
||||
This user is required to have access to create users on your primary organization and reading policy data so it can be
|
||||
restricted to your personal use case but we'll stick with `IAM_OWNER` for convenience. Create a PAT and copy the value to
|
||||
paste it under the `ZITADEL_SERVICE_USER_TOKEN` key.
|
||||
The file should look as follows:
|
||||
|
||||
```
|
||||
ZITADEL_API_URL=[yourinstanceurl]
|
||||
ZITADEL_ORG_ID=[yourprimaryorg]
|
||||
ZITADEL_SERVICE_USER_TOKEN=[yourserviceuserpersonalaccesstoken]
|
||||
```
|
||||
|
||||
then generate the GRPC stubs with
|
||||
|
||||
```sh
|
||||
pnpm generate
|
||||
```
|
||||
|
||||
and then run it with
|
||||
To run the application against a local ZITADEL instance, run the following command:
|
||||
|
||||
```sh
|
||||
pnpm run-zitadel
|
||||
```
|
||||
|
||||
This sets up ZITADEL using docker compose and writes the configuration to the file `apps/login/.env.local`.
|
||||
|
||||
<details>
|
||||
<summary>Alternatively, use another environment</summary>
|
||||
You can develop against any ZITADEL instance in which you have sufficient rights to execute the following steps.
|
||||
Just create or overwrite the file `apps/login/.env.local` yourself.
|
||||
Add your instances base URL to the file at the key `ZITADEL_API_URL`.
|
||||
Go to your instance and create a service user for the login application.
|
||||
The login application creates users on your primary organization and reads policy data.
|
||||
For the sake of simplicity, just make the service user an instance member with the role `IAM_OWNER`.
|
||||
Create a PAT and copy it to the file `apps/login/.env.local` using the key `ZITADEL_SERVICE_USER_TOKEN`.
|
||||
Also add the users ID to the file using the key `ZITADEL_SERVICE_USER_ID`.
|
||||
|
||||
The file should look similar to this:
|
||||
|
||||
```
|
||||
ZITADEL_API_URL=https://zitadel-tlx3du.us1.zitadel.cloud
|
||||
ZITADEL_SERVICE_USER_ID=289106423158521850
|
||||
ZITADEL_SERVICE_USER_TOKEN=1S6w48thfWFI2klgfwkCnhXJLf9FQ457E-_3H74ePQxfO3Af0Tm4V5Xi-ji7urIl_xbn-Rk
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
Start the login application in dev mode:
|
||||
|
||||
```sh
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
Open the login application with your favorite browser at `localhost:3000`.
|
||||
Change the source code and see the changes live in your browser.
|
||||
|
||||
Make sure the application still behaves as expected by running all tests
|
||||
|
||||
```sh
|
||||
pnpm test
|
||||
```
|
||||
|
||||
To satisfy your unique workflow requirements, check out the package.json in the root directory for more detailed scripts.
|
||||
|
||||
### Deploy to Vercel
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
FROM golang:1.19-alpine
|
||||
RUN apk add curl jq
|
||||
RUN go install github.com/zitadel/zitadel-tools@v0.4.0
|
||||
COPY setup.sh /setup.sh
|
||||
RUN chmod +x /setup.sh
|
||||
ENTRYPOINT [ "/setup.sh" ]
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
zitadel:
|
||||
user: "${ZITADEL_DEV_UID}"
|
||||
@@ -8,24 +6,29 @@ services:
|
||||
ports:
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- ./machinekey:/machinekey
|
||||
- ./pat:/pat
|
||||
- ./zitadel.yaml:/zitadel.yaml
|
||||
depends_on:
|
||||
db:
|
||||
condition: "service_healthy"
|
||||
|
||||
db:
|
||||
image: "cockroachdb/cockroach:v22.2.2"
|
||||
command: "start-single-node --insecure --http-addr :9090"
|
||||
restart: 'always'
|
||||
image: "${POSTGRES_IMAGE:-postgres:latest}"
|
||||
environment:
|
||||
- POSTGRES_USER=zitadel
|
||||
- PGUSER=zitadel
|
||||
- POSTGRES_DB=zitadel
|
||||
- POSTGRES_HOST_AUTH_METHOD=trust
|
||||
command: postgres -c shared_preload_libraries=pg_stat_statements -c pg_stat_statements.track=all -c shared_buffers=1GB -c work_mem=16MB -c effective_io_concurrency=100 -c wal_level=minimal -c archive_mode=off -c max_wal_senders=0
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:9090/health?ready=1"]
|
||||
interval: "10s"
|
||||
timeout: "30s"
|
||||
test: ["CMD-SHELL", "pg_isready"]
|
||||
interval: '10s'
|
||||
timeout: '30s'
|
||||
retries: 5
|
||||
start_period: "20s"
|
||||
start_period: '20s'
|
||||
ports:
|
||||
- "26257:26257"
|
||||
- "9090:9090"
|
||||
- 5432:5432
|
||||
|
||||
wait_for_zitadel:
|
||||
image: curlimages/curl:8.00.1
|
||||
@@ -33,7 +36,7 @@ services:
|
||||
[
|
||||
"/bin/sh",
|
||||
"-c",
|
||||
"i=0; while ! curl http://zitadel:8080/debug/ready && [ $$i -lt 30 ]; do sleep 1; i=$$((i+1)); done; [ $$i -eq 30 ] && exit 1 || exit 0",
|
||||
"i=0; while ! curl http://zitadel:8080/debug/ready && [ $$i -lt 30 ]; do sleep 1; i=$$((i+1)); done; [ $$i -eq 120 ] && exit 1 || exit 0",
|
||||
]
|
||||
depends_on:
|
||||
- zitadel
|
||||
@@ -43,11 +46,11 @@ services:
|
||||
container_name: setup
|
||||
build: .
|
||||
environment:
|
||||
KEY: /key/zitadel-admin-sa.json
|
||||
SERVICE: http://zitadel:8080
|
||||
WRITE_ENVIRONMENT_FILE: /apps/login/.env.acceptance
|
||||
PAT_FILE: /pat/zitadel-admin-sa.pat
|
||||
ZITADEL_API_INTERNAL_URL: http://zitadel:8080
|
||||
WRITE_ENVIRONMENT_FILE: /apps/login/.env.local
|
||||
volumes:
|
||||
- "./machinekey:/key"
|
||||
- "./pat:/pat"
|
||||
- "../apps/login:/apps/login"
|
||||
depends_on:
|
||||
wait_for_zitadel:
|
||||
|
||||
1
acceptance/machinekey/.gitignore
vendored
1
acceptance/machinekey/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
zitadel-admin-sa.json
|
||||
2
acceptance/pat/.gitignore
vendored
Normal file
2
acceptance/pat/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitkeep
|
||||
@@ -1,125 +1,34 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
set -ex
|
||||
|
||||
KEY=${KEY:-./machinekey/zitadel-admin-sa.json}
|
||||
echo "Using key path ${KEY} to the instance admin service account."
|
||||
PAT_FILE=${PAT_FILE:-./pat/zitadel-admin-sa.pat}
|
||||
ZITADEL_API_PROTOCOL="${ZITADEL_API_PROTOCOL:-http}"
|
||||
ZITADEL_API_DOMAIN="${ZITADEL_API_DOMAIN:-localhost}"
|
||||
ZITADEL_API_PORT="${ZITADEL_API_PORT:-8080}"
|
||||
ZITADEL_API_URL="${ZITADEL_API_URL:-${ZITADEL_API_PROTOCOL}://${ZITADEL_API_DOMAIN}:${ZITADEL_API_PORT}}"
|
||||
ZITADEL_API_INTERNAL_URL="${ZITADEL_API_INTERNAL_URL:-${ZITADEL_API_URL}}"
|
||||
|
||||
AUDIENCE=${AUDIENCE:-http://localhost:8080}
|
||||
echo "Using audience ${AUDIENCE} for which the key is used."
|
||||
if [ -z "${PAT}" ]; then
|
||||
echo "Reading PAT from file ${PAT_FILE}"
|
||||
PAT=$(cat ${PAT_FILE})
|
||||
fi
|
||||
|
||||
SERVICE=${SERVICE:-$AUDIENCE}
|
||||
echo "Using the service ${SERVICE} to connect to ZITADEL. For example in docker compose this can differ from the audience."
|
||||
if [ -z "${ZITADEL_SERVICE_USER_ID}" ]; then
|
||||
echo "Reading ZITADEL_SERVICE_USER_ID from userinfo endpoint"
|
||||
USERINFO_RESPONSE=$(curl -s --request POST \
|
||||
--url "${ZITADEL_API_INTERNAL_URL}/oidc/v1/userinfo" \
|
||||
--header "Authorization: Bearer ${PAT}" \
|
||||
--header "Host: ${ZITADEL_API_DOMAIN}")
|
||||
echo "Received userinfo response: ${USERINFO_RESPONSE}"
|
||||
ZITADEL_SERVICE_USER_ID=$(echo "${USERINFO_RESPONSE}" | jq --raw-output '.sub')
|
||||
fi
|
||||
|
||||
WRITE_ENVIRONMENT_FILE=${WRITE_ENVIRONMENT_FILE:-$(dirname "$0")/../apps/login/.env.acceptance}
|
||||
WRITE_ENVIRONMENT_FILE=${WRITE_ENVIRONMENT_FILE:-$(dirname "$0")/../apps/login/.env.local}
|
||||
echo "Writing environment file to ${WRITE_ENVIRONMENT_FILE} when done."
|
||||
|
||||
AUDIENCE_HOST="$(echo $AUDIENCE | cut -d/ -f3)"
|
||||
echo "Deferred the Host header ${AUDIENCE_HOST} which will be sent in requests that ZITADEL then maps to a virtual instance"
|
||||
|
||||
JWT=$(zitadel-tools key2jwt --key ${KEY} --audience ${AUDIENCE})
|
||||
echo "Created JWT from Admin service account key ${JWT}"
|
||||
|
||||
TOKEN_RESPONSE=$(curl -s --request POST \
|
||||
--url ${SERVICE}/oauth/v2/token \
|
||||
--header 'Content-Type: application/x-www-form-urlencoded' \
|
||||
--header "Host: ${AUDIENCE_HOST}" \
|
||||
--data grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer \
|
||||
--data scope='openid profile email urn:zitadel:iam:org:project:id:zitadel:aud' \
|
||||
--data assertion="${JWT}")
|
||||
echo "Got response from token endpoint:"
|
||||
echo "${TOKEN_RESPONSE}" | jq
|
||||
|
||||
TOKEN=$(echo -n ${TOKEN_RESPONSE} | jq --raw-output '.access_token')
|
||||
echo "Extracted access token ${TOKEN}"
|
||||
|
||||
ORG_RESPONSE=$(curl -s --request GET \
|
||||
--url ${SERVICE}/admin/v1/orgs/default \
|
||||
--header 'Accept: application/json' \
|
||||
--header "Authorization: Bearer ${TOKEN}" \
|
||||
--header "Host: ${AUDIENCE_HOST}")
|
||||
echo "Got default org response:"
|
||||
echo "${ORG_RESPONSE}" | jq
|
||||
|
||||
ORG_ID=$(echo -n ${ORG_RESPONSE} | jq --raw-output '.org.id')
|
||||
echo "Extracted default org id ${ORG_ID}"
|
||||
|
||||
echo "ZITADEL_API_URL=${AUDIENCE}
|
||||
ZITADEL_ORG_ID=${ORG_ID}
|
||||
ZITADEL_SERVICE_USER_TOKEN=${TOKEN}" > ${WRITE_ENVIRONMENT_FILE}
|
||||
echo "ZITADEL_API_URL=${ZITADEL_API_URL}
|
||||
ZITADEL_SERVICE_USER_ID=${ZITADEL_SERVICE_USER_ID}
|
||||
ZITADEL_SERVICE_USER_TOKEN=${PAT}" > ${WRITE_ENVIRONMENT_FILE}
|
||||
echo "Wrote environment file ${WRITE_ENVIRONMENT_FILE}"
|
||||
cat ${WRITE_ENVIRONMENT_FILE}
|
||||
|
||||
if ! grep -q 'localhost' ${WRITE_ENVIRONMENT_FILE}; then
|
||||
echo "Not developing against localhost, so creating a human user might not be necessary"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
HUMAN_USER_USERNAME="zitadel-admin@zitadel.localhost"
|
||||
HUMAN_USER_PASSWORD="Password1!"
|
||||
|
||||
HUMAN_USER_PAYLOAD=$(cat << EOM
|
||||
{
|
||||
"userName": "${HUMAN_USER_USERNAME}",
|
||||
"profile": {
|
||||
"firstName": "ZITADEL",
|
||||
"lastName": "Admin",
|
||||
"displayName": "ZITADEL Admin",
|
||||
"preferredLanguage": "en"
|
||||
},
|
||||
"email": {
|
||||
"email": "zitadel-admin@zitadel.localhost",
|
||||
"isEmailVerified": true
|
||||
},
|
||||
"password": "${HUMAN_USER_PASSWORD}",
|
||||
"passwordChangeRequired": false
|
||||
}
|
||||
EOM
|
||||
)
|
||||
echo "Creating human user"
|
||||
echo "${HUMAN_USER_PAYLOAD}" | jq
|
||||
|
||||
HUMAN_USER_RESPONSE=$(curl -s --request POST \
|
||||
--url ${SERVICE}/management/v1/users/human/_import \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Accept: application/json' \
|
||||
--header "Authorization: Bearer ${TOKEN}" \
|
||||
--header "Host: ${AUDIENCE_HOST}" \
|
||||
--data-raw "${HUMAN_USER_PAYLOAD}")
|
||||
echo "Create human user response"
|
||||
echo "${HUMAN_USER_RESPONSE}" | jq
|
||||
|
||||
if [ "$(echo -n "${HUMAN_USER_RESPONSE}" | jq --raw-output '.code')" == "6" ]; then
|
||||
echo "admin user already exists"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
HUMAN_USER_ID=$(echo -n ${HUMAN_USER_RESPONSE} | jq --raw-output '.userId')
|
||||
echo "Extracted human user id ${HUMAN_USER_ID}"
|
||||
|
||||
HUMAN_ADMIN_PAYLOAD=$(cat << EOM
|
||||
{
|
||||
"userId": "${HUMAN_USER_ID}",
|
||||
"roles": [
|
||||
"IAM_OWNER"
|
||||
]
|
||||
}
|
||||
EOM
|
||||
)
|
||||
echo "Granting iam owner to human user"
|
||||
echo "${HUMAN_ADMIN_PAYLOAD}" | jq
|
||||
|
||||
HUMAN_ADMIN_RESPONSE=$(curl -s --request POST \
|
||||
--url ${SERVICE}/admin/v1/members \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Accept: application/json' \
|
||||
--header "Authorization: Bearer ${TOKEN}" \
|
||||
--header "Host: ${AUDIENCE_HOST}" \
|
||||
--data-raw "${HUMAN_ADMIN_PAYLOAD}")
|
||||
|
||||
echo "Grant iam owner to human user response"
|
||||
echo "${HUMAN_ADMIN_RESPONSE}" | jq
|
||||
|
||||
echo "You can now log in at ${AUDIENCE}/ui/login"
|
||||
echo "username: ${HUMAN_USER_USERNAME}"
|
||||
echo "password: ${HUMAN_USER_PASSWORD}"
|
||||
12
acceptance/tests/username-password.spec.ts
Normal file
12
acceptance/tests/username-password.spec.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { test } from "@playwright/test";
|
||||
|
||||
test("username and password", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
const loginname = page.getByLabel("Loginname");
|
||||
await loginname.pressSequentially("zitadel-admin@zitadel.localhost");
|
||||
await loginname.press("Enter");
|
||||
const password = page.getByLabel("Password");
|
||||
await password.pressSequentially("Password1!");
|
||||
await password.press("Enter");
|
||||
await page.getByRole("heading", { name: "Welcome ZITADEL Admin!" }).click();
|
||||
});
|
||||
6
acceptance/tests/welcome.ts
Normal file
6
acceptance/tests/welcome.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { test } from "@playwright/test";
|
||||
|
||||
test("login is accessible", async ({ page }) => {
|
||||
await page.goto("http://localhost:3000/");
|
||||
await page.getByRole("heading", { name: "Welcome back!" }).isVisible();
|
||||
});
|
||||
@@ -1,22 +1,41 @@
|
||||
FirstInstance:
|
||||
MachineKeyPath: /machinekey/zitadel-admin-sa.json
|
||||
PatPath: /pat/zitadel-admin-sa.pat
|
||||
Org:
|
||||
Human:
|
||||
UserName: zitadel-admin
|
||||
FirstName: ZITADEL
|
||||
LastName: Admin
|
||||
Password: Password1!
|
||||
PasswordChangeRequired: false
|
||||
PreferredLanguage: en
|
||||
Machine:
|
||||
Machine:
|
||||
Username: zitadel-admin-sa
|
||||
Name: Admin
|
||||
MachineKey:
|
||||
Type: 1
|
||||
Pat:
|
||||
ExpirationDate: 2099-01-01T00:00:00Z
|
||||
|
||||
Database:
|
||||
Cockroach:
|
||||
EventPushConnRatio: 0.2 # 4
|
||||
ProjectionSpoolerConnRatio: 0.3 # 6
|
||||
postgres:
|
||||
Host: db
|
||||
Port: 5432
|
||||
Database: zitadel
|
||||
MaxOpenConns: 20
|
||||
MaxIdleConns: 20
|
||||
MaxConnLifetime: 1h
|
||||
MaxConnIdleTime: 5m
|
||||
User:
|
||||
Username: zitadel
|
||||
SSL:
|
||||
Mode: disable
|
||||
Admin:
|
||||
Username: zitadel
|
||||
SSL:
|
||||
Mode: disable
|
||||
|
||||
Logstore:
|
||||
Access:
|
||||
Stdout:
|
||||
Enabled: true
|
||||
|
||||
DefaultInstance:
|
||||
LoginPolicy:
|
||||
MfaInitSkipLifetime: 0h
|
||||
@@ -24,6 +24,7 @@
|
||||
"build": "next build",
|
||||
"prestart": "pnpm build",
|
||||
"start": "next start",
|
||||
"start:built": "next start",
|
||||
"clean": "pnpm mock:destroy && rm -rf .turbo && rm -rf node_modules && rm -rf .next"
|
||||
},
|
||||
"git": {
|
||||
|
||||
11
package.json
11
package.json
@@ -6,17 +6,22 @@
|
||||
"generate": "turbo run generate",
|
||||
"build": "turbo run build",
|
||||
"test": "turbo run test",
|
||||
"start": "turbo run start",
|
||||
"start:built": "turbo run start:built",
|
||||
"test:unit": "turbo run test:unit -- --passWithNoTests",
|
||||
"test:integration": "turbo run test:integration",
|
||||
"test:acceptance": "pnpm exec playwright test",
|
||||
"test:watch": "turbo run test:watch",
|
||||
"dev": "turbo run dev --no-cache --continue",
|
||||
"lint": "turbo run lint",
|
||||
"lint:fix": "turbo run lint:fix",
|
||||
"clean": "turbo run clean && rm -rf node_modules",
|
||||
"format:fix": "prettier --write \"**/*.{ts,tsx,md}\"",
|
||||
"format": "prettier --check \"**/*.{ts,tsx,md}\"",
|
||||
"changeset": "changeset",
|
||||
"version-packages": "changeset version",
|
||||
"release": "turbo run build --filter=login^... && changeset publish"
|
||||
"release": "turbo run build --filter=login^... && changeset publish",
|
||||
"run-zitadel": "docker compose -f ./acceptance/docker-compose.yaml run setup"
|
||||
},
|
||||
"pnpm": {
|
||||
"overrides": {
|
||||
@@ -25,10 +30,12 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@changesets/cli": "^2.27.8",
|
||||
"@playwright/test": "^1.48.1",
|
||||
"@types/node": "^22.7.5",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
"@zitadel/prettier-config": "workspace:*",
|
||||
"eslint": "8.57.1",
|
||||
"eslint-config-zitadel": "workspace:*",
|
||||
"@zitadel/prettier-config": "workspace:*",
|
||||
"prettier": "^3.2.5",
|
||||
"prettier-plugin-organize-imports": "^4.0.0",
|
||||
"tsup": "^8.3.0",
|
||||
|
||||
81
playwright.config.ts
Normal file
81
playwright.config.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { defineConfig, devices } from "@playwright/test";
|
||||
|
||||
/**
|
||||
* Read environment variables from file.
|
||||
* https://github.com/motdotla/dotenv
|
||||
*/
|
||||
// import dotenv from 'dotenv';
|
||||
// import path from 'path';
|
||||
// dotenv.config({ path: path.resolve(__dirname, '.env') });
|
||||
|
||||
/**
|
||||
* See https://playwright.dev/docs/test-configuration.
|
||||
*/
|
||||
export default defineConfig({
|
||||
testDir: "./acceptance/tests",
|
||||
/* Run tests in files in parallel */
|
||||
fullyParallel: true,
|
||||
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||
forbidOnly: !!process.env.CI,
|
||||
/* Retry on CI only */
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
/* Opt out of parallel tests on CI. */
|
||||
workers: process.env.CI ? 1 : undefined,
|
||||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||
reporter: "html",
|
||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||
use: {
|
||||
/* Base URL to use in actions like `await page.goto('/')`. */
|
||||
baseURL: "http://127.0.0.1:3000",
|
||||
|
||||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||
trace: "on-first-retry",
|
||||
},
|
||||
|
||||
/* Configure projects for major browsers */
|
||||
projects: [
|
||||
{
|
||||
name: "chromium",
|
||||
use: { ...devices["Desktop Chrome"] },
|
||||
},
|
||||
|
||||
{
|
||||
name: "firefox",
|
||||
use: { ...devices["Desktop Firefox"] },
|
||||
},
|
||||
/* TODO: webkit fails. Is this a bug?
|
||||
{
|
||||
name: 'webkit',
|
||||
use: { ...devices['Desktop Safari'] },
|
||||
},
|
||||
*/
|
||||
|
||||
/* Test against mobile viewports. */
|
||||
// {
|
||||
// name: 'Mobile Chrome',
|
||||
// use: { ...devices['Pixel 5'] },
|
||||
// },
|
||||
// {
|
||||
// name: 'Mobile Safari',
|
||||
// use: { ...devices['iPhone 12'] },
|
||||
// },
|
||||
|
||||
/* Test against branded browsers. */
|
||||
// {
|
||||
// name: 'Microsoft Edge',
|
||||
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
|
||||
// },
|
||||
// {
|
||||
// name: 'Google Chrome',
|
||||
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
|
||||
// },
|
||||
],
|
||||
|
||||
/* Run local dev server before starting the tests */
|
||||
webServer: {
|
||||
command: "pnpm start:built",
|
||||
url: "http://127.0.0.1:3000",
|
||||
reuseExistingServer: !process.env.CI,
|
||||
timeout: 5 * 60_000,
|
||||
},
|
||||
});
|
||||
111
pnpm-lock.yaml
generated
111
pnpm-lock.yaml
generated
@@ -14,9 +14,15 @@ importers:
|
||||
'@changesets/cli':
|
||||
specifier: ^2.27.8
|
||||
version: 2.27.8
|
||||
'@playwright/test':
|
||||
specifier: ^1.48.1
|
||||
version: 1.48.1
|
||||
'@types/node':
|
||||
specifier: ^22.7.5
|
||||
version: 22.7.6
|
||||
'@vitejs/plugin-react':
|
||||
specifier: ^4.2.1
|
||||
version: 4.3.1(vite@5.4.6(@types/node@22.5.5)(sass@1.79.1))
|
||||
version: 4.3.1(vite@5.4.6(@types/node@22.7.6)(sass@1.79.1))
|
||||
'@zitadel/prettier-config':
|
||||
specifier: workspace:*
|
||||
version: link:packages/zitadel-prettier-config
|
||||
@@ -43,10 +49,10 @@ importers:
|
||||
version: 5.6.2
|
||||
vite-tsconfig-paths:
|
||||
specifier: ^5.0.1
|
||||
version: 5.0.1(typescript@5.6.2)(vite@5.4.6(@types/node@22.5.5)(sass@1.79.1))
|
||||
version: 5.0.1(typescript@5.6.2)(vite@5.4.6(@types/node@22.7.6)(sass@1.79.1))
|
||||
vitest:
|
||||
specifier: ^2.1.1
|
||||
version: 2.1.1(@types/node@22.5.5)(jsdom@25.0.0)(sass@1.79.1)
|
||||
version: 2.1.1(@types/node@22.7.6)(jsdom@25.0.0)(sass@1.79.1)
|
||||
|
||||
apps/login:
|
||||
dependencies:
|
||||
@@ -61,7 +67,7 @@ importers:
|
||||
version: 0.5.7(tailwindcss@3.4.13)
|
||||
'@vercel/analytics':
|
||||
specifier: ^1.2.2
|
||||
version: 1.3.1(next@14.2.14(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.1))(react@18.3.1)
|
||||
version: 1.3.1(next@14.2.14(@babel/core@7.25.2)(@playwright/test@1.48.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.1))(react@18.3.1)
|
||||
'@zitadel/client':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/zitadel-client
|
||||
@@ -85,13 +91,13 @@ importers:
|
||||
version: 2.30.1
|
||||
next:
|
||||
specifier: 14.2.14
|
||||
version: 14.2.14(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.1)
|
||||
version: 14.2.14(@babel/core@7.25.2)(@playwright/test@1.48.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.1)
|
||||
next-intl:
|
||||
specifier: ^3.20.0
|
||||
version: 3.20.0(next@14.2.14(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.1))(react@18.3.1)
|
||||
version: 3.20.0(next@14.2.14(@babel/core@7.25.2)(@playwright/test@1.48.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.1))(react@18.3.1)
|
||||
next-themes:
|
||||
specifier: ^0.2.1
|
||||
version: 0.2.1(next@14.2.14(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
version: 0.2.1(next@14.2.14(@babel/core@7.25.2)(@playwright/test@1.48.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
nice-grpc:
|
||||
specifier: 2.0.1
|
||||
version: 2.0.1
|
||||
@@ -1050,6 +1056,11 @@ packages:
|
||||
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==, tarball: https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
'@playwright/test@1.48.1':
|
||||
resolution: {integrity: sha512-s9RtWoxkOLmRJdw3oFvhFbs9OJS0BzrLUc8Hf6l2UdCNd1rqeEyD4BhCJkvzeEoD1FsK4mirsWwGerhVmYKtZg==}
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
'@protobufjs/aspromise@1.1.2':
|
||||
resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==}
|
||||
|
||||
@@ -1284,6 +1295,9 @@ packages:
|
||||
'@types/node@22.5.5':
|
||||
resolution: {integrity: sha512-Xjs4y5UPO/CLdzpgR6GirZJx36yScjh73+2NlLlkFRSoQN8B0DpfXPdZGnvVmLRLOsqDpOfTNv7D9trgGhmOIA==}
|
||||
|
||||
'@types/node@22.7.6':
|
||||
resolution: {integrity: sha512-/d7Rnj0/ExXDMcioS78/kf1lMzYk4BZV8MZGTBKzTGZ6/406ukkbYlIsZmMPhcR5KlkunDHQLrtAVmSq7r+mSw==}
|
||||
|
||||
'@types/normalize-package-data@2.4.4':
|
||||
resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==}
|
||||
|
||||
@@ -2420,6 +2434,11 @@ packages:
|
||||
fs.realpath@1.0.0:
|
||||
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
|
||||
|
||||
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==, tarball: https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz}
|
||||
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
||||
@@ -3490,6 +3509,16 @@ packages:
|
||||
resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
playwright-core@1.48.1:
|
||||
resolution: {integrity: sha512-Yw/t4VAFX/bBr1OzwCuOMZkY1Cnb4z/doAFSwf4huqAGWmf9eMNjmK7NiOljCdLmxeRYcGPPmcDgU0zOlzP0YA==}
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
playwright@1.48.1:
|
||||
resolution: {integrity: sha512-j8CiHW/V6HxmbntOfyB4+T/uk08tBy6ph0MpBXwuoofkSnLmlfdYNNkFTYD6ofzzlSqLA1fwH4vwvVFvJgLN0w==}
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
possible-typed-array-names@1.0.0:
|
||||
resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -5404,6 +5433,10 @@ snapshots:
|
||||
'@pkgjs/parseargs@0.11.0':
|
||||
optional: true
|
||||
|
||||
'@playwright/test@1.48.1':
|
||||
dependencies:
|
||||
playwright: 1.48.1
|
||||
|
||||
'@protobufjs/aspromise@1.1.2': {}
|
||||
|
||||
'@protobufjs/base64@1.1.2': {}
|
||||
@@ -5618,6 +5651,10 @@ snapshots:
|
||||
dependencies:
|
||||
undici-types: 6.19.8
|
||||
|
||||
'@types/node@22.7.6':
|
||||
dependencies:
|
||||
undici-types: 6.19.8
|
||||
|
||||
'@types/normalize-package-data@2.4.4': {}
|
||||
|
||||
'@types/prop-types@15.7.12': {}
|
||||
@@ -5643,7 +5680,7 @@ snapshots:
|
||||
|
||||
'@types/yauzl@2.10.3':
|
||||
dependencies:
|
||||
'@types/node': 22.5.5
|
||||
'@types/node': 22.7.6
|
||||
optional: true
|
||||
|
||||
'@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.2)':
|
||||
@@ -5688,23 +5725,23 @@ snapshots:
|
||||
|
||||
'@ungap/structured-clone@1.2.0': {}
|
||||
|
||||
'@vercel/analytics@1.3.1(next@14.2.14(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.1))(react@18.3.1)':
|
||||
'@vercel/analytics@1.3.1(next@14.2.14(@babel/core@7.25.2)(@playwright/test@1.48.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
server-only: 0.0.1
|
||||
optionalDependencies:
|
||||
next: 14.2.14(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.1)
|
||||
next: 14.2.14(@babel/core@7.25.2)(@playwright/test@1.48.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.1)
|
||||
react: 18.3.1
|
||||
|
||||
'@vercel/git-hooks@1.0.0': {}
|
||||
|
||||
'@vitejs/plugin-react@4.3.1(vite@5.4.6(@types/node@22.5.5)(sass@1.79.1))':
|
||||
'@vitejs/plugin-react@4.3.1(vite@5.4.6(@types/node@22.7.6)(sass@1.79.1))':
|
||||
dependencies:
|
||||
'@babel/core': 7.25.2
|
||||
'@babel/plugin-transform-react-jsx-self': 7.24.7(@babel/core@7.25.2)
|
||||
'@babel/plugin-transform-react-jsx-source': 7.24.7(@babel/core@7.25.2)
|
||||
'@types/babel__core': 7.20.5
|
||||
react-refresh: 0.14.2
|
||||
vite: 5.4.6(@types/node@22.5.5)(sass@1.79.1)
|
||||
vite: 5.4.6(@types/node@22.7.6)(sass@1.79.1)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -5715,13 +5752,13 @@ snapshots:
|
||||
chai: 5.1.1
|
||||
tinyrainbow: 1.2.0
|
||||
|
||||
'@vitest/mocker@2.1.1(@vitest/spy@2.1.1)(vite@5.4.6(@types/node@22.5.5)(sass@1.79.1))':
|
||||
'@vitest/mocker@2.1.1(@vitest/spy@2.1.1)(vite@5.4.6(@types/node@22.7.6)(sass@1.79.1))':
|
||||
dependencies:
|
||||
'@vitest/spy': 2.1.1
|
||||
estree-walker: 3.0.3
|
||||
magic-string: 0.30.11
|
||||
optionalDependencies:
|
||||
vite: 5.4.6(@types/node@22.5.5)(sass@1.79.1)
|
||||
vite: 5.4.6(@types/node@22.7.6)(sass@1.79.1)
|
||||
|
||||
'@vitest/pretty-format@2.1.1':
|
||||
dependencies:
|
||||
@@ -7038,6 +7075,9 @@ snapshots:
|
||||
|
||||
fs.realpath@1.0.0: {}
|
||||
|
||||
fsevents@2.3.2:
|
||||
optional: true
|
||||
|
||||
fsevents@2.3.3:
|
||||
optional: true
|
||||
|
||||
@@ -7823,21 +7863,21 @@ snapshots:
|
||||
|
||||
negotiator@0.6.3: {}
|
||||
|
||||
next-intl@3.20.0(next@14.2.14(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.1))(react@18.3.1):
|
||||
next-intl@3.20.0(next@14.2.14(@babel/core@7.25.2)(@playwright/test@1.48.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.1))(react@18.3.1):
|
||||
dependencies:
|
||||
'@formatjs/intl-localematcher': 0.5.4
|
||||
negotiator: 0.6.3
|
||||
next: 14.2.14(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.1)
|
||||
next: 14.2.14(@babel/core@7.25.2)(@playwright/test@1.48.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.1)
|
||||
react: 18.3.1
|
||||
use-intl: 3.20.0(react@18.3.1)
|
||||
|
||||
next-themes@0.2.1(next@14.2.14(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||
next-themes@0.2.1(next@14.2.14(@babel/core@7.25.2)(@playwright/test@1.48.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||
dependencies:
|
||||
next: 14.2.14(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.1)
|
||||
next: 14.2.14(@babel/core@7.25.2)(@playwright/test@1.48.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.1)
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
|
||||
next@14.2.14(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.1):
|
||||
next@14.2.14(@babel/core@7.25.2)(@playwright/test@1.48.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.1):
|
||||
dependencies:
|
||||
'@next/env': 14.2.14
|
||||
'@swc/helpers': 0.5.5
|
||||
@@ -7858,6 +7898,7 @@ snapshots:
|
||||
'@next/swc-win32-arm64-msvc': 14.2.14
|
||||
'@next/swc-win32-ia32-msvc': 14.2.14
|
||||
'@next/swc-win32-x64-msvc': 14.2.14
|
||||
'@playwright/test': 1.48.1
|
||||
sass: 1.79.1
|
||||
transitivePeerDependencies:
|
||||
- '@babel/core'
|
||||
@@ -8096,6 +8137,14 @@ snapshots:
|
||||
|
||||
pirates@4.0.6: {}
|
||||
|
||||
playwright-core@1.48.1: {}
|
||||
|
||||
playwright@1.48.1:
|
||||
dependencies:
|
||||
playwright-core: 1.48.1
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.2
|
||||
|
||||
possible-typed-array-names@1.0.0: {}
|
||||
|
||||
postcss-import@15.1.0(postcss@8.4.47):
|
||||
@@ -8194,7 +8243,7 @@ snapshots:
|
||||
'@protobufjs/path': 1.1.2
|
||||
'@protobufjs/pool': 1.1.0
|
||||
'@protobufjs/utf8': 1.1.0
|
||||
'@types/node': 22.5.5
|
||||
'@types/node': 22.7.6
|
||||
long: 5.2.3
|
||||
|
||||
proxy-from-env@1.0.0: {}
|
||||
@@ -9048,12 +9097,12 @@ snapshots:
|
||||
core-util-is: 1.0.2
|
||||
extsprintf: 1.3.0
|
||||
|
||||
vite-node@2.1.1(@types/node@22.5.5)(sass@1.79.1):
|
||||
vite-node@2.1.1(@types/node@22.7.6)(sass@1.79.1):
|
||||
dependencies:
|
||||
cac: 6.7.14
|
||||
debug: 4.3.7(supports-color@5.5.0)
|
||||
pathe: 1.1.2
|
||||
vite: 5.4.6(@types/node@22.5.5)(sass@1.79.1)
|
||||
vite: 5.4.6(@types/node@22.7.6)(sass@1.79.1)
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- less
|
||||
@@ -9065,31 +9114,31 @@ snapshots:
|
||||
- supports-color
|
||||
- terser
|
||||
|
||||
vite-tsconfig-paths@5.0.1(typescript@5.6.2)(vite@5.4.6(@types/node@22.5.5)(sass@1.79.1)):
|
||||
vite-tsconfig-paths@5.0.1(typescript@5.6.2)(vite@5.4.6(@types/node@22.7.6)(sass@1.79.1)):
|
||||
dependencies:
|
||||
debug: 4.3.6
|
||||
globrex: 0.1.2
|
||||
tsconfck: 3.1.1(typescript@5.6.2)
|
||||
optionalDependencies:
|
||||
vite: 5.4.6(@types/node@22.5.5)(sass@1.79.1)
|
||||
vite: 5.4.6(@types/node@22.7.6)(sass@1.79.1)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
- typescript
|
||||
|
||||
vite@5.4.6(@types/node@22.5.5)(sass@1.79.1):
|
||||
vite@5.4.6(@types/node@22.7.6)(sass@1.79.1):
|
||||
dependencies:
|
||||
esbuild: 0.21.5
|
||||
postcss: 8.4.47
|
||||
rollup: 4.21.3
|
||||
optionalDependencies:
|
||||
'@types/node': 22.5.5
|
||||
'@types/node': 22.7.6
|
||||
fsevents: 2.3.3
|
||||
sass: 1.79.1
|
||||
|
||||
vitest@2.1.1(@types/node@22.5.5)(jsdom@25.0.0)(sass@1.79.1):
|
||||
vitest@2.1.1(@types/node@22.7.6)(jsdom@25.0.0)(sass@1.79.1):
|
||||
dependencies:
|
||||
'@vitest/expect': 2.1.1
|
||||
'@vitest/mocker': 2.1.1(@vitest/spy@2.1.1)(vite@5.4.6(@types/node@22.5.5)(sass@1.79.1))
|
||||
'@vitest/mocker': 2.1.1(@vitest/spy@2.1.1)(vite@5.4.6(@types/node@22.7.6)(sass@1.79.1))
|
||||
'@vitest/pretty-format': 2.1.1
|
||||
'@vitest/runner': 2.1.1
|
||||
'@vitest/snapshot': 2.1.1
|
||||
@@ -9104,11 +9153,11 @@ snapshots:
|
||||
tinyexec: 0.3.0
|
||||
tinypool: 1.0.1
|
||||
tinyrainbow: 1.2.0
|
||||
vite: 5.4.6(@types/node@22.5.5)(sass@1.79.1)
|
||||
vite-node: 2.1.1(@types/node@22.5.5)(sass@1.79.1)
|
||||
vite: 5.4.6(@types/node@22.7.6)(sass@1.79.1)
|
||||
vite-node: 2.1.1(@types/node@22.7.6)(sass@1.79.1)
|
||||
why-is-node-running: 2.3.0
|
||||
optionalDependencies:
|
||||
'@types/node': 22.5.5
|
||||
'@types/node': 22.7.6
|
||||
jsdom: 25.0.0
|
||||
transitivePeerDependencies:
|
||||
- less
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
},
|
||||
"build": {},
|
||||
"test": {},
|
||||
"start": {},
|
||||
"start:built": {},
|
||||
"test:unit": {},
|
||||
"test:integration": {},
|
||||
"test:watch": {
|
||||
|
||||
Reference in New Issue
Block a user