mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 14:47:33 +00:00
chore: fix login integration (#10318)
# Which Problems Are Solved Login integration tests are not executed in the pipeline # How the Problems Are Solved The login integration tests are fixed and added as a pipeline workflow. It tests against the built login docker image. On pipeline failures, developers are guided on how to fix them using a dev container configured for this purpose. # Additional Changes - email domains are replaced by example.com. In case the tests were accidentally run against a cloud instance, it wouldn't cause bounces. - pnpm is upgraded, because the --filter argument doesn't work for the install command on the old version. - The login Dockerfile is optimized for docker image builds # Additional Changes From Review for https://github.com/zitadel/zitadel/pull/10305 These changes were requested from @peintnermax - The base dev container starts without any services besides the database and the dev container itself - CONTRIBUTING.md is restructured - To reproduce pipeline checks, only the devcontainer CLI and Docker are needed. This is described in the CONTRIBUTING.md - The convenience npm script "generate" is added # Additional Context - Follow-up for PR https://github.com/zitadel/zitadel/pull/10305 - Base for https://github.com/zitadel/zitadel/issues/10277
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
NEXT_PUBLIC_BASE_PATH="/ui/v2/login"
|
||||
ZITADEL_API_URL=http://mock-zitadel:22222
|
||||
ZITADEL_API_URL=http://localhost:22222
|
||||
ZITADEL_SERVICE_USER_TOKEN="yolo"
|
||||
EMAIL_VERIFICATION=true
|
||||
DEBUG=true
|
||||
PORT=3001
|
||||
NEXT_PUBLIC_BASE_PATH=/ui/v2/login
|
||||
|
2
apps/login/.gitignore
vendored
2
apps/login/.gitignore
vendored
@@ -2,6 +2,7 @@ custom-config.js
|
||||
.env*.local
|
||||
standalone
|
||||
tsconfig.tsbuildinfo
|
||||
cypress
|
||||
|
||||
.DS_Store
|
||||
node_modules
|
||||
@@ -11,6 +12,5 @@ node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
.env
|
||||
.vscode
|
||||
/blob-report/
|
||||
|
@@ -3,21 +3,21 @@ FROM node:20-alpine AS base
|
||||
FROM base AS build
|
||||
ENV PNPM_HOME="/pnpm"
|
||||
ENV PATH="$PNPM_HOME:$PATH"
|
||||
RUN corepack enable && COREPACK_ENABLE_DOWNLOAD_PROMPT=0 corepack prepare pnpm@9.1.2 --activate && \
|
||||
apk update && apk add --no-cache && \
|
||||
RUN corepack enable && COREPACK_ENABLE_DOWNLOAD_PROMPT=0 corepack prepare pnpm@10.13.1 --activate && \
|
||||
apk update && \
|
||||
rm -rf /var/cache/apk/*
|
||||
WORKDIR /app
|
||||
COPY pnpm-lock.yaml ./
|
||||
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm fetch --frozen-lockfile
|
||||
COPY package.json ./
|
||||
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm install --frozen-lockfile --prod
|
||||
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm install --frozen-lockfile
|
||||
COPY . .
|
||||
RUN pnpm build:login:standalone
|
||||
|
||||
FROM scratch AS build-out
|
||||
COPY --from=build /app/.next/standalone /
|
||||
COPY --from=build /app/.next/static /.next/static
|
||||
COPY --from=build /app/public /public
|
||||
COPY public public
|
||||
|
||||
FROM base AS login-standalone
|
||||
WORKDIR /runtime
|
||||
@@ -25,12 +25,13 @@ RUN addgroup --system --gid 1001 nodejs && \
|
||||
adduser --system --uid 1001 nextjs
|
||||
# If /.env-file/.env is mounted into the container, its variables are made available to the server before it starts up.
|
||||
RUN mkdir -p /.env-file && touch /.env-file/.env && chown -R nextjs:nodejs /.env-file
|
||||
COPY ./scripts/ ./
|
||||
COPY --chown=nextjs:nodejs ./scripts/ ./
|
||||
COPY --chown=nextjs:nodejs --from=build-out / ./
|
||||
USER nextjs
|
||||
ENV HOSTNAME="0.0.0.0"
|
||||
ENV PORT=3000
|
||||
ENV HOSTNAME="0.0.0.0" \
|
||||
NEXT_PUBLIC_BASE_PATH="/ui/v2/login" \
|
||||
PORT=3000
|
||||
# TODO: Check healthy, not ready
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||
CMD ["/bin/sh", "-c", "node ./healthcheck.js http://localhost:${PORT}/ui/v2/login/healthy"]
|
||||
ENTRYPOINT ["./entrypoint.sh"]
|
||||
CMD ["/bin/sh", "-c", "node /runtime/healthcheck.js http://localhost:${PORT}/ui/v2/login/healthy"]
|
||||
ENTRYPOINT ["/runtime/entrypoint.sh"]
|
||||
|
@@ -8,7 +8,8 @@
|
||||
!next.config.mjs
|
||||
!next-env-vars.d.ts
|
||||
!next-env.d.ts
|
||||
!tailwind.config.js
|
||||
!tailwind.config.mjs
|
||||
!postcss.config.cjs
|
||||
!tsconfig.json
|
||||
!package.json
|
||||
!pnpm-lock.yaml
|
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"name": "login-test-acceptance",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"test:acceptance": "dotenv -e ../login/.env.test.local playwright",
|
||||
"test:acceptance:setup": "cd ../.. && make login_test_acceptance_setup_env && NODE_ENV=test turbo run test:acceptance:setup:dev",
|
||||
"test:acceptance:setup:dev": "cd ../.. && make login_test_acceptance_setup_dev",
|
||||
"clean": "rm -rf .turbo node_modules"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@faker-js/faker": "^9.7.0",
|
||||
"@otplib/core": "^12.0.0",
|
||||
"@otplib/plugin-crypto": "^12.0.0",
|
||||
"@otplib/plugin-thirty-two": "^12.0.0",
|
||||
"@playwright/test": "^1.52.0",
|
||||
"dotenv-cli": "^8.0.0",
|
||||
"gaxios": "^7.1.0",
|
||||
"typescript": "^5.8.3"
|
||||
}
|
||||
}
|
@@ -2,11 +2,11 @@ import { defineConfig } from "cypress";
|
||||
|
||||
export default defineConfig({
|
||||
reporter: "list",
|
||||
|
||||
video: true,
|
||||
e2e: {
|
||||
baseUrl: process.env.LOGIN_BASE_URL || "http://localhost:3001/ui/v2/login",
|
||||
specPattern: "integration/**/*.cy.{js,jsx,ts,tsx}",
|
||||
supportFile: "support/e2e.{js,jsx,ts,tsx}",
|
||||
specPattern: "integration/integration/**/*.cy.{js,jsx,ts,tsx}",
|
||||
supportFile: "integration/support/e2e.{js,jsx,ts,tsx}",
|
||||
setupNodeEvents(on, config) {
|
||||
// implement node event listeners here
|
||||
},
|
@@ -1,8 +1,10 @@
|
||||
FROM bufbuild/buf:1.54.0 AS proto-files
|
||||
RUN buf export https://github.com/envoyproxy/protoc-gen-validate.git --path validate --output /proto-files && \
|
||||
buf export https://github.com/grpc-ecosystem/grpc-gateway.git --path protoc-gen-openapiv2 --output /proto-files && \
|
||||
buf export https://github.com/googleapis/googleapis.git --path protos/zitadelgoogle/api/annotations.proto --path google/api/http.proto --path google/api/field_behavior.proto --output /proto-files && \
|
||||
buf export https://github.com/zitadel/zitadel.git --path ./proto/zitadel --output /proto-files
|
||||
FROM bufbuild/buf:1.54.0 AS dependencies
|
||||
RUN buf export https://github.com/envoyproxy/protoc-gen-validate.git --path validate --output /proto && \
|
||||
buf export https://github.com/grpc-ecosystem/grpc-gateway.git --path protoc-gen-openapiv2 --output /proto && \
|
||||
buf export https://github.com/googleapis/googleapis.git --path google/api/annotations.proto --path google/api/http.proto --path google/api/field_behavior.proto --output /proto
|
||||
|
||||
FROM bufbuild/buf:1.54.0 AS zitadel-protos
|
||||
RUN buf export https://github.com/zitadel/zitadel.git --path ./proto/zitadel --output /zitadel
|
||||
|
||||
FROM golang:1.20.5-alpine3.18 AS mock-zitadel
|
||||
|
||||
@@ -10,6 +12,7 @@ RUN go install github.com/eliobischof/grpc-mock/cmd/grpc-mock@01b09f60db1b501178
|
||||
|
||||
COPY mocked-services.cfg .
|
||||
COPY initial-stubs initial-stubs
|
||||
COPY --from=proto-files /proto-files/ ./
|
||||
COPY --from=dependencies /proto/ ./
|
||||
COPY --from=zitadel-protos /zitadel/ ./zitadel/
|
||||
|
||||
ENTRYPOINT [ "sh", "-c", "grpc-mock -v 1 -proto $(tr '\n' ',' < ./mocked-services.cfg) -stub-dir ./initial-stubs -mock-addr :22222" ]
|
||||
|
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io",
|
||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||
}
|
@@ -22,22 +22,22 @@ describe("verify invite", () => {
|
||||
user: {
|
||||
userId: "221394658884845598",
|
||||
state: 1,
|
||||
username: "john@zitadel.com",
|
||||
loginNames: ["john@zitadel.com"],
|
||||
preferredLoginName: "john@zitadel.com",
|
||||
username: "john@example.com",
|
||||
loginNames: ["john@example.com"],
|
||||
preferredLoginName: "john@example.com",
|
||||
human: {
|
||||
userId: "221394658884845598",
|
||||
state: 1,
|
||||
username: "john@zitadel.com",
|
||||
loginNames: ["john@zitadel.com"],
|
||||
preferredLoginName: "john@zitadel.com",
|
||||
username: "john@example.com",
|
||||
loginNames: ["john@example.com"],
|
||||
preferredLoginName: "john@example.com",
|
||||
profile: {
|
||||
givenName: "John",
|
||||
familyName: "Doe",
|
||||
avatarUrl: "https://zitadel.com/avatar.jpg",
|
||||
avatarUrl: "https://example.com/avatar.jpg",
|
||||
},
|
||||
email: {
|
||||
email: "john@zitadel.com",
|
||||
email: "john@example.com",
|
||||
isVerified: false,
|
||||
},
|
||||
},
|
||||
@@ -68,7 +68,7 @@ describe("verify invite", () => {
|
||||
factors: {
|
||||
user: {
|
||||
id: "221394658884845598",
|
||||
loginName: "john@zitadel.com",
|
||||
loginName: "john@example.com",
|
||||
},
|
||||
password: undefined,
|
||||
webAuthN: undefined,
|
||||
@@ -93,7 +93,7 @@ describe("verify invite", () => {
|
||||
stub("zitadel.user.v2.UserService", "VerifyInviteCode");
|
||||
|
||||
cy.visit("/verify?userId=221394658884845598&code=abc&invite=true");
|
||||
cy.url({ timeout: 10_000 }).should("include", Cypress.config().baseUrl + "/authenticator/set");
|
||||
cy.url().should("include", Cypress.config().baseUrl + "/authenticator/set");
|
||||
});
|
||||
|
||||
it("shows an error if invite code validation failed", () => {
|
||||
|
@@ -33,7 +33,7 @@ describe("login", () => {
|
||||
factors: {
|
||||
user: {
|
||||
id: "221394658884845598",
|
||||
loginName: "john@zitadel.com",
|
||||
loginName: "john@example.com",
|
||||
},
|
||||
password: undefined,
|
||||
webAuthN: undefined,
|
||||
@@ -64,22 +64,22 @@ describe("login", () => {
|
||||
{
|
||||
userId: "221394658884845598",
|
||||
state: 1,
|
||||
username: "john@zitadel.com",
|
||||
loginNames: ["john@zitadel.com"],
|
||||
preferredLoginName: "john@zitadel.com",
|
||||
username: "john@example.com",
|
||||
loginNames: ["john@example.com"],
|
||||
preferredLoginName: "john@example.com",
|
||||
human: {
|
||||
userId: "221394658884845598",
|
||||
state: 1,
|
||||
username: "john@zitadel.com",
|
||||
loginNames: ["john@zitadel.com"],
|
||||
preferredLoginName: "john@zitadel.com",
|
||||
username: "john@example.com",
|
||||
loginNames: ["john@example.com"],
|
||||
preferredLoginName: "john@example.com",
|
||||
profile: {
|
||||
givenName: "John",
|
||||
familyName: "Doe",
|
||||
avatarUrl: "https://zitadel.com/avatar.jpg",
|
||||
avatarUrl: "https://example.com/avatar.jpg",
|
||||
},
|
||||
email: {
|
||||
email: "john@zitadel.com",
|
||||
email: "john@example.com",
|
||||
isVerified: true,
|
||||
},
|
||||
},
|
||||
@@ -94,8 +94,8 @@ describe("login", () => {
|
||||
});
|
||||
});
|
||||
it("should redirect a user with password authentication to /password", () => {
|
||||
cy.visit("/loginname?loginName=john%40zitadel.com&submit=true");
|
||||
cy.url({ timeout: 10_000 }).should("include", Cypress.config().baseUrl + "/password");
|
||||
cy.visit("/loginname?loginName=john%40example.com&submit=true");
|
||||
cy.url({ timeout: 5 * 60_000 }).should("include", Cypress.config().baseUrl + "/password");
|
||||
});
|
||||
describe("with passkey prompt", () => {
|
||||
beforeEach(() => {
|
||||
@@ -112,8 +112,8 @@ describe("login", () => {
|
||||
});
|
||||
});
|
||||
// it("should prompt a user to setup passwordless authentication if passkey is allowed in the login settings", () => {
|
||||
// cy.visit("/loginname?loginName=john%40zitadel.com&submit=true");
|
||||
// cy.location("pathname", { timeout: 10_000 }).should("eq", "/password");
|
||||
// cy.visit("/loginname?loginName=john%40example.com&submit=true");
|
||||
// cy.location("pathname", { timeout: 5 * 60_000 }).should("eq", "/password");
|
||||
// cy.get('input[type="password"]').focus().type("MyStrongPassword!1");
|
||||
// cy.get('button[type="submit"]').click();
|
||||
// cy.location("pathname", { timeout: 10_000 }).should(
|
||||
@@ -134,22 +134,22 @@ describe("login", () => {
|
||||
{
|
||||
userId: "221394658884845598",
|
||||
state: 1,
|
||||
username: "john@zitadel.com",
|
||||
loginNames: ["john@zitadel.com"],
|
||||
preferredLoginName: "john@zitadel.com",
|
||||
username: "john@example.com",
|
||||
loginNames: ["john@example.com"],
|
||||
preferredLoginName: "john@example.com",
|
||||
human: {
|
||||
userId: "221394658884845598",
|
||||
state: 1,
|
||||
username: "john@zitadel.com",
|
||||
loginNames: ["john@zitadel.com"],
|
||||
preferredLoginName: "john@zitadel.com",
|
||||
username: "john@example.com",
|
||||
loginNames: ["john@example.com"],
|
||||
preferredLoginName: "john@example.com",
|
||||
profile: {
|
||||
givenName: "John",
|
||||
familyName: "Doe",
|
||||
avatarUrl: "https://zitadel.com/avatar.jpg",
|
||||
avatarUrl: "https://example.com/avatar.jpg",
|
||||
},
|
||||
email: {
|
||||
email: "john@zitadel.com",
|
||||
email: "john@example.com",
|
||||
isVerified: true,
|
||||
},
|
||||
},
|
||||
@@ -165,8 +165,8 @@ describe("login", () => {
|
||||
});
|
||||
|
||||
it("should redirect a user with passwordless authentication to /passkey", () => {
|
||||
cy.visit("/loginname?loginName=john%40zitadel.com&submit=true");
|
||||
cy.url({ timeout: 10_000 }).should("include", Cypress.config().baseUrl + "/passkey");
|
||||
cy.visit("/loginname?loginName=john%40example.com&submit=true");
|
||||
cy.url().should("include", Cypress.config().baseUrl + "/passkey");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -15,7 +15,7 @@ describe("register idps", () => {
|
||||
cy.visit("/idp");
|
||||
cy.get('button[e2e="google"]').click();
|
||||
cy.origin(IDP_URL, { args: IDP_URL }, (url) => {
|
||||
cy.location("href", { timeout: 10_000 }).should("eq", url);
|
||||
cy.location("href").should("eq", url);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -48,7 +48,7 @@ describe("register", () => {
|
||||
factors: {
|
||||
user: {
|
||||
id: "221394658884845598",
|
||||
loginName: "john@zitadel.com",
|
||||
loginName: "john@example.com",
|
||||
},
|
||||
password: undefined,
|
||||
webAuthN: undefined,
|
||||
@@ -64,10 +64,10 @@ describe("register", () => {
|
||||
cy.visit("/register");
|
||||
cy.get('input[data-testid="firstname-text-input"]').focus().type("John");
|
||||
cy.get('input[data-testid="lastname-text-input"]').focus().type("Doe");
|
||||
cy.get('input[data-testid="email-text-input"]').focus().type("john@zitadel.com");
|
||||
cy.get('input[data-testid="email-text-input"]').focus().type("john@example.com");
|
||||
cy.get('input[type="checkbox"][value="privacypolicy"]').check();
|
||||
cy.get('input[type="checkbox"][value="tos"]').check();
|
||||
cy.get('button[type="submit"]').click();
|
||||
cy.url({ timeout: 10_000 }).should("include", Cypress.config().baseUrl + "/passkey/set");
|
||||
cy.url().should("include", Cypress.config().baseUrl + "/passkey/set");
|
||||
});
|
||||
});
|
||||
|
@@ -24,22 +24,22 @@ describe("verify email", () => {
|
||||
user: {
|
||||
userId: "221394658884845598",
|
||||
state: 1,
|
||||
username: "john@zitadel.com",
|
||||
loginNames: ["john@zitadel.com"],
|
||||
preferredLoginName: "john@zitadel.com",
|
||||
username: "john@example.com",
|
||||
loginNames: ["john@example.com"],
|
||||
preferredLoginName: "john@example.com",
|
||||
human: {
|
||||
userId: "221394658884845598",
|
||||
state: 1,
|
||||
username: "john@zitadel.com",
|
||||
loginNames: ["john@zitadel.com"],
|
||||
preferredLoginName: "john@zitadel.com",
|
||||
username: "john@example.com",
|
||||
loginNames: ["john@example.com"],
|
||||
preferredLoginName: "john@example.com",
|
||||
profile: {
|
||||
givenName: "John",
|
||||
familyName: "Doe",
|
||||
avatarUrl: "https://zitadel.com/avatar.jpg",
|
||||
avatarUrl: "https://example.com/avatar.jpg",
|
||||
},
|
||||
email: {
|
||||
email: "john@zitadel.com",
|
||||
email: "john@example.com",
|
||||
isVerified: false, // email is not verified yet
|
||||
},
|
||||
},
|
||||
@@ -70,7 +70,7 @@ describe("verify email", () => {
|
||||
factors: {
|
||||
user: {
|
||||
id: "221394658884845598",
|
||||
loginName: "john@zitadel.com",
|
||||
loginName: "john@example.com",
|
||||
},
|
||||
password: undefined,
|
||||
webAuthN: undefined,
|
||||
@@ -90,6 +90,6 @@ describe("verify email", () => {
|
||||
// TODO: Avoid uncaught exception in application
|
||||
cy.once("uncaught:exception", () => false);
|
||||
cy.visit("/verify?userId=221394658884845598&code=abc");
|
||||
cy.contains("Could not verify email", { timeout: 10_000 });
|
||||
cy.contains("Could not verify email");
|
||||
});
|
||||
});
|
||||
|
@@ -1,4 +1,4 @@
|
||||
const url = Cypress.env("CORE_MOCK_STUBS_URL") || "http://mock-zitadel:22220/v1/stubs";
|
||||
const url = Cypress.env("CORE_MOCK_STUBS_URL") || "http://localhost:22220/v1/stubs";
|
||||
|
||||
function removeStub(service: string, method: string) {
|
||||
return cy.request({
|
||||
|
@@ -4,5 +4,5 @@
|
||||
"lib": ["es5", "dom"],
|
||||
"types": ["cypress", "node"]
|
||||
},
|
||||
"include": ["**/*.ts"]
|
||||
"include": ["**/*.ts", "../cypress.config.ts"]
|
||||
}
|
||||
|
2
apps/login/next-env-vars.d.ts
vendored
2
apps/login/next-env-vars.d.ts
vendored
@@ -27,6 +27,8 @@ declare namespace NodeJS {
|
||||
/**
|
||||
* Optional: custom request headers to be added to every request
|
||||
* Split by comma, key value pairs separated by colon
|
||||
* For example: to call the Zitadel API at an internal address, you can set:
|
||||
* `CUSTOM_REQUEST_HEADERS=Host:http://zitadel-internal:8080`
|
||||
*/
|
||||
CUSTOM_REQUEST_HEADERS?: string;
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"packageManager": "pnpm@9.1.2+sha256.19c17528f9ca20bd442e4ca42f00f1b9808a9cb419383cd04ba32ef19322aba7",
|
||||
"packageManager": "pnpm@10.13.1",
|
||||
"name": "@zitadel/login",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
@@ -15,8 +15,7 @@
|
||||
"test:unit": "vitest --run",
|
||||
"lint-staged": "lint-staged",
|
||||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next",
|
||||
"test:integration:login": "cypress run",
|
||||
"test:integration:login:debug": "cypress open",
|
||||
"test:integration:login": "wait-on --simultaneous 1 http://localhost:3001/ui/v2/login/verify?userId=221394658884845598&code=abc && cypress run",
|
||||
"test:acceptance": "dotenv -e ../login/.env.test.local playwright",
|
||||
"test:acceptance:setup": "cd ../.. && make login_test_acceptance_setup_env && NODE_ENV=test turbo run test:acceptance:setup:dev",
|
||||
"test:acceptance:setup:dev": "cd ../.. && make login_test_acceptance_setup_dev"
|
||||
@@ -54,6 +53,11 @@
|
||||
"devDependencies": {
|
||||
"@babel/eslint-parser": "^7.23.0",
|
||||
"@bufbuild/buf": "^1.53.0",
|
||||
"@faker-js/faker": "^9.7.0",
|
||||
"@otplib/core": "^12.0.0",
|
||||
"@otplib/plugin-crypto": "^12.0.0",
|
||||
"@otplib/plugin-thirty-two": "^12.0.0",
|
||||
"@playwright/test": "^1.52.0",
|
||||
"@testing-library/jest-dom": "^6.6.3",
|
||||
"@testing-library/react": "^16.3.0",
|
||||
"@types/ms": "2.1.0",
|
||||
@@ -67,34 +71,30 @@
|
||||
"@vercel/git-hooks": "1.0.0",
|
||||
"@vitejs/plugin-react": "^4.4.1",
|
||||
"autoprefixer": "10.4.21",
|
||||
"concurrently": "^9.1.2",
|
||||
"cypress": "^14.5.2",
|
||||
"dotenv-cli": "^8.0.0",
|
||||
"env-cmd": "^10.0.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-next": "15.4.0-canary.86",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"gaxios": "^7.1.0",
|
||||
"grpc-tools": "1.13.0",
|
||||
"jsdom": "^26.1.0",
|
||||
"lint-staged": "15.5.1",
|
||||
"make-dir-cli": "4.0.0",
|
||||
"nodemon": "^3.1.9",
|
||||
"postcss": "8.5.3",
|
||||
"prettier": "^3.2.5",
|
||||
"prettier-plugin-organize-imports": "^3.2.0",
|
||||
"prettier-plugin-tailwindcss": "0.6.11",
|
||||
"sass": "^1.87.0",
|
||||
"start-server-and-test": "^2.0.11",
|
||||
"tailwindcss": "3.4.14",
|
||||
"ts-proto": "^2.7.0",
|
||||
"typescript": "^5.8.3",
|
||||
"vite-tsconfig-paths": "^5.1.4",
|
||||
"vitest": "^2.0.0",
|
||||
"concurrently": "^9.1.2",
|
||||
"cypress": "^14.5.2",
|
||||
"dotenv-cli": "^8.0.0",
|
||||
"env-cmd": "^10.0.0",
|
||||
"nodemon": "^3.1.9",
|
||||
"start-server-and-test": "^2.0.11",
|
||||
"@faker-js/faker": "^9.7.0",
|
||||
"@otplib/core": "^12.0.0",
|
||||
"@otplib/plugin-crypto": "^12.0.0",
|
||||
"@otplib/plugin-thirty-two": "^12.0.0",
|
||||
"@playwright/test": "^1.52.0",
|
||||
"gaxios": "^7.1.0"
|
||||
"wait-on": "^7.2.0"
|
||||
}
|
||||
}
|
||||
}
|
9151
apps/login/pnpm-lock.yaml
generated
Normal file
9151
apps/login/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,22 +1,57 @@
|
||||
{
|
||||
"extends": ["//"],
|
||||
"extends": [
|
||||
"//"
|
||||
],
|
||||
"tasks": {
|
||||
"build": {
|
||||
"outputs": ["dist/**", ".next/**", "!.next/cache/**"],
|
||||
"dependsOn": ["@zitadel/client#build"]
|
||||
"outputs": [
|
||||
"dist/**",
|
||||
".next/**",
|
||||
"!.next/cache/**"
|
||||
],
|
||||
"dependsOn": [
|
||||
"@zitadel/client#build"
|
||||
]
|
||||
},
|
||||
"build:login:standalone": {
|
||||
"outputs": ["dist/**", ".next/**", "!.next/cache/**"],
|
||||
"dependsOn": ["@zitadel/client#build"]
|
||||
"outputs": [
|
||||
"dist/**",
|
||||
".next/**",
|
||||
"!.next/cache/**"
|
||||
],
|
||||
"dependsOn": [
|
||||
"@zitadel/client#build"
|
||||
]
|
||||
},
|
||||
"dev": {
|
||||
"dependsOn": ["@zitadel/client#build"]
|
||||
"persistent": true,
|
||||
"cache": false,
|
||||
"dependsOn": [
|
||||
"@zitadel/client#build"
|
||||
]
|
||||
},
|
||||
"test": {
|
||||
"dependsOn": ["@zitadel/client#build"]
|
||||
"dependsOn": [
|
||||
"@zitadel/client#build"
|
||||
]
|
||||
},
|
||||
"test:unit": {
|
||||
"dependsOn": ["@zitadel/client#build"]
|
||||
"dependsOn": [
|
||||
"@zitadel/client#build"
|
||||
]
|
||||
},
|
||||
"test:integration:login": {
|
||||
"inputs": [
|
||||
".next/**",
|
||||
"!.next/cache/**",
|
||||
"integration/integration/**",
|
||||
"integration/support/**",
|
||||
"cypress.config.ts"
|
||||
],
|
||||
"outputs": [
|
||||
"cypress/videos/**",
|
||||
"cypress/screenshots/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user