diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml index 150e308daa68..44de096b978b 100644 --- a/.github/codeql/codeql-config.yml +++ b/.github/codeql/codeql-config.yml @@ -1,8 +1,8 @@ -name: 'CodeQL config' +name: "CodeQL config" queries: - uses: security-and-quality paths-ignore: - - '/test/' - - '/internal/testhelpers' + - "/test/" + - "/internal/testhelpers" diff --git a/.github/config.yml b/.github/config.yml index 0d121fe184f9..ea335697979b 100644 --- a/.github/config.yml +++ b/.github/config.yml @@ -1,3 +1,3 @@ todo: - keyword: '@todo' + keyword: "@todo" label: todo diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index fd42a7c5c26f..b1e98fc98d4b 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -4,7 +4,7 @@ on: branches: - master tags: - - '*' + - "*" pull_request: # Cancel in-progress runs in current workflow. @@ -42,14 +42,14 @@ jobs: ports: - 3306:3306 env: - TEST_MAILHOG_SMTP: 'smtp://test:test@127.0.0.1:1025/?disable_starttls=true' + TEST_MAILHOG_SMTP: "smtp://test:test@127.0.0.1:1025/?disable_starttls=true" TEST_MAILHOG_API: http://127.0.0.1:8025 TEST_SELFSERVICE_OIDC_HYDRA_ADMIN: http://localhost:4445 TEST_SELFSERVICE_OIDC_HYDRA_PUBLIC: http://localhost:4444 TEST_SELFSERVICE_OIDC_HYDRA_INTEGRATION_ADDR: http://127.0.0.1:4499 - TEST_DATABASE_POSTGRESQL: 'postgres://test:test@localhost:5432/postgres?sslmode=disable' - TEST_DATABASE_MYSQL: 'mysql://root:test@(localhost:3306)/mysql?parseTime=true&multiStatements=true' - TEST_DATABASE_COCKROACHDB: 'cockroach://root@localhost:26257/defaultdb?sslmode=disable' + TEST_DATABASE_POSTGRESQL: "postgres://test:test@localhost:5432/postgres?sslmode=disable" + TEST_DATABASE_MYSQL: "mysql://root:test@(localhost:3306)/mysql?parseTime=true&multiStatements=true" + TEST_DATABASE_COCKROACHDB: "cockroach://root@localhost:26257/defaultdb?sslmode=disable" steps: - run: | docker create --name cockroach -p 26257:26257 \ @@ -77,7 +77,7 @@ jobs: fetch-depth: 2 - uses: actions/setup-go@v2 with: - go-version: '~1.18' + go-version: "~1.18" - run: go list -json > go.list - name: Run nancy uses: sonatype-nexus-community/nancy-github-action@v1.0.2 @@ -133,12 +133,12 @@ jobs: - 4437:4437 - 1025:1025 env: - TEST_DATABASE_POSTGRESQL: 'postgres://test:test@localhost:5432/postgres?sslmode=disable' - TEST_DATABASE_MYSQL: 'mysql://root:test@(localhost:3306)/mysql?parseTime=true&multiStatements=true' - TEST_DATABASE_COCKROACHDB: 'cockroach://root@localhost:26257/defaultdb?sslmode=disable' + TEST_DATABASE_POSTGRESQL: "postgres://test:test@localhost:5432/postgres?sslmode=disable" + TEST_DATABASE_MYSQL: "mysql://root:test@(localhost:3306)/mysql?parseTime=true&multiStatements=true" + TEST_DATABASE_COCKROACHDB: "cockroach://root@localhost:26257/defaultdb?sslmode=disable" strategy: matrix: - database: ['postgres', 'cockroach', 'sqlite', 'mysql'] + database: ["postgres", "cockroach", "sqlite", "mysql"] steps: - run: | docker create --name cockroach -p 26257:26257 \ @@ -162,7 +162,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v2 with: - go-version: '~1.18' + go-version: "~1.18" - name: Install selfservice-ui-react-native uses: actions/checkout@v2 with: @@ -202,7 +202,7 @@ jobs: - uses: ory/ci/docs/cli-next@master with: token: ${{ secrets.ORY_BOT_PAT }} - arg: '.' + arg: "." output-dir: docs/kratos changelog: @@ -230,7 +230,7 @@ jobs: - uses: ory/ci/sdk/release@master with: token: ${{ secrets.ORY_BOT_PAT }} - swag-spec-location: 'spec/api.json' + swag-spec-location: "spec/api.json" release: name: Generate release @@ -273,7 +273,7 @@ jobs: mailchimp_list_id: f605a41b53 mailchmip_segment_id: 6479477 mailchimp_api_key: ${{ secrets.MAILCHIMP_API_KEY }} - draft: 'true' + draft: "true" ssh_key: ${{ secrets.ORY_BOT_SSH_KEY }} slack-approval-notification: @@ -300,5 +300,5 @@ jobs: mailchimp_list_id: f605a41b53 mailchmip_segment_id: 6479477 mailchimp_api_key: ${{ secrets.MAILCHIMP_API_KEY }} - draft: 'false' + draft: "false" ssh_key: ${{ secrets.ORY_BOT_SSH_KEY }} diff --git a/.github/workflows/closed_references.yml b/.github/workflows/closed_references.yml index ebafc8a71af4..2789ac42c2c7 100644 --- a/.github/workflows/closed_references.yml +++ b/.github/workflows/closed_references.yml @@ -2,13 +2,13 @@ name: Closed Reference Notifier on: schedule: - - cron: '0 0 * * *' + - cron: "0 0 * * *" workflow_dispatch: inputs: issueLimit: description: Max. number of issues to create required: true - default: '5' + default: "5" jobs: find_closed_references: @@ -19,7 +19,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-node@v2-beta with: - node-version: '14' + node-version: "14" - uses: ory/closed-reference-notifier@v1 with: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 5748d218807d..a4d098e9826a 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -9,7 +9,7 @@ # the `language` matrix defined below to confirm you have the correct set of # supported CodeQL languages. # -name: 'CodeQL' +name: "CodeQL" on: push: @@ -18,7 +18,7 @@ on: # The branches below must be a subset of the branches above branches: [master] schedule: - - cron: '26 21 * * 3' + - cron: "26 21 * * 3" jobs: analyze: @@ -28,7 +28,7 @@ jobs: strategy: fail-fast: false matrix: - language: ['go', 'javascript'] + language: ["go", "javascript"] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] # Learn more: # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed diff --git a/.github/workflows/cve-scan.yaml b/.github/workflows/cve-scan.yaml index b6f169ebc6b4..91cee707752e 100644 --- a/.github/workflows/cve-scan.yaml +++ b/.github/workflows/cve-scan.yaml @@ -2,12 +2,12 @@ name: Docker Image Scanners on: push: branches: - - 'master' + - "master" tags: - - 'v*.*.*' + - "v*.*.*" pull_request: branches: - - 'master' + - "master" jobs: scanners: @@ -50,11 +50,11 @@ jobs: if: ${{ always() }} with: image-ref: oryd/kratos:${{ steps.vars.outputs.sha_short }} - format: 'table' - exit-code: '42' + format: "table" + exit-code: "42" ignore-unfixed: true - vuln-type: 'os,library' - severity: 'CRITICAL,HIGH' + vuln-type: "os,library" + severity: "CRITICAL,HIGH" - name: Dockle Linter uses: erzz/dockle-action@v1.3.1 if: ${{ always() }} diff --git a/.github/workflows/milestone.yml b/.github/workflows/milestone.yml index b4a30699f010..fb47e4a78f0f 100644 --- a/.github/workflows/milestone.yml +++ b/.github/workflows/milestone.yml @@ -3,7 +3,7 @@ name: Generate and Publish Milestone Document on: workflow_dispatch: schedule: - - cron: '0 0 * * *' + - cron: "0 0 * * *" jobs: milestone: @@ -23,8 +23,8 @@ jobs: - name: Commit Milestone Documentation uses: EndBug/add-and-commit@v4.4.0 with: - message: 'autogen(docs): update milestone document' + message: "autogen(docs): update milestone document" author_name: aeneasr - author_email: '3372410+aeneasr@users.noreply.github.com' + author_email: "3372410+aeneasr@users.noreply.github.com" env: GITHUB_TOKEN: ${{ secrets.TOKEN_PRIVILEGED }} diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 395cb69206da..eb36db174bba 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -1,8 +1,8 @@ -name: 'Close Stale Issues' +name: "Close Stale Issues" on: workflow_dispatch: schedule: - - cron: '0 0 * * *' + - cron: "0 0 * * *" jobs: stale: @@ -35,10 +35,10 @@ jobs: Thank you for your understanding and to anyone who participated in the conversation! And as written above, please do participate in the conversation if this topic is important to you! Thank you 🙏✌️ - stale-issue-label: 'stale' - exempt-issue-labels: 'bug,blocking,docs,backlog' + stale-issue-label: "stale" + exempt-issue-labels: "bug,blocking,docs,backlog" days-before-stale: 365 days-before-close: 30 exempt-milestones: true exempt-assignees: true - only-pr-labels: 'stale' + only-pr-labels: "stale" diff --git a/.prettierignore b/.prettierignore index 7ecf7b391740..f17dca413604 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1 +1,2 @@ .schema/ +.github/ISSUE_TEMPLATE diff --git a/Makefile b/Makefile index 31dff407bef4..b2e009ef6c3a 100644 --- a/Makefile +++ b/Makefile @@ -138,6 +138,7 @@ quickstart-dev: format: .bin/goimports node_modules goimports -w -local github.com/ory . npm exec -- prettier --write 'test/e2e/**/*{.ts,.js}' + npm exec -- prettier --write '.github' # Build local docker image .PHONY: docker diff --git a/internal/httpclient/api_metadata.go b/internal/httpclient/api_metadata.go index a63febb073aa..eec994165b53 100644 --- a/internal/httpclient/api_metadata.go +++ b/internal/httpclient/api_metadata.go @@ -102,16 +102,16 @@ func (r MetadataApiApiGetVersionRequest) Execute() (*InlineResponse2001, *http.R } /* - * GetVersion Return Running Software Version. - * This endpoint returns the version of Ory Kratos. + - GetVersion Return Running Software Version. + - This endpoint returns the version of Ory Kratos. If the service supports TLS Edge Termination, this endpoint does not require the `X-Forwarded-Proto` header to be set. Be aware that if you are running multiple nodes of this service, the version will never refer to the cluster state, only to a single instance. - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return MetadataApiApiGetVersionRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return MetadataApiApiGetVersionRequest */ func (a *MetadataApiService) GetVersion(ctx context.Context) MetadataApiApiGetVersionRequest { return MetadataApiApiGetVersionRequest{ @@ -209,8 +209,9 @@ func (r MetadataApiApiIsAliveRequest) Execute() (*InlineResponse200, *http.Respo } /* - * IsAlive Check HTTP Server Status - * This endpoint returns a HTTP 200 status code when Ory Kratos is accepting incoming + - IsAlive Check HTTP Server Status + - This endpoint returns a HTTP 200 status code when Ory Kratos is accepting incoming + HTTP requests. This status does currently not include checks whether the database connection is working. If the service supports TLS Edge Termination, this endpoint does not require the @@ -218,8 +219,8 @@ If the service supports TLS Edge Termination, this endpoint does not require the Be aware that if you are running multiple nodes of this service, the health status will never refer to the cluster state, only to a single instance. - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return MetadataApiApiIsAliveRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return MetadataApiApiIsAliveRequest */ func (a *MetadataApiService) IsAlive(ctx context.Context) MetadataApiApiIsAliveRequest { return MetadataApiApiIsAliveRequest{ @@ -326,8 +327,9 @@ func (r MetadataApiApiIsReadyRequest) Execute() (*InlineResponse200, *http.Respo } /* - * IsReady Check HTTP Server and Database Status - * This endpoint returns a HTTP 200 status code when Ory Kratos is up running and the environment dependencies (e.g. + - IsReady Check HTTP Server and Database Status + - This endpoint returns a HTTP 200 status code when Ory Kratos is up running and the environment dependencies (e.g. + the database) are responsive as well. If the service supports TLS Edge Termination, this endpoint does not require the @@ -335,8 +337,8 @@ If the service supports TLS Edge Termination, this endpoint does not require the Be aware that if you are running multiple nodes of Ory Kratos, the health status will never refer to the cluster state, only to a single instance. - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return MetadataApiApiIsReadyRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return MetadataApiApiIsReadyRequest */ func (a *MetadataApiService) IsReady(ctx context.Context) MetadataApiApiIsReadyRequest { return MetadataApiApiIsReadyRequest{ diff --git a/internal/httpclient/api_v0alpha2.go b/internal/httpclient/api_v0alpha2.go index 9a364f251342..28ee4d1f4359 100644 --- a/internal/httpclient/api_v0alpha2.go +++ b/internal/httpclient/api_v0alpha2.go @@ -1292,11 +1292,12 @@ func (r V0alpha2ApiApiAdminCreateSelfServiceRecoveryLinkRequest) Execute() (*Sel } /* - * AdminCreateSelfServiceRecoveryLink # Create a Recovery Link - * This endpoint creates a recovery link which should be given to the user in order for them to recover + - AdminCreateSelfServiceRecoveryLink # Create a Recovery Link + - This endpoint creates a recovery link which should be given to the user in order for them to recover + (or activate) their account. - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiAdminCreateSelfServiceRecoveryLinkRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiAdminCreateSelfServiceRecoveryLinkRequest */ func (a *V0alpha2ApiService) AdminCreateSelfServiceRecoveryLink(ctx context.Context) V0alpha2ApiApiAdminCreateSelfServiceRecoveryLinkRequest { return V0alpha2ApiApiAdminCreateSelfServiceRecoveryLinkRequest{ @@ -1426,15 +1427,16 @@ func (r V0alpha2ApiApiAdminDeleteIdentityRequest) Execute() (*http.Response, err } /* - * AdminDeleteIdentity # Delete an Identity - * Calling this endpoint irrecoverably and permanently deletes the identity given its ID. This action can not be undone. + - AdminDeleteIdentity # Delete an Identity + - Calling this endpoint irrecoverably and permanently deletes the identity given its ID. This action can not be undone. + This endpoint returns 204 when the identity was deleted or when the identity was not found, in which case it is assumed that is has been deleted already. Learn how identities work in [Ory Kratos' User And Identity Model Documentation](https://www.ory.sh/docs/next/kratos/concepts/identity-user-model). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @param id ID is the identity's ID. - * @return V0alpha2ApiApiAdminDeleteIdentityRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param id ID is the identity's ID. + - @return V0alpha2ApiApiAdminDeleteIdentityRequest */ func (a *V0alpha2ApiService) AdminDeleteIdentity(ctx context.Context, id string) V0alpha2ApiApiAdminDeleteIdentityRequest { return V0alpha2ApiApiAdminDeleteIdentityRequest{ @@ -1557,13 +1559,13 @@ func (r V0alpha2ApiApiAdminDeleteIdentitySessionsRequest) Execute() (*http.Respo } /* - * AdminDeleteIdentitySessions Calling this endpoint irrecoverably and permanently deletes and invalidates all sessions that belong to the given Identity. - * This endpoint is useful for: + - AdminDeleteIdentitySessions Calling this endpoint irrecoverably and permanently deletes and invalidates all sessions that belong to the given Identity. + - This endpoint is useful for: To forcefully logout Identity from all devices and sessions - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @param id ID is the identity's ID. - * @return V0alpha2ApiApiAdminDeleteIdentitySessionsRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param id ID is the identity's ID. + - @return V0alpha2ApiApiAdminDeleteIdentitySessionsRequest */ func (a *V0alpha2ApiService) AdminDeleteIdentitySessions(ctx context.Context, id string) V0alpha2ApiApiAdminDeleteIdentitySessionsRequest { return V0alpha2ApiApiAdminDeleteIdentitySessionsRequest{ @@ -2172,12 +2174,12 @@ func (r V0alpha2ApiApiAdminListIdentitiesRequest) Execute() ([]Identity, *http.R } /* - * AdminListIdentities # List Identities - * Lists all identities. Does not support search at the moment. + - AdminListIdentities # List Identities + - Lists all identities. Does not support search at the moment. Learn how identities work in [Ory Kratos' User And Identity Model Documentation](https://www.ory.sh/docs/next/kratos/concepts/identity-user-model). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiAdminListIdentitiesRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiAdminListIdentitiesRequest */ func (a *V0alpha2ApiService) AdminListIdentities(ctx context.Context) V0alpha2ApiApiAdminListIdentitiesRequest { return V0alpha2ApiApiAdminListIdentitiesRequest{ @@ -2321,13 +2323,13 @@ func (r V0alpha2ApiApiAdminListIdentitySessionsRequest) Execute() ([]Session, *h } /* - * AdminListIdentitySessions This endpoint returns all sessions that belong to the given Identity. - * This endpoint is useful for: + - AdminListIdentitySessions This endpoint returns all sessions that belong to the given Identity. + - This endpoint is useful for: Listing all sessions that belong to an Identity in an administrative context. - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @param id ID is the identity's ID. - * @return V0alpha2ApiApiAdminListIdentitySessionsRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param id ID is the identity's ID. + - @return V0alpha2ApiApiAdminListIdentitySessionsRequest */ func (a *V0alpha2ApiService) AdminListIdentitySessions(ctx context.Context, id string) V0alpha2ApiApiAdminListIdentitySessionsRequest { return V0alpha2ApiApiAdminListIdentitySessionsRequest{ @@ -2496,13 +2498,13 @@ func (r V0alpha2ApiApiAdminPatchIdentityRequest) Execute() (*Identity, *http.Res } /* - * AdminPatchIdentity Partially updates an Identity's field using [JSON Patch](https://jsonpatch.com/) - * NOTE: The fields `id`, `stateChangedAt` and `credentials` are not updateable. + - AdminPatchIdentity Partially updates an Identity's field using [JSON Patch](https://jsonpatch.com/) + - NOTE: The fields `id`, `stateChangedAt` and `credentials` are not updateable. Learn how identities work in [Ory Kratos' User And Identity Model Documentation](https://www.ory.sh/docs/next/kratos/concepts/identity-user-model). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @param id ID must be set to the ID of identity you want to update - * @return V0alpha2ApiApiAdminPatchIdentityRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param id ID must be set to the ID of identity you want to update + - @return V0alpha2ApiApiAdminPatchIdentityRequest */ func (a *V0alpha2ApiService) AdminPatchIdentity(ctx context.Context, id string) V0alpha2ApiApiAdminPatchIdentityRequest { return V0alpha2ApiApiAdminPatchIdentityRequest{ @@ -2664,13 +2666,13 @@ func (r V0alpha2ApiApiAdminUpdateIdentityRequest) Execute() (*Identity, *http.Re } /* - * AdminUpdateIdentity # Update an Identity - * This endpoint updates an identity. The full identity payload (except credentials) is expected. This endpoint does not support patching. + - AdminUpdateIdentity # Update an Identity + - This endpoint updates an identity. The full identity payload (except credentials) is expected. This endpoint does not support patching. Learn how identities work in [Ory Kratos' User And Identity Model Documentation](https://www.ory.sh/docs/next/kratos/concepts/identity-user-model). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @param id ID must be set to the ID of identity you want to update - * @return V0alpha2ApiApiAdminUpdateIdentityRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param id ID must be set to the ID of identity you want to update + - @return V0alpha2ApiApiAdminUpdateIdentityRequest */ func (a *V0alpha2ApiService) AdminUpdateIdentity(ctx context.Context, id string) V0alpha2ApiApiAdminUpdateIdentityRequest { return V0alpha2ApiApiAdminUpdateIdentityRequest{ @@ -2831,8 +2833,8 @@ func (r V0alpha2ApiApiCreateSelfServiceLogoutFlowUrlForBrowsersRequest) Execute( } /* - * CreateSelfServiceLogoutFlowUrlForBrowsers # Create a Logout URL for Browsers - * This endpoint initializes a browser-based user logout flow and a URL which can be used to log out the user. + - CreateSelfServiceLogoutFlowUrlForBrowsers # Create a Logout URL for Browsers + - This endpoint initializes a browser-based user logout flow and a URL which can be used to log out the user. This endpoint is NOT INTENDED for API clients and only works with browsers (Chrome, Firefox, ...). For API clients you can @@ -2842,8 +2844,8 @@ The URL is only valid for the currently signed in user. If no user is signed in, a 401 error. When calling this endpoint from a backend, please ensure to properly forward the HTTP cookies. - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiCreateSelfServiceLogoutFlowUrlForBrowsersRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiCreateSelfServiceLogoutFlowUrlForBrowsersRequest */ func (a *V0alpha2ApiService) CreateSelfServiceLogoutFlowUrlForBrowsers(ctx context.Context) V0alpha2ApiApiCreateSelfServiceLogoutFlowUrlForBrowsersRequest { return V0alpha2ApiApiCreateSelfServiceLogoutFlowUrlForBrowsersRequest{ @@ -3093,16 +3095,16 @@ func (r V0alpha2ApiApiGetSelfServiceErrorRequest) Execute() (*SelfServiceError, } /* - * GetSelfServiceError # Get Self-Service Errors - * This endpoint returns the error associated with a user-facing self service errors. + - GetSelfServiceError # Get Self-Service Errors + - This endpoint returns the error associated with a user-facing self service errors. This endpoint supports stub values to help you implement the error UI: `?id=stub:500` - returns a stub 500 (Internal Server Error) error. More information can be found at [Ory Kratos User User Facing Error Documentation](https://www.ory.sh/docs/kratos/self-service/flows/user-facing-errors). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiGetSelfServiceErrorRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiGetSelfServiceErrorRequest */ func (a *V0alpha2ApiService) GetSelfServiceError(ctx context.Context) V0alpha2ApiApiGetSelfServiceErrorRequest { return V0alpha2ApiApiGetSelfServiceErrorRequest{ @@ -3244,8 +3246,8 @@ func (r V0alpha2ApiApiGetSelfServiceLoginFlowRequest) Execute() (*SelfServiceLog } /* - * GetSelfServiceLoginFlow # Get Login Flow - * This endpoint returns a login flow's context with, for example, error details and other information. + - GetSelfServiceLoginFlow # Get Login Flow + - This endpoint returns a login flow's context with, for example, error details and other information. Browser flows expect the anti-CSRF cookie to be included in the request's HTTP Cookie Header. For AJAX requests you must ensure that cookies are included in the request or requests will fail. @@ -3268,8 +3270,8 @@ This request may fail due to several reasons. The `error.id` can be one of: `self_service_flow_expired`: The flow is expired and you should request a new one. More information can be found at [Ory Kratos User Login](https://www.ory.sh/docs/kratos/self-service/flows/user-login) and [User Registration Documentation](https://www.ory.sh/docs/kratos/self-service/flows/user-registration). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiGetSelfServiceLoginFlowRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiGetSelfServiceLoginFlowRequest */ func (a *V0alpha2ApiService) GetSelfServiceLoginFlow(ctx context.Context) V0alpha2ApiApiGetSelfServiceLoginFlowRequest { return V0alpha2ApiApiGetSelfServiceLoginFlowRequest{ @@ -3424,8 +3426,8 @@ func (r V0alpha2ApiApiGetSelfServiceRecoveryFlowRequest) Execute() (*SelfService } /* - * GetSelfServiceRecoveryFlow # Get Recovery Flow - * This endpoint returns a recovery flow's context with, for example, error details and other information. + - GetSelfServiceRecoveryFlow # Get Recovery Flow + - This endpoint returns a recovery flow's context with, for example, error details and other information. Browser flows expect the anti-CSRF cookie to be included in the request's HTTP Cookie Header. For AJAX requests you must ensure that cookies are included in the request or requests will fail. @@ -3443,8 +3445,8 @@ res.render('recovery', flow) ``` More information can be found at [Ory Kratos Account Recovery Documentation](../self-service/flows/account-recovery). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiGetSelfServiceRecoveryFlowRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiGetSelfServiceRecoveryFlowRequest */ func (a *V0alpha2ApiService) GetSelfServiceRecoveryFlow(ctx context.Context) V0alpha2ApiApiGetSelfServiceRecoveryFlowRequest { return V0alpha2ApiApiGetSelfServiceRecoveryFlowRequest{ @@ -3589,8 +3591,8 @@ func (r V0alpha2ApiApiGetSelfServiceRegistrationFlowRequest) Execute() (*SelfSer } /* - * GetSelfServiceRegistrationFlow # Get Registration Flow - * This endpoint returns a registration flow's context with, for example, error details and other information. + - GetSelfServiceRegistrationFlow # Get Registration Flow + - This endpoint returns a registration flow's context with, for example, error details and other information. Browser flows expect the anti-CSRF cookie to be included in the request's HTTP Cookie Header. For AJAX requests you must ensure that cookies are included in the request or requests will fail. @@ -3613,8 +3615,8 @@ This request may fail due to several reasons. The `error.id` can be one of: `self_service_flow_expired`: The flow is expired and you should request a new one. More information can be found at [Ory Kratos User Login](https://www.ory.sh/docs/kratos/self-service/flows/user-login) and [User Registration Documentation](https://www.ory.sh/docs/kratos/self-service/flows/user-registration). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiGetSelfServiceRegistrationFlowRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiGetSelfServiceRegistrationFlowRequest */ func (a *V0alpha2ApiService) GetSelfServiceRegistrationFlow(ctx context.Context) V0alpha2ApiApiGetSelfServiceRegistrationFlowRequest { return V0alpha2ApiApiGetSelfServiceRegistrationFlowRequest{ @@ -3774,8 +3776,9 @@ func (r V0alpha2ApiApiGetSelfServiceSettingsFlowRequest) Execute() (*SelfService } /* - * GetSelfServiceSettingsFlow # Get Settings Flow - * When accessing this endpoint through Ory Kratos' Public API you must ensure that either the Ory Kratos Session Cookie + - GetSelfServiceSettingsFlow # Get Settings Flow + - When accessing this endpoint through Ory Kratos' Public API you must ensure that either the Ory Kratos Session Cookie + or the Ory Kratos Session Token are set. Depending on your configuration this endpoint might return a 403 error if the session has a lower Authenticator @@ -3794,8 +3797,8 @@ case of an error, the `error.id` of the JSON response body can be one of: identity logged in instead. More information can be found at [Ory Kratos User Settings & Profile Management Documentation](../self-service/flows/user-settings). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiGetSelfServiceSettingsFlowRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiGetSelfServiceSettingsFlowRequest */ func (a *V0alpha2ApiService) GetSelfServiceSettingsFlow(ctx context.Context) V0alpha2ApiApiGetSelfServiceSettingsFlowRequest { return V0alpha2ApiApiGetSelfServiceSettingsFlowRequest{ @@ -3963,8 +3966,8 @@ func (r V0alpha2ApiApiGetSelfServiceVerificationFlowRequest) Execute() (*SelfSer } /* - * GetSelfServiceVerificationFlow # Get Verification Flow - * This endpoint returns a verification flow's context with, for example, error details and other information. + - GetSelfServiceVerificationFlow # Get Verification Flow + - This endpoint returns a verification flow's context with, for example, error details and other information. Browser flows expect the anti-CSRF cookie to be included in the request's HTTP Cookie Header. For AJAX requests you must ensure that cookies are included in the request or requests will fail. @@ -3981,8 +3984,8 @@ res.render('verification', flow) }) More information can be found at [Ory Kratos Email and Phone Verification Documentation](https://www.ory.sh/docs/kratos/selfservice/flows/verify-email-account-activation). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiGetSelfServiceVerificationFlowRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiGetSelfServiceVerificationFlowRequest */ func (a *V0alpha2ApiService) GetSelfServiceVerificationFlow(ctx context.Context) V0alpha2ApiApiGetSelfServiceVerificationFlowRequest { return V0alpha2ApiApiGetSelfServiceVerificationFlowRequest{ @@ -4116,8 +4119,8 @@ func (r V0alpha2ApiApiGetWebAuthnJavaScriptRequest) Execute() (string, *http.Res } /* - * GetWebAuthnJavaScript # Get WebAuthn JavaScript - * This endpoint provides JavaScript which is needed in order to perform WebAuthn login and registration. + - GetWebAuthnJavaScript # Get WebAuthn JavaScript + - This endpoint provides JavaScript which is needed in order to perform WebAuthn login and registration. If you are building a JavaScript Browser App (e.g. in ReactJS or AngularJS) you will need to load this file: @@ -4126,8 +4129,8 @@ If you are building a JavaScript Browser App (e.g. in ReactJS or AngularJS) you ``` More information can be found at [Ory Kratos User Login](https://www.ory.sh/docs/kratos/self-service/flows/user-login) and [User Registration Documentation](https://www.ory.sh/docs/kratos/self-service/flows/user-registration). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiGetWebAuthnJavaScriptRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiGetWebAuthnJavaScriptRequest */ func (a *V0alpha2ApiService) GetWebAuthnJavaScript(ctx context.Context) V0alpha2ApiApiGetWebAuthnJavaScriptRequest { return V0alpha2ApiApiGetWebAuthnJavaScriptRequest{ @@ -4246,8 +4249,9 @@ func (r V0alpha2ApiApiInitializeSelfServiceLoginFlowForBrowsersRequest) Execute( } /* - * InitializeSelfServiceLoginFlowForBrowsers # Initialize Login Flow for Browsers - * This endpoint initializes a browser-based user login flow. This endpoint will set the appropriate + - InitializeSelfServiceLoginFlowForBrowsers # Initialize Login Flow for Browsers + - This endpoint initializes a browser-based user login flow. This endpoint will set the appropriate + cookies and anti-CSRF measures required for browser-based flows. If this endpoint is opened as a link in the browser, it will be redirected to @@ -4266,8 +4270,8 @@ case of an error, the `error.id` of the JSON response body can be one of: This endpoint is NOT INTENDED for clients that do not have a browser (Chrome, Firefox, ...) as cookies are needed. More information can be found at [Ory Kratos User Login](https://www.ory.sh/docs/kratos/self-service/flows/user-login) and [User Registration Documentation](https://www.ory.sh/docs/kratos/self-service/flows/user-registration). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiInitializeSelfServiceLoginFlowForBrowsersRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiInitializeSelfServiceLoginFlowForBrowsersRequest */ func (a *V0alpha2ApiService) InitializeSelfServiceLoginFlowForBrowsers(ctx context.Context) V0alpha2ApiApiInitializeSelfServiceLoginFlowForBrowsersRequest { return V0alpha2ApiApiInitializeSelfServiceLoginFlowForBrowsersRequest{ @@ -4412,8 +4416,8 @@ func (r V0alpha2ApiApiInitializeSelfServiceLoginFlowWithoutBrowserRequest) Execu } /* - * InitializeSelfServiceLoginFlowWithoutBrowser Initialize Login Flow for APIs, Services, Apps, ... - * This endpoint initiates a login flow for API clients that do not use a browser, such as mobile devices, smart TVs, and so on. + - InitializeSelfServiceLoginFlowWithoutBrowser Initialize Login Flow for APIs, Services, Apps, ... + - This endpoint initiates a login flow for API clients that do not use a browser, such as mobile devices, smart TVs, and so on. If a valid provided session cookie or session token is provided, a 400 Bad Request error will be returned unless the URL query parameter `?refresh=true` is set. @@ -4433,8 +4437,8 @@ In the case of an error, the `error.id` of the JSON response body can be one of: This endpoint MUST ONLY be used in scenarios such as native mobile apps (React Native, Objective C, Swift, Java, ...). More information can be found at [Ory Kratos User Login](https://www.ory.sh/docs/kratos/self-service/flows/user-login) and [User Registration Documentation](https://www.ory.sh/docs/kratos/self-service/flows/user-registration). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiInitializeSelfServiceLoginFlowWithoutBrowserRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiInitializeSelfServiceLoginFlowWithoutBrowserRequest */ func (a *V0alpha2ApiService) InitializeSelfServiceLoginFlowWithoutBrowser(ctx context.Context) V0alpha2ApiApiInitializeSelfServiceLoginFlowWithoutBrowserRequest { return V0alpha2ApiApiInitializeSelfServiceLoginFlowWithoutBrowserRequest{ @@ -4566,8 +4570,9 @@ func (r V0alpha2ApiApiInitializeSelfServiceRecoveryFlowForBrowsersRequest) Execu } /* - * InitializeSelfServiceRecoveryFlowForBrowsers # Initialize Recovery Flow for Browsers - * This endpoint initializes a browser-based account recovery flow. Once initialized, the browser will be redirected to + - InitializeSelfServiceRecoveryFlowForBrowsers # Initialize Recovery Flow for Browsers + - This endpoint initializes a browser-based account recovery flow. Once initialized, the browser will be redirected to + `selfservice.flows.recovery.ui_url` with the flow ID set as the query parameter `?flow=`. If a valid user session exists, the browser is returned to the configured return URL. @@ -4577,8 +4582,8 @@ or a 400 bad request error if the user is already authenticated. This endpoint is NOT INTENDED for clients that do not have a browser (Chrome, Firefox, ...) as cookies are needed. More information can be found at [Ory Kratos Account Recovery Documentation](../self-service/flows/account-recovery). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiInitializeSelfServiceRecoveryFlowForBrowsersRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiInitializeSelfServiceRecoveryFlowForBrowsersRequest */ func (a *V0alpha2ApiService) InitializeSelfServiceRecoveryFlowForBrowsers(ctx context.Context) V0alpha2ApiApiInitializeSelfServiceRecoveryFlowForBrowsersRequest { return V0alpha2ApiApiInitializeSelfServiceRecoveryFlowForBrowsersRequest{ @@ -4698,8 +4703,8 @@ func (r V0alpha2ApiApiInitializeSelfServiceRecoveryFlowWithoutBrowserRequest) Ex } /* - * InitializeSelfServiceRecoveryFlowWithoutBrowser Initialize Recovery Flow for APIs, Services, Apps, ... - * This endpoint initiates a recovery flow for API clients such as mobile devices, smart TVs, and so on. + - InitializeSelfServiceRecoveryFlowWithoutBrowser Initialize Recovery Flow for APIs, Services, Apps, ... + - This endpoint initiates a recovery flow for API clients such as mobile devices, smart TVs, and so on. If a valid provided session cookie or session token is provided, a 400 Bad Request error. @@ -4712,8 +4717,8 @@ you vulnerable to a variety of CSRF attacks. This endpoint MUST ONLY be used in scenarios such as native mobile apps (React Native, Objective C, Swift, Java, ...). More information can be found at [Ory Kratos Account Recovery Documentation](../self-service/flows/account-recovery). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiInitializeSelfServiceRecoveryFlowWithoutBrowserRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiInitializeSelfServiceRecoveryFlowWithoutBrowserRequest */ func (a *V0alpha2ApiService) InitializeSelfServiceRecoveryFlowWithoutBrowser(ctx context.Context) V0alpha2ApiApiInitializeSelfServiceRecoveryFlowWithoutBrowserRequest { return V0alpha2ApiApiInitializeSelfServiceRecoveryFlowWithoutBrowserRequest{ @@ -4836,8 +4841,9 @@ func (r V0alpha2ApiApiInitializeSelfServiceRegistrationFlowForBrowsersRequest) E } /* - * InitializeSelfServiceRegistrationFlowForBrowsers # Initialize Registration Flow for Browsers - * This endpoint initializes a browser-based user registration flow. This endpoint will set the appropriate + - InitializeSelfServiceRegistrationFlowForBrowsers # Initialize Registration Flow for Browsers + - This endpoint initializes a browser-based user registration flow. This endpoint will set the appropriate + cookies and anti-CSRF measures required for browser-based flows. :::info @@ -4862,8 +4868,8 @@ If this endpoint is called via an AJAX request, the response contains the regist This endpoint is NOT INTENDED for clients that do not have a browser (Chrome, Firefox, ...) as cookies are needed. More information can be found at [Ory Kratos User Login](https://www.ory.sh/docs/kratos/self-service/flows/user-login) and [User Registration Documentation](https://www.ory.sh/docs/kratos/self-service/flows/user-registration). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiInitializeSelfServiceRegistrationFlowForBrowsersRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiInitializeSelfServiceRegistrationFlowForBrowsersRequest */ func (a *V0alpha2ApiService) InitializeSelfServiceRegistrationFlowForBrowsers(ctx context.Context) V0alpha2ApiApiInitializeSelfServiceRegistrationFlowForBrowsersRequest { return V0alpha2ApiApiInitializeSelfServiceRegistrationFlowForBrowsersRequest{ @@ -4973,8 +4979,8 @@ func (r V0alpha2ApiApiInitializeSelfServiceRegistrationFlowWithoutBrowserRequest } /* - * InitializeSelfServiceRegistrationFlowWithoutBrowser Initialize Registration Flow for APIs, Services, Apps, ... - * This endpoint initiates a registration flow for API clients such as mobile devices, smart TVs, and so on. + - InitializeSelfServiceRegistrationFlowWithoutBrowser Initialize Registration Flow for APIs, Services, Apps, ... + - This endpoint initiates a registration flow for API clients such as mobile devices, smart TVs, and so on. If a valid provided session cookie or session token is provided, a 400 Bad Request error will be returned unless the URL query parameter `?refresh=true` is set. @@ -4993,8 +4999,8 @@ In the case of an error, the `error.id` of the JSON response body can be one of: This endpoint MUST ONLY be used in scenarios such as native mobile apps (React Native, Objective C, Swift, Java, ...). More information can be found at [Ory Kratos User Login](https://www.ory.sh/docs/kratos/self-service/flows/user-login) and [User Registration Documentation](https://www.ory.sh/docs/kratos/self-service/flows/user-registration). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiInitializeSelfServiceRegistrationFlowWithoutBrowserRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiInitializeSelfServiceRegistrationFlowWithoutBrowserRequest */ func (a *V0alpha2ApiService) InitializeSelfServiceRegistrationFlowWithoutBrowser(ctx context.Context) V0alpha2ApiApiInitializeSelfServiceRegistrationFlowWithoutBrowserRequest { return V0alpha2ApiApiInitializeSelfServiceRegistrationFlowWithoutBrowserRequest{ @@ -5122,8 +5128,9 @@ func (r V0alpha2ApiApiInitializeSelfServiceSettingsFlowForBrowsersRequest) Execu } /* - * InitializeSelfServiceSettingsFlowForBrowsers # Initialize Settings Flow for Browsers - * This endpoint initializes a browser-based user settings flow. Once initialized, the browser will be redirected to + - InitializeSelfServiceSettingsFlowForBrowsers # Initialize Settings Flow for Browsers + - This endpoint initializes a browser-based user settings flow. Once initialized, the browser will be redirected to + `selfservice.flows.settings.ui_url` with the flow ID set as the query parameter `?flow=`. If no valid Ory Kratos Session Cookie is included in the request, a login flow will be initialized. @@ -5149,8 +5156,8 @@ case of an error, the `error.id` of the JSON response body can be one of: This endpoint is NOT INTENDED for clients that do not have a browser (Chrome, Firefox, ...) as cookies are needed. More information can be found at [Ory Kratos User Settings & Profile Management Documentation](../self-service/flows/user-settings). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiInitializeSelfServiceSettingsFlowForBrowsersRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiInitializeSelfServiceSettingsFlowForBrowsersRequest */ func (a *V0alpha2ApiService) InitializeSelfServiceSettingsFlowForBrowsers(ctx context.Context) V0alpha2ApiApiInitializeSelfServiceSettingsFlowForBrowsersRequest { return V0alpha2ApiApiInitializeSelfServiceSettingsFlowForBrowsersRequest{ @@ -5299,8 +5306,9 @@ func (r V0alpha2ApiApiInitializeSelfServiceSettingsFlowWithoutBrowserRequest) Ex } /* - * InitializeSelfServiceSettingsFlowWithoutBrowser Initialize Settings Flow for APIs, Services, Apps, ... - * This endpoint initiates a settings flow for API clients such as mobile devices, smart TVs, and so on. + - InitializeSelfServiceSettingsFlowWithoutBrowser Initialize Settings Flow for APIs, Services, Apps, ... + - This endpoint initiates a settings flow for API clients such as mobile devices, smart TVs, and so on. + You must provide a valid Ory Kratos Session Token for this endpoint to respond with HTTP 200 OK. To fetch an existing settings flow call `/self-service/settings/flows?flow=`. @@ -5322,8 +5330,8 @@ In the case of an error, the `error.id` of the JSON response body can be one of: This endpoint MUST ONLY be used in scenarios such as native mobile apps (React Native, Objective C, Swift, Java, ...). More information can be found at [Ory Kratos User Settings & Profile Management Documentation](../self-service/flows/user-settings). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiInitializeSelfServiceSettingsFlowWithoutBrowserRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiInitializeSelfServiceSettingsFlowWithoutBrowserRequest */ func (a *V0alpha2ApiService) InitializeSelfServiceSettingsFlowWithoutBrowser(ctx context.Context) V0alpha2ApiApiInitializeSelfServiceSettingsFlowWithoutBrowserRequest { return V0alpha2ApiApiInitializeSelfServiceSettingsFlowWithoutBrowserRequest{ @@ -5449,8 +5457,9 @@ func (r V0alpha2ApiApiInitializeSelfServiceVerificationFlowForBrowsersRequest) E } /* - * InitializeSelfServiceVerificationFlowForBrowsers # Initialize Verification Flow for Browser Clients - * This endpoint initializes a browser-based account verification flow. Once initialized, the browser will be redirected to + - InitializeSelfServiceVerificationFlowForBrowsers # Initialize Verification Flow for Browser Clients + - This endpoint initializes a browser-based account verification flow. Once initialized, the browser will be redirected to + `selfservice.flows.verification.ui_url` with the flow ID set as the query parameter `?flow=`. If this endpoint is called via an AJAX request, the response contains the recovery flow without any redirects. @@ -5458,8 +5467,8 @@ If this endpoint is called via an AJAX request, the response contains the recove This endpoint is NOT INTENDED for API clients and only works with browsers (Chrome, Firefox, ...). More information can be found at [Ory Kratos Email and Phone Verification Documentation](https://www.ory.sh/docs/kratos/selfservice/flows/verify-email-account-activation). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiInitializeSelfServiceVerificationFlowForBrowsersRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiInitializeSelfServiceVerificationFlowForBrowsersRequest */ func (a *V0alpha2ApiService) InitializeSelfServiceVerificationFlowForBrowsers(ctx context.Context) V0alpha2ApiApiInitializeSelfServiceVerificationFlowForBrowsersRequest { return V0alpha2ApiApiInitializeSelfServiceVerificationFlowForBrowsersRequest{ @@ -5569,8 +5578,8 @@ func (r V0alpha2ApiApiInitializeSelfServiceVerificationFlowWithoutBrowserRequest } /* - * InitializeSelfServiceVerificationFlowWithoutBrowser Initialize Verification Flow for APIs, Services, Apps, ... - * This endpoint initiates a verification flow for API clients such as mobile devices, smart TVs, and so on. + - InitializeSelfServiceVerificationFlowWithoutBrowser Initialize Verification Flow for APIs, Services, Apps, ... + - This endpoint initiates a verification flow for API clients such as mobile devices, smart TVs, and so on. To fetch an existing verification flow call `/self-service/verification/flows?flow=`. @@ -5581,8 +5590,8 @@ you vulnerable to a variety of CSRF attacks. This endpoint MUST ONLY be used in scenarios such as native mobile apps (React Native, Objective C, Swift, Java, ...). More information can be found at [Ory Kratos Email and Phone Verification Documentation](https://www.ory.sh/docs/kratos/self-service/flows/verify-email-account-activation). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiInitializeSelfServiceVerificationFlowWithoutBrowserRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiInitializeSelfServiceVerificationFlowWithoutBrowserRequest */ func (a *V0alpha2ApiService) InitializeSelfServiceVerificationFlowWithoutBrowser(ctx context.Context) V0alpha2ApiApiInitializeSelfServiceVerificationFlowWithoutBrowserRequest { return V0alpha2ApiApiInitializeSelfServiceVerificationFlowWithoutBrowserRequest{ @@ -5847,12 +5856,12 @@ func (r V0alpha2ApiApiListSessionsRequest) Execute() ([]Session, *http.Response, } /* - * ListSessions This endpoints returns all other active sessions that belong to the logged-in user. The current session can be retrieved by calling the `/sessions/whoami` endpoint. - * This endpoint is useful for: + - ListSessions This endpoints returns all other active sessions that belong to the logged-in user. The current session can be retrieved by calling the `/sessions/whoami` endpoint. + - This endpoint is useful for: Displaying all other sessions that belong to the logged-in user - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiListSessionsRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiListSessionsRequest */ func (a *V0alpha2ApiService) ListSessions(ctx context.Context) V0alpha2ApiApiListSessionsRequest { return V0alpha2ApiApiListSessionsRequest{ @@ -6002,13 +6011,13 @@ func (r V0alpha2ApiApiRevokeSessionRequest) Execute() (*http.Response, error) { } /* - * RevokeSession Calling this endpoint invalidates the specified session. The current session cannot be revoked. Session data are not deleted. - * This endpoint is useful for: + - RevokeSession Calling this endpoint invalidates the specified session. The current session cannot be revoked. Session data are not deleted. + - This endpoint is useful for: To forcefully logout the current user from another device or session - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @param id ID is the session's ID. - * @return V0alpha2ApiApiRevokeSessionRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param id ID is the session's ID. + - @return V0alpha2ApiApiRevokeSessionRequest */ func (a *V0alpha2ApiService) RevokeSession(ctx context.Context, id string) V0alpha2ApiApiRevokeSessionRequest { return V0alpha2ApiApiRevokeSessionRequest{ @@ -6137,12 +6146,12 @@ func (r V0alpha2ApiApiRevokeSessionsRequest) Execute() (*RevokedSessions, *http. } /* - * RevokeSessions Calling this endpoint invalidates all except the current session that belong to the logged-in user. Session data are not deleted. - * This endpoint is useful for: + - RevokeSessions Calling this endpoint invalidates all except the current session that belong to the logged-in user. Session data are not deleted. + - This endpoint is useful for: To forcefully logout the current user from all other devices and sessions - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiRevokeSessionsRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiRevokeSessionsRequest */ func (a *V0alpha2ApiService) RevokeSessions(ctx context.Context) V0alpha2ApiApiRevokeSessionsRequest { return V0alpha2ApiApiRevokeSessionsRequest{ @@ -6306,8 +6315,8 @@ func (r V0alpha2ApiApiSubmitSelfServiceLoginFlowRequest) Execute() (*SuccessfulS } /* - * SubmitSelfServiceLoginFlow # Submit a Login Flow - * :::info + - SubmitSelfServiceLoginFlow # Submit a Login Flow + - :::info This endpoint is EXPERIMENTAL and subject to potential breaking changes in the future. @@ -6340,8 +6349,8 @@ case of an error, the `error.id` of the JSON response body can be one of: Most likely used in Social Sign In flows. More information can be found at [Ory Kratos User Login](https://www.ory.sh/docs/kratos/self-service/flows/user-login) and [User Registration Documentation](https://www.ory.sh/docs/kratos/self-service/flows/user-registration). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiSubmitSelfServiceLoginFlowRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiSubmitSelfServiceLoginFlowRequest */ func (a *V0alpha2ApiService) SubmitSelfServiceLoginFlow(ctx context.Context) V0alpha2ApiApiSubmitSelfServiceLoginFlowRequest { return V0alpha2ApiApiSubmitSelfServiceLoginFlowRequest{ @@ -6504,8 +6513,8 @@ func (r V0alpha2ApiApiSubmitSelfServiceLogoutFlowRequest) Execute() (*http.Respo } /* - * SubmitSelfServiceLogoutFlow # Complete Self-Service Logout - * This endpoint logs out an identity in a self-service manner. + - SubmitSelfServiceLogoutFlow # Complete Self-Service Logout + - This endpoint logs out an identity in a self-service manner. If the `Accept` HTTP header is not set to `application/json`, the browser will be redirected (HTTP 303 See Other) to the `return_to` parameter of the initial request or fall back to `urls.default_return_to`. @@ -6518,8 +6527,8 @@ with browsers (Chrome, Firefox, ...). For API clients you can call the `/self-service/logout/api` URL directly with the Ory Session Token. More information can be found at [Ory Kratos User Logout Documentation](https://www.ory.sh/docs/next/kratos/self-service/flows/user-logout). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiSubmitSelfServiceLogoutFlowRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiSubmitSelfServiceLogoutFlowRequest */ func (a *V0alpha2ApiService) SubmitSelfServiceLogoutFlow(ctx context.Context) V0alpha2ApiApiSubmitSelfServiceLogoutFlowRequest { return V0alpha2ApiApiSubmitSelfServiceLogoutFlowRequest{ @@ -6627,8 +6636,9 @@ func (r V0alpha2ApiApiSubmitSelfServiceLogoutFlowWithoutBrowserRequest) Execute( } /* - * SubmitSelfServiceLogoutFlowWithoutBrowser Perform Logout for APIs, Services, Apps, ... - * Use this endpoint to log out an identity using an Ory Session Token. If the Ory Session Token was successfully + - SubmitSelfServiceLogoutFlowWithoutBrowser Perform Logout for APIs, Services, Apps, ... + - Use this endpoint to log out an identity using an Ory Session Token. If the Ory Session Token was successfully + revoked, the server returns a 204 No Content response. A 204 No Content response is also sent when the Ory Session Token has been revoked already before. @@ -6636,8 +6646,8 @@ If the Ory Session Token is malformed or does not exist a 403 Forbidden response This endpoint does not remove any HTTP Cookies - use the Browser-Based Self-Service Logout Flow instead. - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiSubmitSelfServiceLogoutFlowWithoutBrowserRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiSubmitSelfServiceLogoutFlowWithoutBrowserRequest */ func (a *V0alpha2ApiService) SubmitSelfServiceLogoutFlowWithoutBrowser(ctx context.Context) V0alpha2ApiApiSubmitSelfServiceLogoutFlowWithoutBrowserRequest { return V0alpha2ApiApiSubmitSelfServiceLogoutFlowWithoutBrowserRequest{ @@ -6769,8 +6779,9 @@ func (r V0alpha2ApiApiSubmitSelfServiceRecoveryFlowRequest) Execute() (*SelfServ } /* - * SubmitSelfServiceRecoveryFlow # Complete Recovery Flow - * Use this endpoint to complete a recovery flow. This endpoint + - SubmitSelfServiceRecoveryFlow # Complete Recovery Flow + - Use this endpoint to complete a recovery flow. This endpoint + behaves differently for API and browser flows and has several states: `choose_method` expects `flow` (in the URL query) and `email` (in the body) to be sent @@ -6786,8 +6797,8 @@ does not have any API capabilities. The server responds with a HTTP 303 See Othe a new Recovery Flow ID which contains an error message that the recovery link was invalid. More information can be found at [Ory Kratos Account Recovery Documentation](../self-service/flows/account-recovery). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiSubmitSelfServiceRecoveryFlowRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiSubmitSelfServiceRecoveryFlowRequest */ func (a *V0alpha2ApiService) SubmitSelfServiceRecoveryFlow(ctx context.Context) V0alpha2ApiApiSubmitSelfServiceRecoveryFlowRequest { return V0alpha2ApiApiSubmitSelfServiceRecoveryFlowRequest{ @@ -6945,8 +6956,9 @@ func (r V0alpha2ApiApiSubmitSelfServiceRegistrationFlowRequest) Execute() (*Succ } /* - * SubmitSelfServiceRegistrationFlow # Submit a Registration Flow - * Use this endpoint to complete a registration flow by sending an identity's traits and password. This endpoint + - SubmitSelfServiceRegistrationFlow # Submit a Registration Flow + - Use this endpoint to complete a registration flow by sending an identity's traits and password. This endpoint + behaves differently for API and browser flows. API flows expect `application/json` to be sent in the body and respond with @@ -6974,8 +6986,8 @@ case of an error, the `error.id` of the JSON response body can be one of: Most likely used in Social Sign In flows. More information can be found at [Ory Kratos User Login](https://www.ory.sh/docs/kratos/self-service/flows/user-login) and [User Registration Documentation](https://www.ory.sh/docs/kratos/self-service/flows/user-registration). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiSubmitSelfServiceRegistrationFlowRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiSubmitSelfServiceRegistrationFlowRequest */ func (a *V0alpha2ApiService) SubmitSelfServiceRegistrationFlow(ctx context.Context) V0alpha2ApiApiSubmitSelfServiceRegistrationFlowRequest { return V0alpha2ApiApiSubmitSelfServiceRegistrationFlowRequest{ @@ -7145,8 +7157,9 @@ func (r V0alpha2ApiApiSubmitSelfServiceSettingsFlowRequest) Execute() (*SelfServ } /* - * SubmitSelfServiceSettingsFlow # Complete Settings Flow - * Use this endpoint to complete a settings flow by sending an identity's updated password. This endpoint + - SubmitSelfServiceSettingsFlow # Complete Settings Flow + - Use this endpoint to complete a settings flow by sending an identity's updated password. This endpoint + behaves differently for API and browser flows. API-initiated flows expect `application/json` to be sent in the body and respond with @@ -7189,8 +7202,8 @@ identity logged in instead. Most likely used in Social Sign In flows. More information can be found at [Ory Kratos User Settings & Profile Management Documentation](../self-service/flows/user-settings). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiSubmitSelfServiceSettingsFlowRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiSubmitSelfServiceSettingsFlowRequest */ func (a *V0alpha2ApiService) SubmitSelfServiceSettingsFlow(ctx context.Context) V0alpha2ApiApiSubmitSelfServiceSettingsFlowRequest { return V0alpha2ApiApiSubmitSelfServiceSettingsFlowRequest{ @@ -7383,8 +7396,9 @@ func (r V0alpha2ApiApiSubmitSelfServiceVerificationFlowRequest) Execute() (*Self } /* - * SubmitSelfServiceVerificationFlow # Complete Verification Flow - * Use this endpoint to complete a verification flow. This endpoint + - SubmitSelfServiceVerificationFlow # Complete Verification Flow + - Use this endpoint to complete a verification flow. This endpoint + behaves differently for API and browser flows and has several states: `choose_method` expects `flow` (in the URL query) and `email` (in the body) to be sent @@ -7400,8 +7414,8 @@ does not have any API capabilities. The server responds with a HTTP 303 See Othe a new Verification Flow ID which contains an error message that the verification link was invalid. More information can be found at [Ory Kratos Email and Phone Verification Documentation](https://www.ory.sh/docs/kratos/selfservice/flows/verify-email-account-activation). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiSubmitSelfServiceVerificationFlowRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiSubmitSelfServiceVerificationFlowRequest */ func (a *V0alpha2ApiService) SubmitSelfServiceVerificationFlow(ctx context.Context) V0alpha2ApiApiSubmitSelfServiceVerificationFlowRequest { return V0alpha2ApiApiSubmitSelfServiceVerificationFlowRequest{ @@ -7554,8 +7568,9 @@ func (r V0alpha2ApiApiToSessionRequest) Execute() (*Session, *http.Response, err } /* - * ToSession # Check Who the Current HTTP Session Belongs To - * Uses the HTTP Headers in the GET request to determine (e.g. by using checking the cookies) who is authenticated. + - ToSession # Check Who the Current HTTP Session Belongs To + - Uses the HTTP Headers in the GET request to determine (e.g. by using checking the cookies) who is authenticated. + Returns a session object in the body or 401 if the credentials are invalid or no credentials were sent. Additionally when the request it successful it adds the user ID to the 'X-Kratos-Authenticated-Identity-Id' header in the response. @@ -7604,8 +7619,8 @@ As explained above, this request may fail due to several reasons. The `error.id` `session_inactive`: No active session was found in the request (e.g. no Ory Session Cookie / Ory Session Token). `session_aal2_required`: An active session was found but it does not fulfil the Authenticator Assurance Level, implying that the session must (e.g.) authenticate the second factor. - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return V0alpha2ApiApiToSessionRequest + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return V0alpha2ApiApiToSessionRequest */ func (a *V0alpha2ApiService) ToSession(ctx context.Context) V0alpha2ApiApiToSessionRequest { return V0alpha2ApiApiToSessionRequest{ diff --git a/package-lock.json b/package-lock.json index 4d6d08500f34..20bc1051908a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,9 +16,9 @@ "cypress": "^9.5.1", "dayjs": "^1.10.4", "got": "^11.8.2", - "ory-prettier-styles": "1.1.2", + "ory-prettier-styles": "1.3.0", "otplib": "^12.0.1", - "prettier": "^2.7.1", + "prettier": "2.7.1", "prettier-plugin-packagejson": "^2.2.18", "typescript": "^4.4.3", "wait-on": "5.3.0" @@ -2416,9 +2416,9 @@ } }, "node_modules/ory-prettier-styles": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/ory-prettier-styles/-/ory-prettier-styles-1.1.2.tgz", - "integrity": "sha512-J7YcNdGlfTKCXAHEoFl9lp5EhnIASGgM5ua9Y+8OdWtS9tXJTik5xFYCF6xS46tpI3sk8cxFguKWhZeaeb6Z/A==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ory-prettier-styles/-/ory-prettier-styles-1.3.0.tgz", + "integrity": "sha512-Vfn0G6CyLaadwcCamwe1SQCf37ZQfBDgMrhRI70dE/2fbE3Q43/xu7K5c32I5FGt/EliroWty5yBjmdkj0eWug==", "dev": true }, "node_modules/os-tmpdir": { @@ -5129,9 +5129,9 @@ } }, "ory-prettier-styles": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/ory-prettier-styles/-/ory-prettier-styles-1.1.2.tgz", - "integrity": "sha512-J7YcNdGlfTKCXAHEoFl9lp5EhnIASGgM5ua9Y+8OdWtS9tXJTik5xFYCF6xS46tpI3sk8cxFguKWhZeaeb6Z/A==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ory-prettier-styles/-/ory-prettier-styles-1.3.0.tgz", + "integrity": "sha512-Vfn0G6CyLaadwcCamwe1SQCf37ZQfBDgMrhRI70dE/2fbE3Q43/xu7K5c32I5FGt/EliroWty5yBjmdkj0eWug==", "dev": true }, "os-tmpdir": { @@ -5737,7 +5737,8 @@ "version": "7.5.7", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", - "dev": true + "dev": true, + "requires": {} }, "y18n": { "version": "5.0.8", diff --git a/package.json b/package.json index e4a8e60b2627..81f8e1fef445 100644 --- a/package.json +++ b/package.json @@ -20,9 +20,9 @@ "cypress": "^9.5.1", "dayjs": "^1.10.4", "got": "^11.8.2", - "ory-prettier-styles": "1.1.2", + "ory-prettier-styles": "1.3.0", "otplib": "^12.0.1", - "prettier": "^2.7.1", + "prettier": "2.7.1", "prettier-plugin-packagejson": "^2.2.18", "typescript": "^4.4.3", "wait-on": "5.3.0" diff --git a/test/e2e/cypress.config.ts b/test/e2e/cypress.config.ts index a9a55def40b6..1e2c0e612114 100644 --- a/test/e2e/cypress.config.ts +++ b/test/e2e/cypress.config.ts @@ -1,6 +1,6 @@ -import { defineConfig } from 'cypress' -import got from 'got' -const CRI = require('chrome-remote-interface') +import { defineConfig } from "cypress" +import got from "got" +const CRI = require("chrome-remote-interface") let criPort = 0, criClient = null @@ -8,28 +8,28 @@ export default defineConfig({ chromeWebSecurity: false, defaultCommandTimeout: 10000, requestTimeout: 10000, - projectId: 'bc48bg', + projectId: "bc48bg", video: true, videoCompression: false, screenshotOnRunFailure: true, e2e: { retries: { runMode: 6, - openMode: 1 + openMode: 1, }, - videosFolder: 'cypress/videos', - screenshotsFolder: 'cypress/screenshots', - excludeSpecPattern: '**/*snapshots.js', - supportFile: 'cypress/support/index.js', - specPattern: '**/*.spec.{js,ts}', - baseUrl: 'http://localhost:4455/', + videosFolder: "cypress/videos", + screenshotsFolder: "cypress/screenshots", + excludeSpecPattern: "**/*snapshots.js", + supportFile: "cypress/support/index.js", + specPattern: "**/*.spec.{js,ts}", + baseUrl: "http://localhost:4455/", setupNodeEvents(on, config) { - on('before:browser:launch', (browser, args) => { + on("before:browser:launch", (browser, args) => { criPort = ensureRdpPort(args.args) - console.log('criPort is', criPort) + console.log("criPort is", criPort) }) - on('task', { + on("task", { httpRequest(params) { return got(params).then(({ body }) => body) }, @@ -50,19 +50,19 @@ export default defineConfig({ } return criClient.send(args.query, args.opts) - } + }, }) - } - } + }, + }, }) function ensureRdpPort(args) { const existing = args.find( - (arg) => arg.slice(0, 23) === '--remote-debugging-port' + (arg) => arg.slice(0, 23) === "--remote-debugging-port", ) if (existing) { - return Number(existing.split('=')[1]) + return Number(existing.split("=")[1]) } const port = 40000 + Math.round(Math.random() * 25000) diff --git a/test/e2e/cypress/helpers/express.ts b/test/e2e/cypress/helpers/express.ts index cb8ea52292cc..51bd49f35439 100644 --- a/test/e2e/cypress/helpers/express.ts +++ b/test/e2e/cypress/helpers/express.ts @@ -1,10 +1,10 @@ -import { APP_URL, SPA_URL } from './index' +import { APP_URL, SPA_URL } from "./index" export const routes = { base: APP_URL, - login: APP_URL + '/login', - registration: APP_URL + '/registration', - settings: APP_URL + '/settings', - recovery: APP_URL + '/recovery', - verification: APP_URL + '/verification' + login: APP_URL + "/login", + registration: APP_URL + "/registration", + settings: APP_URL + "/settings", + recovery: APP_URL + "/recovery", + verification: APP_URL + "/verification", } diff --git a/test/e2e/cypress/helpers/index.ts b/test/e2e/cypress/helpers/index.ts index 439ec483414b..48e365e381a8 100644 --- a/test/e2e/cypress/helpers/index.ts +++ b/test/e2e/cypress/helpers/index.ts @@ -1,6 +1,6 @@ -export const email = () => Math.random().toString(36) + '@ory.sh' +export const email = () => Math.random().toString(36) + "@ory.sh" export const blockedEmail = () => - Math.random().toString(36) + '_blocked' + '@ory.sh' + Math.random().toString(36) + "_blocked" + "@ory.sh" export const password = () => Math.random().toString(36) @@ -8,7 +8,7 @@ export const assertVerifiableAddress = ({ isVerified, email }) => (session) => { const { identity } = session - expect(identity).to.have.property('verifiable_addresses') + expect(identity).to.have.property("verifiable_addresses") expect(identity.verifiable_addresses).to.have.length(1) const address = identity.verifiable_addresses[0] @@ -19,14 +19,14 @@ export const assertVerifiableAddress = if (isVerified) { expect(address.verified_at).to.not.be.null } else { - expect(address).to.not.have.property('verified_at') + expect(address).to.not.have.property("verified_at") } } export const assertRecoveryAddress = ({ email }) => ({ identity }) => { - expect(identity).to.have.property('recovery_addresses') + expect(identity).to.have.property("recovery_addresses") expect(identity.recovery_addresses).to.have.length(1) const address = identity.recovery_addresses[0] @@ -35,35 +35,35 @@ export const assertRecoveryAddress = } export const parseHtml = (html) => - new DOMParser().parseFromString(html, 'text/html') + new DOMParser().parseFromString(html, "text/html") export const APP_URL = ( - Cypress.env('app_url') || 'http://localhost:4455' -).replace(/\/$/, '') + Cypress.env("app_url") || "http://localhost:4455" +).replace(/\/$/, "") export const MOBILE_URL = ( - Cypress.env('mobile_url') || 'http://localhost:4457' -).replace(/\/$/, '') + Cypress.env("mobile_url") || "http://localhost:4457" +).replace(/\/$/, "") export const SPA_URL = ( - Cypress.env('react_url') || 'http://localhost:4455' -).replace(/\/$/, '') + Cypress.env("react_url") || "http://localhost:4455" +).replace(/\/$/, "") export const KRATOS_ADMIN = ( - Cypress.env('kratos_admin') || 'http://localhost:4434' + Cypress.env("kratos_admin") || "http://localhost:4434" ) .replace() - .replace(/\/$/, '') + .replace(/\/$/, "") export const KRATOS_PUBLIC = ( - Cypress.env('kratos_public') || 'http://localhost:4433' + Cypress.env("kratos_public") || "http://localhost:4433" ) .replace() - .replace(/\/$/, '') + .replace(/\/$/, "") export const MAIL_API = ( - Cypress.env('mail_url') || 'http://localhost:4437' -).replace(/\/$/, '') + Cypress.env("mail_url") || "http://localhost:4437" +).replace(/\/$/, "") -export const website = 'https://www.ory.sh/' +export const website = "https://www.ory.sh/" export const gen = { email, @@ -73,8 +73,8 @@ export const gen = { identityWithWebsite: () => ({ email: email(), password: password(), - fields: { 'traits.website': 'https://www.ory.sh' } - }) + fields: { "traits.website": "https://www.ory.sh" }, + }), } // Format is diff --git a/test/e2e/cypress/helpers/react.ts b/test/e2e/cypress/helpers/react.ts index 26cc97230180..e5a3fd4e5d61 100644 --- a/test/e2e/cypress/helpers/react.ts +++ b/test/e2e/cypress/helpers/react.ts @@ -1,10 +1,10 @@ -import { SPA_URL } from './index' +import { SPA_URL } from "./index" export const routes = { base: SPA_URL, - login: SPA_URL + '/login', - registration: SPA_URL + '/registration', - settings: SPA_URL + '/settings', - recovery: SPA_URL + '/recovery', - verification: SPA_URL + '/verification' + login: SPA_URL + "/login", + registration: SPA_URL + "/registration", + settings: SPA_URL + "/settings", + recovery: SPA_URL + "/recovery", + verification: SPA_URL + "/verification", } diff --git a/test/e2e/cypress/integration/profiles/email/error/ui.spec.ts b/test/e2e/cypress/integration/profiles/email/error/ui.spec.ts index be7bb5d407d6..d2e8874d364b 100644 --- a/test/e2e/cypress/integration/profiles/email/error/ui.spec.ts +++ b/test/e2e/cypress/integration/profiles/email/error/ui.spec.ts @@ -1,19 +1,19 @@ -import { routes as express } from '../../../../helpers/express' -import { routes as react } from '../../../../helpers/react' -import { appPrefix } from '../../../../helpers' +import { routes as express } from "../../../../helpers/express" +import { routes as react } from "../../../../helpers/react" +import { appPrefix } from "../../../../helpers" -describe('Handling self-service error flows', () => { +describe("Handling self-service error flows", () => { ;[ { route: express.base, - app: 'express' as 'express', - profile: 'email' + app: "express" as "express", + profile: "email", }, { route: react.base, - app: 'react' as 'react', - profile: 'spa' - } + app: "react" as "react", + profile: "spa", + }, ].forEach(({ route, app, profile }) => { describe(`for app ${app}`, () => { before(() => { @@ -21,14 +21,14 @@ describe('Handling self-service error flows', () => { cy.proxy(app) }) - it('should show the error', () => { + it("should show the error", () => { cy.visit(`${route}/error?id=stub:500`, { - failOnStatusCode: false + failOnStatusCode: false, }) cy.get(`${appPrefix(app)}code`).should( - 'contain.text', - 'This is a stub error.' + "contain.text", + "This is a stub error.", ) }) }) diff --git a/test/e2e/cypress/integration/profiles/email/login/error.spec.ts b/test/e2e/cypress/integration/profiles/email/login/error.spec.ts index 90873f9cb882..58cd061a0a74 100644 --- a/test/e2e/cypress/integration/profiles/email/login/error.spec.ts +++ b/test/e2e/cypress/integration/profiles/email/login/error.spec.ts @@ -1,19 +1,19 @@ -import { appPrefix, gen } from '../../../../helpers' -import { routes as express } from '../../../../helpers/express' -import { routes as react } from '../../../../helpers/react' +import { appPrefix, gen } from "../../../../helpers" +import { routes as express } from "../../../../helpers/express" +import { routes as react } from "../../../../helpers/react" -describe('Basic email profile with failing login flows', () => { +describe("Basic email profile with failing login flows", () => { ;[ { route: express.login, - app: 'express' as 'express', - profile: 'email' + app: "express" as "express", + profile: "email", }, { route: react.login, - app: 'react' as 'react', - profile: 'spa' - } + app: "react" as "react", + profile: "spa", + }, ].forEach(({ route, profile, app }) => { describe(`for app ${app}`, () => { before(() => { @@ -26,60 +26,60 @@ describe('Basic email profile with failing login flows', () => { cy.visit(route) }) - it('fails when CSRF cookies are missing', () => { + it("fails when CSRF cookies are missing", () => { cy.get(`${appPrefix(app)}input[name="identifier"]`).type( - 'i-do-not-exist' + "i-do-not-exist", ) - cy.get('input[name="password"]').type('invalid-password') + cy.get('input[name="password"]').type("invalid-password") cy.shouldHaveCsrfError({ app }) }) - it('fails when a disallowed return_to url is requested', () => { + it("fails when a disallowed return_to url is requested", () => { cy.shouldErrorOnDisallowedReturnTo( - route + '?return_to=https://not-allowed', - { app } + route + "?return_to=https://not-allowed", + { app }, ) }) - describe('shows validation errors when invalid signup data is used', () => { - it('should show an error when the identifier is missing', () => { + describe("shows validation errors when invalid signup data is used", () => { + it("should show an error when the identifier is missing", () => { cy.submitPasswordForm() cy.get('*[data-testid="ui/message/4000002"]').should( - 'contain.text', - 'Property identifier is missing' + "contain.text", + "Property identifier is missing", ) cy.get('*[data-testid="ui/message/4000002"]').should( - 'contain.text', - 'Property password is missing' + "contain.text", + "Property password is missing", ) }) - it('should show an error when the password is missing', () => { + it("should show an error when the password is missing", () => { const identity = gen.email() cy.get('input[name="identifier"]') .type(identity) - .should('have.value', identity) + .should("have.value", identity) cy.submitPasswordForm() cy.get('*[data-testid^="ui/message/"]') - .invoke('text') + .invoke("text") .then((text) => { expect(text).to.be.oneOf([ - 'length must be >= 1, but got 0', - 'Property password is missing.' + "length must be >= 1, but got 0", + "Property password is missing.", ]) }) }) - it('should show fail to sign in', () => { - cy.get('input[name="identifier"]').type('i-do-not-exist') - cy.get('input[name="password"]').type('invalid-password') + it("should show fail to sign in", () => { + cy.get('input[name="identifier"]').type("i-do-not-exist") + cy.get('input[name="password"]').type("invalid-password") cy.submitPasswordForm() cy.get('*[data-testid="ui/message/4000006"]').should( - 'contain.text', - 'credentials are invalid' + "contain.text", + "credentials are invalid", ) }) }) diff --git a/test/e2e/cypress/integration/profiles/email/login/success.spec.ts b/test/e2e/cypress/integration/profiles/email/login/success.spec.ts index 4a8c5f846f6f..d3244366b63f 100644 --- a/test/e2e/cypress/integration/profiles/email/login/success.spec.ts +++ b/test/e2e/cypress/integration/profiles/email/login/success.spec.ts @@ -1,25 +1,25 @@ -import { APP_URL, appPrefix, gen, website } from '../../../../helpers' -import { routes as express } from '../../../../helpers/express' -import { routes as react } from '../../../../helpers/react' +import { APP_URL, appPrefix, gen, website } from "../../../../helpers" +import { routes as express } from "../../../../helpers/express" +import { routes as react } from "../../../../helpers/react" -describe('Basic email profile with succeeding login flows', () => { +describe("Basic email profile with succeeding login flows", () => { const email = gen.email() const password = gen.password() before(() => { - cy.registerApi({ email, password, fields: { 'traits.website': website } }) + cy.registerApi({ email, password, fields: { "traits.website": website } }) }) ;[ { route: express.login, - app: 'express' as 'express', - profile: 'email' + app: "express" as "express", + profile: "email", }, { route: react.login, - app: 'react' as 'react', - profile: 'spa' - } + app: "react" as "react", + profile: "spa", + }, ].forEach(({ route, profile, app }) => { describe(`for app ${app}`, () => { before(() => { @@ -32,57 +32,57 @@ describe('Basic email profile with succeeding login flows', () => { cy.visit(route) }) - it('should sign in and be logged in', () => { + it("should sign in and be logged in", () => { cy.get(`${appPrefix(app)}input[name="identifier"]`).type(email) cy.get('input[name="password"]').type(password) cy.submitPasswordForm() - cy.location('pathname').should('not.contain', '/login') + cy.location("pathname").should("not.contain", "/login") cy.getSession().should((session) => { const { identity } = session expect(identity.id).to.not.be.empty - expect(identity.schema_id).to.equal('default') + expect(identity.schema_id).to.equal("default") expect(identity.schema_url).to.equal(`${APP_URL}/schemas/ZGVmYXVsdA`) expect(identity.traits.website).to.equal(website) expect(identity.traits.email).to.equal(email) }) }) - it('should sign in with case insensitive identifier surrounded by whitespace', () => { + it("should sign in with case insensitive identifier surrounded by whitespace", () => { cy.get('input[name="identifier"]').type( - ' ' + email.toUpperCase() + ' ' + " " + email.toUpperCase() + " ", ) cy.get('input[name="password"]').type(password) cy.submitPasswordForm() - cy.location('pathname').should('not.contain', '/login') + cy.location("pathname").should("not.contain", "/login") cy.getSession().should((session) => { const { identity } = session expect(identity.id).to.not.be.empty - expect(identity.schema_id).to.equal('default') + expect(identity.schema_id).to.equal("default") expect(identity.schema_url).to.equal(`${APP_URL}/schemas/ZGVmYXVsdA`) expect(identity.traits.website).to.equal(website) expect(identity.traits.email).to.equal(email) }) }) - it('should sign in and be redirected', () => { + it("should sign in and be redirected", () => { cy.browserReturnUrlOry() - cy.visit(route + '?return_to=https://www.example.org/') + cy.visit(route + "?return_to=https://www.example.org/") cy.get('input[name="identifier"]').type(email.toUpperCase()) cy.get('input[name="password"]').type(password) cy.submitPasswordForm() - cy.url().should('eq', 'https://www.example.org/') + cy.url().should("eq", "https://www.example.org/") }) }) }) - describe('for app express handle return_to correctly for expired flows', () => { + describe("for app express handle return_to correctly for expired flows", () => { before(() => { - cy.proxy('express') - cy.useConfigProfile('email') + cy.proxy("express") + cy.useConfigProfile("email") cy.browserReturnUrlOry() }) @@ -91,23 +91,23 @@ describe('Basic email profile with succeeding login flows', () => { cy.clearAllCookies() }) - it('should redirect to return_to when retrying expired flow', () => { + it("should redirect to return_to when retrying expired flow", () => { cy.shortLoginLifespan() cy.wait(500) - cy.visit(express.login + '?return_to=https://www.example.org/') + cy.visit(express.login + "?return_to=https://www.example.org/") cy.longLoginLifespan() - cy.get(appPrefix('express') + 'input[name="identifier"]').type( - email.toUpperCase() + cy.get(appPrefix("express") + 'input[name="identifier"]').type( + email.toUpperCase(), ) cy.get('input[name="password"]').type(password) cy.submitPasswordForm() cy.get('[data-testid="ui/message/4010001"]').should( - 'contain.text', - 'The login flow expired' + "contain.text", + "The login flow expired", ) // try again with long lifespan set @@ -116,7 +116,7 @@ describe('Basic email profile with succeeding login flows', () => { cy.submitPasswordForm() // check that redirection has happened - cy.url().should('eq', 'https://www.example.org/') + cy.url().should("eq", "https://www.example.org/") }) }) }) diff --git a/test/e2e/cypress/integration/profiles/email/login/ui.spec.ts b/test/e2e/cypress/integration/profiles/email/login/ui.spec.ts index 883a7f9a28d9..b8293fc01889 100644 --- a/test/e2e/cypress/integration/profiles/email/login/ui.spec.ts +++ b/test/e2e/cypress/integration/profiles/email/login/ui.spec.ts @@ -1,19 +1,19 @@ -import { routes as express } from '../../../../helpers/express' -import { routes as react } from '../../../../helpers/react' -import { appPrefix } from '../../../../helpers' +import { routes as express } from "../../../../helpers/express" +import { routes as react } from "../../../../helpers/react" +import { appPrefix } from "../../../../helpers" -context('UI tests using the email profile', () => { +context("UI tests using the email profile", () => { ;[ { route: express.login, - app: 'express' as 'express', - profile: 'email' + app: "express" as "express", + profile: "email", }, { route: react.login, - app: 'react' as 'react', - profile: 'spa' - } + app: "react" as "react", + profile: "spa", + }, ].forEach(({ route, profile, app }) => { describe(`for app ${app}`, () => { before(() => { @@ -25,22 +25,22 @@ context('UI tests using the email profile', () => { cy.visit(route) }) - it('should use the json schema titles', () => { + it("should use the json schema titles", () => { cy.get(`${appPrefix(app)}input[name="identifier"]`) .parent() - .should('contain.text', 'ID') + .should("contain.text", "ID") cy.get('input[name="password"]') .parent() - .should('contain.text', 'Password') - cy.get('button[value="password"]').should('contain.text', 'Sign in') + .should("contain.text", "Password") + cy.get('button[value="password"]').should("contain.text", "Sign in") }) - it('clicks the log in link', () => { + it("clicks the log in link", () => { cy.get('a[href*="registration"]').click() - cy.location('pathname').should('include', 'registration') + cy.location("pathname").should("include", "registration") - if (app === 'express') { - cy.location('search').should('not.be.empty') + if (app === "express") { + cy.location("search").should("not.be.empty") } }) }) diff --git a/test/e2e/cypress/integration/profiles/email/logout/success.spec.ts b/test/e2e/cypress/integration/profiles/email/logout/success.spec.ts index 03c3a3ecb85b..946301f9941f 100644 --- a/test/e2e/cypress/integration/profiles/email/logout/success.spec.ts +++ b/test/e2e/cypress/integration/profiles/email/logout/success.spec.ts @@ -1,19 +1,19 @@ -import { appPrefix, gen, website } from '../../../../helpers' -import { routes as express } from '../../../../helpers/express' -import { routes as react } from '../../../../helpers/react' +import { appPrefix, gen, website } from "../../../../helpers" +import { routes as express } from "../../../../helpers/express" +import { routes as react } from "../../../../helpers/react" -context('Testing logout flows', () => { +context("Testing logout flows", () => { ;[ { route: express.login, - app: 'express' as 'express', - profile: 'email' + app: "express" as "express", + profile: "email", }, { route: react.login, - app: 'react' as 'react', - profile: 'spa' - } + app: "react" as "react", + profile: "spa", + }, ].forEach(({ route, profile, app }) => { describe(`for app ${app}`, () => { const email = gen.email() @@ -26,7 +26,7 @@ context('Testing logout flows', () => { cy.registerApi({ email, password, - fields: { 'traits.website': website } + fields: { "traits.website": website }, }) }) @@ -36,15 +36,15 @@ context('Testing logout flows', () => { cy.visit(route) }) - it('should sign out and be able to sign in again', () => { + it("should sign out and be able to sign in again", () => { cy.getSession() - cy.getCookie('ory_kratos_session').should('not.be.null') + cy.getCookie("ory_kratos_session").should("not.be.null") cy.get( - `${appPrefix(app)} [data-testid="logout"]:not(.disabled)` + `${appPrefix(app)} [data-testid="logout"]:not(.disabled)`, ).click() cy.noSession() - cy.url().should('include', '/login') - cy.getCookie('ory_kratos_session').should('be.null') + cy.url().should("include", "/login") + cy.getCookie("ory_kratos_session").should("be.null") }) }) }) diff --git a/test/e2e/cypress/integration/profiles/email/registration/errors.spec.ts b/test/e2e/cypress/integration/profiles/email/registration/errors.spec.ts index 5be1bac5aafb..9c6559c5dc42 100644 --- a/test/e2e/cypress/integration/profiles/email/registration/errors.spec.ts +++ b/test/e2e/cypress/integration/profiles/email/registration/errors.spec.ts @@ -1,19 +1,19 @@ -import { appPrefix, gen } from '../../../../helpers' -import { routes as express } from '../../../../helpers/express' -import { routes as react } from '../../../../helpers/react' +import { appPrefix, gen } from "../../../../helpers" +import { routes as express } from "../../../../helpers/express" +import { routes as react } from "../../../../helpers/react" -describe('Registration failures with email profile', () => { +describe("Registration failures with email profile", () => { ;[ { route: express.registration, - app: 'express' as 'express', - profile: 'email' + app: "express" as "express", + profile: "email", }, { route: react.registration, - app: 'react' as 'react', - profile: 'spa' - } + app: "react" as "react", + profile: "spa", + }, ].forEach(({ route, profile, app }) => { describe(`for app ${app}`, () => { before(() => { @@ -28,146 +28,146 @@ describe('Registration failures with email profile', () => { const identity = gen.email() const password = gen.password() - it('fails when CSRF cookies are missing', () => { + it("fails when CSRF cookies are missing", () => { cy.get(`${appPrefix(app)}input[name="traits.website"]`).type( - 'https://www.ory.sh' + "https://www.ory.sh", ) cy.get('input[name="traits.email"]') .type(identity) - .should('have.value', identity) + .should("have.value", identity) cy.get('input[name="password"]') - .type('12345678') - .should('have.value', '12345678') + .type("12345678") + .should("have.value", "12345678") cy.shouldHaveCsrfError({ app }) }) - it('fails when a disallowed return_to url is requested', () => { + it("fails when a disallowed return_to url is requested", () => { cy.shouldErrorOnDisallowedReturnTo( - route + '?return_to=https://not-allowed', - { app } + route + "?return_to=https://not-allowed", + { app }, ) }) - describe('show errors when invalid signup data is used', () => { - it('should show an error when the password has leaked before', () => { - cy.get('input[name="traits.website"]').type('https://www.ory.sh') + describe("show errors when invalid signup data is used", () => { + it("should show an error when the password has leaked before", () => { + cy.get('input[name="traits.website"]').type("https://www.ory.sh") cy.get('input[name="traits.email"]') .type(identity) - .should('have.value', identity) + .should("have.value", identity) cy.get('input[name="password"]') - .type('12345678') - .should('have.value', '12345678') + .type("12345678") + .should("have.value", "12345678") cy.submitPasswordForm() cy.get('*[data-testid^="ui/message"]').should( - 'contain.text', - 'data breaches' + "contain.text", + "data breaches", ) }) - it('should show an error when the password is too similar', () => { - cy.get('input[name="traits.website"]').type('https://www.ory.sh') + it("should show an error when the password is too similar", () => { + cy.get('input[name="traits.website"]').type("https://www.ory.sh") cy.get('input[name="traits.email"]').type(identity) cy.get('input[name="password"]').type(identity) cy.submitPasswordForm() cy.get('*[data-testid^="ui/message"]').should( - 'contain.text', - 'too similar' + "contain.text", + "too similar", ) }) - it('should show an error when the password is empty', () => { - cy.get('input[name="traits.website"]').type('https://www.ory.sh') + it("should show an error when the password is empty", () => { + cy.get('input[name="traits.website"]').type("https://www.ory.sh") cy.get('input[name="traits.email"]').type(identity) cy.submitPasswordForm() cy.get('*[data-testid^="ui/message/"]') - .invoke('text') + .invoke("text") .then((text) => { expect(text).to.be.oneOf([ - 'length must be >= 1, but got 0', - 'Property password is missing.' + "length must be >= 1, but got 0", + "Property password is missing.", ]) }) }) - it('should show an error when the email is empty', () => { - cy.get('input[name="traits.website"]').type('https://www.ory.sh') + it("should show an error when the email is empty", () => { + cy.get('input[name="traits.website"]').type("https://www.ory.sh") cy.get('input[name="password"]').type(password) cy.submitPasswordForm() cy.get('*[data-testid^="ui/message/"]') - .invoke('text') + .invoke("text") .then((text) => { expect(text).to.be.oneOf([ '"" is not valid "email"length must be >= 3, but got 0', - 'Property email is missing.' + "Property email is missing.", ]) }) }) - it('should show an error when the email is not an email', () => { - cy.get('input[name="traits.website"]').type('https://www.ory.sh') - cy.get('input[name="password"]').type('not-an-email') + it("should show an error when the email is not an email", () => { + cy.get('input[name="traits.website"]').type("https://www.ory.sh") + cy.get('input[name="password"]').type("not-an-email") cy.submitPasswordForm() cy.get( - '*[data-testid="ui/message/4000001"], *[data-testid="ui/message/4000002"]' - ).should('exist') + '*[data-testid="ui/message/4000001"], *[data-testid="ui/message/4000002"]', + ).should("exist") }) - it('should show a missing indicator if no fields are set', () => { + it("should show a missing indicator if no fields are set", () => { cy.submitPasswordForm() cy.get( - '*[data-testid="ui/message/4000001"], *[data-testid="ui/message/4000002"]' - ).should('exist') + '*[data-testid="ui/message/4000001"], *[data-testid="ui/message/4000002"]', + ).should("exist") }) - it('should show an error when the website is not a valid URI', () => { + it("should show an error when the website is not a valid URI", () => { cy.get('input[name="traits.website"]') - .type('1234') + .type("1234") .then(($input) => { expect( - ($input[0] as HTMLInputElement).validationMessage - ).to.contain('URL') + ($input[0] as HTMLInputElement).validationMessage, + ).to.contain("URL") }) }) - it('should show an error when the website is too short', () => { - cy.get('input[name="traits.website"]').type('http://s') + it("should show an error when the website is too short", () => { + cy.get('input[name="traits.website"]').type("http://s") cy.submitPasswordForm() cy.get('*[data-testid^="ui/message"]').should( - 'contain.text', - 'length must be >= 10' + "contain.text", + "length must be >= 10", ) }) - it('should show an error when required params are missing', () => { + it("should show an error when required params are missing", () => { cy.submitPasswordForm() cy.get('*[data-testid^="ui/message"]').should( - 'contain.text', - 'Property website is missing.' + "contain.text", + "Property website is missing.", ) cy.get('*[data-testid^="ui/message"]').should( - 'contain.text', - 'Property email is missing.' + "contain.text", + "Property email is missing.", ) cy.get('*[data-testid^="ui/message"]').should( - 'contain.text', - 'Property password is missing.' + "contain.text", + "Property password is missing.", ) }) - it('should show an error when the age is too high', () => { - cy.get('input[name="traits.age"]').type('600') + it("should show an error when the age is too high", () => { + cy.get('input[name="traits.age"]').type("600") cy.submitPasswordForm() cy.get('*[data-testid^="ui/message"]').should( - 'contain.text', - 'must be <= 300 but found 600' + "contain.text", + "must be <= 300 but found 600", ) }) }) diff --git a/test/e2e/cypress/integration/profiles/email/registration/success.spec.ts b/test/e2e/cypress/integration/profiles/email/registration/success.spec.ts index 725c41b08b30..3e645593c2b8 100644 --- a/test/e2e/cypress/integration/profiles/email/registration/success.spec.ts +++ b/test/e2e/cypress/integration/profiles/email/registration/success.spec.ts @@ -1,19 +1,19 @@ -import { APP_URL, appPrefix, gen } from '../../../../helpers' -import { routes as express } from '../../../../helpers/express' -import { routes as react } from '../../../../helpers/react' +import { APP_URL, appPrefix, gen } from "../../../../helpers" +import { routes as express } from "../../../../helpers/express" +import { routes as react } from "../../../../helpers/react" -context('Registration success with email profile', () => { +context("Registration success with email profile", () => { ;[ { route: express.registration, - app: 'express' as 'express', - profile: 'email' + app: "express" as "express", + profile: "email", }, { route: react.registration, - app: 'react' as 'react', - profile: 'spa' - } + app: "react" as "react", + profile: "spa", + }, ].forEach(({ route, profile, app }) => { describe(`for app ${app}`, () => { before(() => { @@ -26,13 +26,13 @@ context('Registration success with email profile', () => { cy.visit(route) }) - it('should sign up and be logged in', () => { + it("should sign up and be logged in", () => { const email = gen.email() const password = gen.password() - const website = 'https://www.example.org/' + const website = "https://www.example.org/" const age = 30 - cy.get(appPrefix(app) + 'input[name="traits"]').should('not.exist') + cy.get(appPrefix(app) + 'input[name="traits"]').should("not.exist") cy.get('input[name="traits.email"]').type(email) cy.get('input[name="password"]').type(password) cy.get('input[name="traits.website').type(website) @@ -40,13 +40,13 @@ context('Registration success with email profile', () => { cy.get('[type="checkbox"][name="traits.tos"]').click({ force: true }) cy.submitPasswordForm() - cy.get('pre').should('contain.text', email) + cy.get("pre").should("contain.text", email) cy.getSession().should((session) => { const { identity } = session expect(identity.id).to.not.be.empty expect(identity.verifiable_addresses).to.have.length(1) - expect(identity.schema_id).to.equal('default') + expect(identity.schema_id).to.equal("default") expect(identity.schema_url).to.equal(`${APP_URL}/schemas/ZGVmYXVsdA`) expect(identity.traits.website).to.equal(website) expect(identity.traits.email).to.equal(email) @@ -55,24 +55,24 @@ context('Registration success with email profile', () => { }) }) - it('should sign up with advanced form field values be logged in', () => { + it("should sign up with advanced form field values be logged in", () => { const email = gen.email() const password = gen.password() - cy.get('input[name="traits"]').should('not.exist') + cy.get('input[name="traits"]').should("not.exist") cy.get('input[name="traits.email"]').type(email) cy.get('input[name="password"]').type(password) - const website = 'https://www.example.org/' + const website = "https://www.example.org/" cy.get('input[name="traits.website"]').type(website) cy.submitPasswordForm() - cy.get('pre').should('contain.text', email) + cy.get("pre").should("contain.text", email) cy.getSession().should((session) => { const { identity } = session expect(identity.id).to.not.be.empty expect(identity.verifiable_addresses).to.have.length(1) - expect(identity.schema_id).to.equal('default') + expect(identity.schema_id).to.equal("default") expect(identity.schema_url).to.equal(`${APP_URL}/schemas/ZGVmYXVsdA`) expect(identity.traits.website).to.equal(website) expect(identity.traits.email).to.equal(email) @@ -81,39 +81,39 @@ context('Registration success with email profile', () => { }) }) - it('should sign up and be redirected', () => { + it("should sign up and be redirected", () => { cy.browserReturnUrlOry() - cy.visit(route + '?return_to=https://www.example.org/') + cy.visit(route + "?return_to=https://www.example.org/") const email = gen.email() const password = gen.password() - const website = 'https://www.example.org/' + const website = "https://www.example.org/" - cy.get('input[name="traits"]').should('not.exist') + cy.get('input[name="traits"]').should("not.exist") cy.get('input[name="traits.email"]').type(email) cy.get('input[name="traits.website').type(website) cy.get('input[name="password"]').type(password) cy.submitPasswordForm() - cy.url().should('eq', 'https://www.example.org/') + cy.url().should("eq", "https://www.example.org/") }) }) }) - describe('redirect for express app', () => { - it('should redirect to return_to after flow expires', () => { + describe("redirect for express app", () => { + it("should redirect to return_to after flow expires", () => { // Wait for flow to expire - cy.useConfigProfile('email') + cy.useConfigProfile("email") cy.shortRegisterLifespan() cy.browserReturnUrlOry() - cy.proxy('express') - cy.visit(express.registration + '?return_to=https://www.example.org/') + cy.proxy("express") + cy.visit(express.registration + "?return_to=https://www.example.org/") cy.wait(105) const email = gen.email() const password = gen.password() - const website = 'https://www.example.org/' + const website = "https://www.example.org/" - cy.get(appPrefix('express') + 'input[name="traits"]').should('not.exist') + cy.get(appPrefix("express") + 'input[name="traits"]').should("not.exist") cy.get('input[name="traits.email"]').type(email) cy.get('input[name="traits.website').type(website) cy.get('input[name="password"]').type(password) @@ -122,18 +122,18 @@ context('Registration success with email profile', () => { cy.submitPasswordForm() cy.get('*[data-testid^="ui/message/"]').should( - 'contain.text', - 'The registration flow expired' + "contain.text", + "The registration flow expired", ) // Try again with long lifespan set - cy.get('input[name="traits"]').should('not.exist') + cy.get('input[name="traits"]').should("not.exist") cy.get('input[name="traits.email"]').type(email) cy.get('input[name="traits.website').type(website) cy.get('input[name="password"]').type(password) cy.submitPasswordForm() - cy.url().should('eq', 'https://www.example.org/') + cy.url().should("eq", "https://www.example.org/") }) }) }) diff --git a/test/e2e/cypress/integration/profiles/email/registration/ui.spec.ts b/test/e2e/cypress/integration/profiles/email/registration/ui.spec.ts index 6ddb33286994..122adfc974bc 100644 --- a/test/e2e/cypress/integration/profiles/email/registration/ui.spec.ts +++ b/test/e2e/cypress/integration/profiles/email/registration/ui.spec.ts @@ -1,19 +1,19 @@ -import { routes as express } from '../../../../helpers/express' -import { routes as react } from '../../../../helpers/react' -import { appPrefix } from '../../../../helpers' +import { routes as express } from "../../../../helpers/express" +import { routes as react } from "../../../../helpers/react" +import { appPrefix } from "../../../../helpers" -describe('Registration UI for email flows', () => { +describe("Registration UI for email flows", () => { ;[ { route: express.registration, - app: 'express' as 'express', - profile: 'email' + app: "express" as "express", + profile: "email", }, { route: react.registration, - app: 'react' as 'react', - profile: 'spa' - } + app: "react" as "react", + profile: "spa", + }, ].forEach(({ route, profile, app }) => { describe(`for app ${app}`, () => { before(() => { @@ -25,22 +25,22 @@ describe('Registration UI for email flows', () => { cy.visit(route) }) - describe('use ui elements', () => { - it('should use the json schema titles', () => { + describe("use ui elements", () => { + it("should use the json schema titles", () => { cy.get(appPrefix(app) + 'input[name="traits.email"]') .parent() - .should('contain.text', 'Your E-Mail') + .should("contain.text", "Your E-Mail") cy.get('input[name="traits.website"]') .parent() - .should('contain.text', 'Your website') - cy.get('button[value="password"]').should('contain.text', 'Sign up') + .should("contain.text", "Your website") + cy.get('button[value="password"]').should("contain.text", "Sign up") }) - it('clicks the log in link', () => { + it("clicks the log in link", () => { cy.get('*[data-testid="cta-link"]').click() - cy.location('pathname').should('include', '/login') - if (app === 'express') { - cy.location('search').should('not.be.empty') + cy.location("pathname").should("include", "/login") + if (app === "express") { + cy.location("search").should("not.be.empty") } }) }) diff --git a/test/e2e/cypress/integration/profiles/email/settings/errors.spec.ts b/test/e2e/cypress/integration/profiles/email/settings/errors.spec.ts index b0cc0815ce2f..68880c25eb4f 100644 --- a/test/e2e/cypress/integration/profiles/email/settings/errors.spec.ts +++ b/test/e2e/cypress/integration/profiles/email/settings/errors.spec.ts @@ -1,21 +1,21 @@ -import { appPrefix, gen, website } from '../../../../helpers' -import { routes as react } from '../../../../helpers/react' -import { routes as express } from '../../../../helpers/express' +import { appPrefix, gen, website } from "../../../../helpers" +import { routes as react } from "../../../../helpers/react" +import { routes as express } from "../../../../helpers/express" -context('Settings failures with email profile', () => { +context("Settings failures with email profile", () => { ;[ { route: express.settings, base: express.base, - app: 'express' as 'express', - profile: 'email' + app: "express" as "express", + profile: "email", }, { route: react.settings, base: react.base, - app: 'react' as 'react', - profile: 'spa' - } + app: "react" as "react", + profile: "spa", + }, ].forEach(({ route, profile, app, base }) => { describe(`for app ${app}`, () => { let email = gen.email() @@ -32,12 +32,12 @@ context('Settings failures with email profile', () => { cy.registerApi({ email: emailSecond, password: passwordSecond, - fields: { 'traits.website': 'https://github.com/ory/kratos' } + fields: { "traits.website": "https://github.com/ory/kratos" }, }) cy.registerApi({ email, password, - fields: { 'traits.website': website } + fields: { "traits.website": website }, }) }) @@ -51,21 +51,21 @@ context('Settings failures with email profile', () => { cy.visit(route) }) - describe('profile', () => { + describe("profile", () => { beforeEach(() => { cy.visit(route) }) - it('fails with validation errors', () => { - cy.get('input[name="traits.website"]').clear().type('http://s') + it("fails with validation errors", () => { + cy.get('input[name="traits.website"]').clear().type("http://s") cy.get('[name="method"][value="profile"]').click() cy.get('[data-testid^="ui/message"]').should( - 'contain.text', - 'length must be >= 10' + "contain.text", + "length must be >= 10", ) }) - it('fails because reauth is another person', () => { + it("fails because reauth is another person", () => { // Force this because it is hidden cy.get('input[name="traits.email"]').clear().type(up(email)) cy.shortPrivilegedSessionTime() @@ -76,14 +76,14 @@ context('Settings failures with email profile', () => { cy.reauthWithOtherAccount({ previousUrl: loc.toString(), expect: { email }, - type: { email: emailSecond, password: passwordSecond } + type: { email: emailSecond, password: passwordSecond }, }) - cy.location('pathname').should('contain', '/settings') + cy.location("pathname").should("contain", "/settings") }) // We end up in a new settings flow for the second user - cy.get('input[name="traits.email"]').should('have.value', emailSecond) + cy.get('input[name="traits.email"]').should("have.value", emailSecond) // Try to log in with updated credentials -> should fail cy.clearAllCookies() @@ -91,11 +91,11 @@ context('Settings failures with email profile', () => { email: up(email), password, expectSession: false, - cookieUrl: base + cookieUrl: base, }) }) - it('does not update data because resumable session was removed', () => { + it("does not update data because resumable session was removed", () => { cy.get('input[name="traits.email"]').clear().type(up(email)) cy.shortPrivilegedSessionTime() cy.get('button[value="profile"]').click() @@ -109,7 +109,7 @@ context('Settings failures with email profile', () => { }) }) - it('does not update without re-auth', () => { + it("does not update without re-auth", () => { cy.get('input[name="traits.email"]').clear().type(up(email)) cy.shortPrivilegedSessionTime() // wait for the privileged session to time out cy.get('button[value="profile"]').click() @@ -122,17 +122,17 @@ context('Settings failures with email profile', () => { }) }) - it('does not resume another failed request', () => { + it("does not resume another failed request", () => { // checks here that we're checking settingsRequest.id == cookie.stored.id cy.get('input[name="traits.email"]').clear().type(up(email)) cy.shortPrivilegedSessionTime() // wait for the privileged session to time out cy.get('button[value="profile"]').click() - cy.location('pathname').should('not.contain', '/settings') + cy.location("pathname").should("not.contain", "/settings") cy.visit(route) cy.get('input[name="traits.website"]') .clear() - .type('http://github.com/aeneasr') + .type("http://github.com/aeneasr") cy.get('button[value="profile"]').click() cy.expectSettingsSaved() @@ -140,13 +140,13 @@ context('Settings failures with email profile', () => { const { identity } = session expect(identity.traits.email).to.equal(email) // this is NOT up(email) expect(identity.traits.website).to.equal( - 'http://github.com/aeneasr' + "http://github.com/aeneasr", ) // this is NOT up(email) }) }) }) - describe('password', () => { + describe("password", () => { beforeEach(() => { cy.longPrivilegedSessionTime() }) @@ -155,16 +155,16 @@ context('Settings failures with email profile', () => { cy.longPrivilegedSessionTime() }) - it('fails if password policy is violated', () => { - cy.get('input[name="password"]').clear().type('12345678') + it("fails if password policy is violated", () => { + cy.get('input[name="password"]').clear().type("12345678") cy.get('button[value="password"]').click() cy.get('*[data-testid^="ui/message"]').should( - 'contain.text', - 'data breaches' + "contain.text", + "data breaches", ) }) - it('fails because reauth is another person', () => { + it("fails because reauth is another person", () => { cy.shortPrivilegedSessionTime() // wait for the privileged session to time out cy.get('input[name="password"]').clear().type(up(password)) @@ -179,10 +179,10 @@ context('Settings failures with email profile', () => { cy.reauthWithOtherAccount({ previousUrl: loc.toString(), expect: { email }, - type: { email: emailSecond, password: passwordSecond } + type: { email: emailSecond, password: passwordSecond }, }) - cy.location('pathname').should('contain', '/settings') + cy.location("pathname").should("contain", "/settings") }) // We want to ensure that the reauth session is completely different from the one we had in the first place. @@ -192,12 +192,12 @@ context('Settings failures with email profile', () => { expect(session.id).to.not.eq(firstSession.id) expect(session.identity.id).to.not.eq(firstSession.identity.id) expect(session.authenticated_at).to.not.eq( - firstSession.authenticated_at + firstSession.authenticated_at, ) }) // We end up in a new settings flow for the second user - cy.get('input[name="traits.email"]').should('have.value', emailSecond) + cy.get('input[name="traits.email"]').should("have.value", emailSecond) // Try to log in with updated credentials -> should fail cy.clearAllCookies() @@ -205,11 +205,11 @@ context('Settings failures with email profile', () => { email, password: up(password), expectSession: false, - cookieUrl: base + cookieUrl: base, }) }) - it('does not update without re-auth', () => { + it("does not update without re-auth", () => { cy.get('input[name="password"]').clear().type(up(password)) cy.shortPrivilegedSessionTime() // wait for the privileged session to time out cy.get('button[value="password"]').click() @@ -220,11 +220,11 @@ context('Settings failures with email profile', () => { email, password: up(password), expectSession: false, - cookieUrl: base + cookieUrl: base, }) }) - it('does not update data because resumable session was removed', () => { + it("does not update data because resumable session was removed", () => { cy.get('input[name="password"]').clear().type(up(password)) cy.shortPrivilegedSessionTime() // wait for the privileged session to time out cy.get('button[value="password"]').click() @@ -236,38 +236,38 @@ context('Settings failures with email profile', () => { email, password: up(password), expectSession: false, - cookieUrl: base + cookieUrl: base, }) }) - it('does not resume another queued request', () => { + it("does not resume another queued request", () => { const email = gen.email() const password = gen.password() cy.clearAllCookies() cy.register({ email, password, - fields: { 'traits.website': website } + fields: { "traits.website": website }, }) cy.visit(route) // checks here that we're checking settingsRequest.id == cookie.stored.id - const invalidPassword = 'invalid-' + gen.password() + const invalidPassword = "invalid-" + gen.password() cy.get('input[name="password"]').clear().type(invalidPassword) cy.shortPrivilegedSessionTime() // wait for the privileged session to time out cy.get('button[value="password"]').click() - cy.location('pathname').should('include', '/login') + cy.location("pathname").should("include", "/login") - const validPassword = 'valid-' + gen.password() + const validPassword = "valid-" + gen.password() cy.visit(route) cy.get('input[name="password"]').clear().type(validPassword) cy.get('button[value="password"]').click() - cy.location('pathname').should('include', '/login') + cy.location("pathname").should("include", "/login") cy.reauth({ expect: { email }, type: { password: password } }) - cy.location('pathname').should('include', '/settings') - cy.get('input[name="password"]').should('exist') + cy.location("pathname").should("include", "/settings") + cy.get('input[name="password"]').should("exist") // This should pass because it is the correct password cy.clearAllCookies() @@ -279,7 +279,7 @@ context('Settings failures with email profile', () => { email, password: invalidPassword, expectSession: false, - cookieUrl: base + cookieUrl: base, }) cy.clearAllCookies() @@ -287,21 +287,21 @@ context('Settings failures with email profile', () => { email, password: password, expectSession: false, - cookieUrl: base + cookieUrl: base, }) }) }) - describe('global errors', () => { - it('fails when CSRF is incorrect', () => { - cy.get(appPrefix(app) + 'input[name="password"]').type('12345678') + describe("global errors", () => { + it("fails when CSRF is incorrect", () => { + cy.get(appPrefix(app) + 'input[name="password"]').type("12345678") cy.shouldHaveCsrfError({ app }) }) - it('fails when a disallowed return_to url is requested', () => { + it("fails when a disallowed return_to url is requested", () => { cy.shouldErrorOnDisallowedReturnTo( - route + '?return_to=https://not-allowed', - { app } + route + "?return_to=https://not-allowed", + { app }, ) }) }) diff --git a/test/e2e/cypress/integration/profiles/email/settings/success.spec.ts b/test/e2e/cypress/integration/profiles/email/settings/success.spec.ts index df55207f0e7a..183279abbb9e 100644 --- a/test/e2e/cypress/integration/profiles/email/settings/success.spec.ts +++ b/test/e2e/cypress/integration/profiles/email/settings/success.spec.ts @@ -1,37 +1,37 @@ -import { APP_URL, appPrefix, gen, website } from '../../../../helpers' -import { routes as express } from '../../../../helpers/express' -import { routes as react } from '../../../../helpers/react' +import { APP_URL, appPrefix, gen, website } from "../../../../helpers" +import { routes as express } from "../../../../helpers/express" +import { routes as react } from "../../../../helpers/react" -context('Settings success with email profile', () => { +context("Settings success with email profile", () => { ;[ { route: express.settings, base: express.base, - app: 'express' as 'express', - profile: 'email', - login: express.login + app: "express" as "express", + profile: "email", + login: express.login, }, { route: react.settings, base: react.base, - app: 'react' as 'react', - profile: 'spa', - login: react.login - } + app: "react" as "react", + profile: "spa", + login: react.login, + }, ].forEach(({ route, profile, app, base, login }) => { describe(`for app ${app}`, () => { let email = gen.email() let password = gen.password() const up = (value) => `not-${value}` - const down = (value) => value.replace(/not-/, '') + const down = (value) => value.replace(/not-/, "") before(() => { cy.useConfigProfile(profile) cy.registerApi({ email, password, - fields: { 'traits.website': website } + fields: { "traits.website": website }, }) cy.proxy(app) }) @@ -42,33 +42,33 @@ context('Settings success with email profile', () => { cy.visit(route) }) - it('shows all settings forms', () => { - cy.get(appPrefix(app) + 'h3').should('contain.text', 'Profile') - cy.get('input[name="traits.email"]').should('contain.value', email) - cy.get('input[name="traits.website"]').should('contain.value', website) + it("shows all settings forms", () => { + cy.get(appPrefix(app) + "h3").should("contain.text", "Profile") + cy.get('input[name="traits.email"]').should("contain.value", email) + cy.get('input[name="traits.website"]').should("contain.value", website) - cy.get('h3').should('contain.text', 'Password') - cy.get('input[name="password"]').should('be.empty') + cy.get("h3").should("contain.text", "Password") + cy.get('input[name="password"]').should("be.empty") }) - describe('password', () => { - it('modifies the password with privileged session', () => { + describe("password", () => { + it("modifies the password with privileged session", () => { // Once input weak password to test which error message is cleared after updating successfully - cy.get('input[name="password"]').clear().type('123') + cy.get('input[name="password"]').clear().type("123") cy.get('button[value="password"]').click() - cy.get('[data-testid="ui/message/1050001"]').should('not.exist') - cy.get('[data-testid="ui/message/4000005"]').should('exist') - cy.get('input[name="password"]').should('be.empty') + cy.get('[data-testid="ui/message/1050001"]').should("not.exist") + cy.get('[data-testid="ui/message/4000005"]').should("exist") + cy.get('input[name="password"]').should("be.empty") password = up(password) cy.get('input[name="password"]').clear().type(password) cy.get('button[value="password"]').click() cy.expectSettingsSaved() - cy.get('[data-testid="ui/message/4000005"]').should('not.exist') - cy.get('input[name="password"]').should('be.empty') + cy.get('[data-testid="ui/message/4000005"]').should("not.exist") + cy.get('input[name="password"]').should("be.empty") }) - it('is unable to log in with the old password', () => { + it("is unable to log in with the old password", () => { cy.visit(base) cy.clearAllCookies() cy.visit(login) @@ -76,11 +76,11 @@ context('Settings success with email profile', () => { email: email, password: down(password), expectSession: false, - cookieUrl: base + cookieUrl: base, }) }) - it('modifies the password with an unprivileged session', () => { + it("modifies the password with an unprivileged session", () => { password = up(password) cy.get('input[name="password"]').clear().type(password) cy.shortPrivilegedSessionTime() // wait for the privileged session to time out @@ -88,54 +88,54 @@ context('Settings success with email profile', () => { cy.reauth({ expect: { email }, type: { password: down(password) } }) - cy.url().should('include', '/settings') + cy.url().should("include", "/settings") cy.expectSettingsSaved() - cy.get('input[name="password"]').should('be.empty') + cy.get('input[name="password"]').should("be.empty") }) }) - describe('profile', () => { - it('modifies an unprotected traits', () => { + describe("profile", () => { + it("modifies an unprotected traits", () => { cy.get('input[name="traits.website"]') .clear() - .type('https://github.com/ory') - cy.get('input[name="traits.age"]').clear().type('30') + .type("https://github.com/ory") + cy.get('input[name="traits.age"]').clear().type("30") cy.get('input[type="checkbox"][name="traits.tos"]').click({ - force: true + force: true, }) cy.submitProfileForm() cy.expectSettingsSaved() cy.get('input[name="traits.website"]').should( - 'contain.value', - 'https://github.com/ory' + "contain.value", + "https://github.com/ory", ) cy.get('input[type="checkbox"][name="traits.tos"]') - .should('be.checked') + .should("be.checked") .click({ force: true }) cy.get('input[name="traits.age"]') - .should('have.value', '30') + .should("have.value", "30") .clear() - .type('90') + .type("90") cy.submitProfileForm() cy.expectSettingsSaved() cy.get('input[type="checkbox"][name="traits.tos"]').should( - 'not.be.checked' + "not.be.checked", ) - cy.get('input[name="traits.age"]').should('have.value', '90') + cy.get('input[name="traits.age"]').should("have.value", "90") }) - it('modifies a protected trait with privileged session', () => { + it("modifies a protected trait with privileged session", () => { email = up(email) cy.get('input[name="traits.email"]').clear().type(email) cy.get('button[value="profile"]').click() cy.expectSettingsSaved() - cy.get('input[name="traits.email"]').should('contain.value', email) + cy.get('input[name="traits.email"]').should("contain.value", email) }) - it('is unable to log in with the old email', () => { + it("is unable to log in with the old email", () => { cy.visit(base) cy.clearAllCookies() cy.visit(login) @@ -143,11 +143,11 @@ context('Settings success with email profile', () => { email: down(email), password, expectSession: false, - cookieUrl: base + cookieUrl: base, }) }) - it('modifies a protected trait with unprivileged session', () => { + it("modifies a protected trait with unprivileged session", () => { email = up(email) cy.get('input[name="traits.email"]').clear().type(email) cy.shortPrivilegedSessionTime() // wait for the privileged session to time out @@ -155,9 +155,9 @@ context('Settings success with email profile', () => { cy.reauth({ expect: { email: down(email) }, type: { password } }) - cy.url().should('include', '/settings') + cy.url().should("include", "/settings") cy.expectSettingsSaved() - cy.get('input[name="traits.email"]').should('contain.value', email) + cy.get('input[name="traits.email"]').should("contain.value", email) }) }) }) diff --git a/test/e2e/cypress/integration/profiles/email/settings/ui.spec.ts b/test/e2e/cypress/integration/profiles/email/settings/ui.spec.ts index 4668c056cd8d..3e421d9a53e8 100644 --- a/test/e2e/cypress/integration/profiles/email/settings/ui.spec.ts +++ b/test/e2e/cypress/integration/profiles/email/settings/ui.spec.ts @@ -1,19 +1,19 @@ -import { appPrefix, gen } from '../../../../helpers' -import { routes as express } from '../../../../helpers/express' -import { routes as react } from '../../../../helpers/react' +import { appPrefix, gen } from "../../../../helpers" +import { routes as express } from "../../../../helpers/express" +import { routes as react } from "../../../../helpers/react" -context('Settings errors with email profile', () => { +context("Settings errors with email profile", () => { ;[ { base: express.base, - app: 'express' as 'express', - profile: 'email' + app: "express" as "express", + profile: "email", }, { base: react.base, - app: 'react' as 'react', - profile: 'spa' - } + app: "react" as "react", + profile: "spa", + }, ].forEach(({ profile, app, base }) => { describe(`for app ${app}`, () => { const identity = gen.identity() @@ -22,7 +22,7 @@ context('Settings errors with email profile', () => { cy.useConfigProfile(profile) cy.registerApi({ ...identity, - fields: { 'traits.website': 'https://www.ory.sh/' } + fields: { "traits.website": "https://www.ory.sh/" }, }) cy.proxy(app) }) @@ -32,25 +32,25 @@ context('Settings errors with email profile', () => { cy.visit(base) }) - describe('use ui elements', () => { - it('should use the json schema titles', () => { + describe("use ui elements", () => { + it("should use the json schema titles", () => { cy.get(appPrefix(app) + 'a[href*="settings"]').click() cy.get('input[name="traits.email"]') .parent() - .should('contain.text', 'Your E-Mail') + .should("contain.text", "Your E-Mail") cy.get('input[name="traits.website"]') .parent() - .should('contain.text', 'Your website') + .should("contain.text", "Your website") cy.get('input[name="password"]') .parent() - .should('contain.text', 'Password') - cy.get('button[value="profile"]').should('contain.text', 'Save') - cy.get('button[value="password"]').should('contain.text', 'Save') + .should("contain.text", "Password") + cy.get('button[value="profile"]').should("contain.text", "Save") + cy.get('button[value="password"]').should("contain.text", "Save") }) - it('clicks the settings link', () => { + it("clicks the settings link", () => { cy.get('a[href*="settings"]').click() - cy.location('pathname').should('include', 'settings') + cy.location("pathname").should("include", "settings") }) }) }) diff --git a/test/e2e/cypress/integration/profiles/import/import.spec.ts b/test/e2e/cypress/integration/profiles/import/import.spec.ts index c539809924bb..ccbfabaaafff 100644 --- a/test/e2e/cypress/integration/profiles/import/import.spec.ts +++ b/test/e2e/cypress/integration/profiles/import/import.spec.ts @@ -1,10 +1,10 @@ -import { routes as express } from '../../../helpers/express' -import { gen, KRATOS_ADMIN, website } from '../../../helpers' +import { routes as express } from "../../../helpers/express" +import { gen, KRATOS_ADMIN, website } from "../../../helpers" -context('Import Identities', () => { +context("Import Identities", () => { before(() => { - cy.useConfigProfile('oidc') - cy.proxy('express') + cy.useConfigProfile("oidc") + cy.proxy("express") }) beforeEach(() => { @@ -14,68 +14,68 @@ context('Import Identities', () => { const password = gen.password() for (const tc of [ { - name: 'cleartext', + name: "cleartext", config: { - password + password, }, - checkPassword: password + checkPassword: password, }, { - name: 'pbkdf2', + name: "pbkdf2", config: { hashed_password: - '$pbkdf2-sha256$i=1000,l=128$e8/arsEf4cvQihdNgqj0Nw$5xQQKNTyeTHx2Ld5/JDE7A' + "$pbkdf2-sha256$i=1000,l=128$e8/arsEf4cvQihdNgqj0Nw$5xQQKNTyeTHx2Ld5/JDE7A", }, - checkPassword: '123456' + checkPassword: "123456", }, { - name: 'bcrypt', + name: "bcrypt", config: { hashed_password: - '$2a$10$ZsCsoVQ3xfBG/K2z2XpBf.tm90GZmtOqtqWcB5.pYd5Eq8y7RlDyq' + "$2a$10$ZsCsoVQ3xfBG/K2z2XpBf.tm90GZmtOqtqWcB5.pYd5Eq8y7RlDyq", }, - checkPassword: '123456' + checkPassword: "123456", }, { - name: 'argon2id', + name: "argon2id", config: { hashed_password: - '$argon2id$v=19$m=16,t=2,p=1$bVI1aE1SaTV6SGQ3bzdXdw$fnjCcZYmEPOUOjYXsT92Cg' + "$argon2id$v=19$m=16,t=2,p=1$bVI1aE1SaTV6SGQ3bzdXdw$fnjCcZYmEPOUOjYXsT92Cg", }, - checkPassword: '123456' - } + checkPassword: "123456", + }, ]) { it(`should be able to sign in using an imported password (${tc.name})`, () => { const email = gen.email() - cy.request('POST', `${KRATOS_ADMIN}/identities`, { - schema_id: 'default', + cy.request("POST", `${KRATOS_ADMIN}/identities`, { + schema_id: "default", traits: { email, - website + website, }, credentials: { password: { - config: tc.config - } - } + config: tc.config, + }, + }, }) cy.visit(express.login) // Try to sign in with an incorrect password cy.get('input[name="identifier"]').type(email) - cy.get('input[name="password"]').type('invalid-password') + cy.get('input[name="password"]').type("invalid-password") cy.submitPasswordForm() cy.get('*[data-testid="ui/message/4000006"]').should( - 'contain.text', - 'credentials are invalid' + "contain.text", + "credentials are invalid", ) // But with correct password it succeeds cy.get('input[name="password"]').type(tc.checkPassword) cy.submitPasswordForm() - cy.location('pathname').should('not.contain', '/login') + cy.location("pathname").should("not.contain", "/login") cy.getSession().should((session) => { const { identity } = session expect(identity.id).to.not.be.empty @@ -86,36 +86,36 @@ context('Import Identities', () => { it(`should be able to sign in using imported oidc credentials`, () => { const email = gen.email() - const website = 'https://' + gen.password() + '.com' - cy.request('POST', `${KRATOS_ADMIN}/identities`, { - schema_id: 'default', + const website = "https://" + gen.password() + ".com" + cy.request("POST", `${KRATOS_ADMIN}/identities`, { + schema_id: "default", traits: { email, - website + website, }, credentials: { oidc: { config: { providers: [ { - provider: 'hydra', - subject: email - } - ] - } - } - } + provider: "hydra", + subject: email, + }, + ], + }, + }, + }, }) cy.visit(express.login) cy.triggerOidc({ url: express.login }) - cy.get('#username').clear().type(email) - cy.get('#remember').click() - cy.get('#accept').click() + cy.get("#username").clear().type(email) + cy.get("#remember").click() + cy.get("#accept").click() cy.get('[name="scope"]').each(($el) => cy.wrap($el).click()) - cy.get('#remember').click() - cy.get('#accept').click() + cy.get("#remember").click() + cy.get("#accept").click() cy.getSession().should((session) => { const { identity } = session diff --git a/test/e2e/cypress/integration/profiles/mfa/lookup.spec.ts b/test/e2e/cypress/integration/profiles/mfa/lookup.spec.ts index 513b73e55e43..e2cc66e84db1 100644 --- a/test/e2e/cypress/integration/profiles/mfa/lookup.spec.ts +++ b/test/e2e/cypress/integration/profiles/mfa/lookup.spec.ts @@ -1,23 +1,23 @@ -import { appPrefix, gen, website } from '../../../helpers' -import { routes as express } from '../../../helpers/express' -import { routes as react } from '../../../helpers/react' +import { appPrefix, gen, website } from "../../../helpers" +import { routes as express } from "../../../helpers/express" +import { routes as react } from "../../../helpers/react" -context('2FA lookup secrets', () => { +context("2FA lookup secrets", () => { ;[ { login: react.login, settings: react.settings, base: react.base, - app: 'react' as 'react', - profile: 'spa' + app: "react" as "react", + profile: "spa", }, { login: express.login, settings: express.settings, base: express.base, - app: 'express' as 'express', - profile: 'mfa' - } + app: "express" as "express", + profile: "mfa", + }, ].forEach(({ settings, login, profile, app, base }) => { describe(`for app ${app}`, () => { before(() => { @@ -36,7 +36,7 @@ context('2FA lookup secrets', () => { cy.registerApi({ email, password, - fields: { 'traits.website': website } + fields: { "traits.website": website }, }) cy.login({ email, password, cookieUrl: base }) @@ -44,12 +44,12 @@ context('2FA lookup secrets', () => { cy.sessionRequiresNo2fa() }) - it('should be able to remove lookup codes', () => { + it("should be able to remove lookup codes", () => { cy.sessionRequires2fa() cy.longPrivilegedSessionTime() cy.visit(settings) cy.get( - appPrefix(app) + 'button[name="lookup_secret_regenerate"]' + appPrefix(app) + 'button[name="lookup_secret_regenerate"]', ).click() cy.get('button[name="lookup_secret_confirm"]').click() cy.expectSettingsSaved() @@ -59,37 +59,37 @@ context('2FA lookup secrets', () => { cy.get('button[name="lookup_secret_disable"]').click() cy.reauth({ expect: { email }, - type: { email: email, password: password } + type: { email: email, password: password }, }) cy.expectSettingsSaved() cy.clearAllCookies() cy.login({ email: email, password: password, cookieUrl: base }) - cy.visit(login + '?aal=aal2') - cy.get('h2').should('contain.text', 'Two-Factor Authentication') - cy.get('*[name="method"][value="totp"]').should('not.exist') - cy.get('*[name="method"][value="lookup_secret"]').should('not.exist') - cy.get('*[name="method"][value="password"]').should('not.exist') + cy.visit(login + "?aal=aal2") + cy.get("h2").should("contain.text", "Two-Factor Authentication") + cy.get('*[name="method"][value="totp"]').should("not.exist") + cy.get('*[name="method"][value="lookup_secret"]').should("not.exist") + cy.get('*[name="method"][value="password"]').should("not.exist") }) - it('should go through several lookup secret lifecycles', () => { + it("should go through several lookup secret lifecycles", () => { cy.visit(settings) cy.get('[data-testid="node/text/lookup_secret_codes/label"]').should( - 'not.exist' + "not.exist", ) cy.get('[data-testid="text-lookup_secret_codes-content"] code').should( - 'not.exist' + "not.exist", ) - cy.get('button[name="lookup_secret_confirm"]').should('not.exist') + cy.get('button[name="lookup_secret_confirm"]').should("not.exist") cy.get('button[name="lookup_secret_regenerate"]').click() cy.get('[data-testid="node/text/lookup_secret_codes/label"]').should( - 'contain.text', - 'These are your back up recovery codes.' + "contain.text", + "These are your back up recovery codes.", ) cy.get('[data-testid="text-lookup_secret_codes-content"] code').should( - 'not.be.empty' + "not.be.empty", ) let codes @@ -100,12 +100,12 @@ context('2FA lookup secrets', () => { cy.get('button[name="lookup_secret_confirm"]').click() cy.expectSettingsSaved() - cy.get('button[name="lookup_secret_reveal"]').should('exist') + cy.get('button[name="lookup_secret_reveal"]').should("exist") cy.get('[data-testid="text-lookup_secret_codes-content"] code').should( - 'not.exist' + "not.exist", ) - cy.get('button[name="lookup_secret_confirm"]').should('not.exist') - cy.get('button[name="lookup_secret_regenerate"]').should('not.exist') + cy.get('button[name="lookup_secret_confirm"]').should("not.exist") + cy.get('button[name="lookup_secret_regenerate"]').should("not.exist") cy.get('button[name="lookup_secret_reveal"]').click() cy.getLookupSecrets().should((c) => { @@ -113,48 +113,48 @@ context('2FA lookup secrets', () => { }) cy.getSession({ - expectAal: 'aal2', - expectMethods: ['password', 'lookup_secret'] + expectAal: "aal2", + expectMethods: ["password", "lookup_secret"], }) // Try to log in with a recovery code now - cy.visit(login + '?aal=aal2&refresh=true') - cy.location('pathname').should('contain', 'login') + cy.visit(login + "?aal=aal2&refresh=true") + cy.location("pathname").should("contain", "login") - cy.get('*[name="method"][value="lookup_secret"]').should('exist') - cy.get('*[name="method"][value="password"]').should('not.exist') + cy.get('*[name="method"][value="lookup_secret"]').should("exist") + cy.get('*[name="method"][value="password"]').should("not.exist") // Type an invalid code - cy.get('input[name="lookup_secret"]').should('exist') - cy.get('input[name="lookup_secret"]').type('invalid-code') + cy.get('input[name="lookup_secret"]').should("exist") + cy.get('input[name="lookup_secret"]').type("invalid-code") cy.get('*[name="method"][value="lookup_secret"]').click() cy.get('[data-testid="ui/message/4000016"]').should( - 'contain.text', - 'The backup recovery code is not valid.' + "contain.text", + "The backup recovery code is not valid.", ) // Type a valid code - cy.get('input[name="lookup_secret"]').should('exist') - cy.get('input[name="lookup_secret"]').should('have.value', '') + cy.get('input[name="lookup_secret"]').should("exist") + cy.get('input[name="lookup_secret"]').should("have.value", "") cy.get('input[name="lookup_secret"]').then(($e) => { cy.wrap($e).type(codes[0]) }) cy.get('*[name="method"][value="lookup_secret"]').click() - cy.location('pathname').should('not.contain', 'login') + cy.location("pathname").should("not.contain", "login") let authenticatedAt cy.getSession({ - expectAal: 'aal2', - expectMethods: ['password', 'lookup_secret', 'lookup_secret'] + expectAal: "aal2", + expectMethods: ["password", "lookup_secret", "lookup_secret"], }).then((session) => { authenticatedAt = session.authenticated_at - expect(session.authenticator_assurance_level).to.equal('aal2') + expect(session.authenticator_assurance_level).to.equal("aal2") }) // Retry auth with the used code - cy.visit(login + '?aal=aal2&refresh=true') + cy.visit(login + "?aal=aal2&refresh=true") cy.location().should((loc) => { - expect(loc.href).to.include('/login') + expect(loc.href).to.include("/login") }) cy.get('input[name="lookup_secret"]').then(($e) => { cy.wrap($e).type(codes[0]) @@ -162,24 +162,24 @@ context('2FA lookup secrets', () => { cy.get('*[name="method"][value="lookup_secret"]').click() // Use a valid code cy.get('[data-testid="ui/message/4000012"]').should( - 'contain.text', - 'This backup recovery code has already been used.' + "contain.text", + "This backup recovery code has already been used.", ) cy.get('input[name="lookup_secret"]').then(($e) => { cy.wrap($e).type(codes[1]) }) cy.get('*[name="method"][value="lookup_secret"]').click() - cy.location('pathname').should('not.contain', 'login') + cy.location("pathname").should("not.contain", "login") cy.getSession({ - expectAal: 'aal2', + expectAal: "aal2", expectMethods: [ - 'password', - 'lookup_secret', - 'lookup_secret', - 'lookup_secret' - ] + "password", + "lookup_secret", + "lookup_secret", + "lookup_secret", + ], }).then((session) => { expect(session.authenticated_at).to.not.equal(authenticatedAt) }) @@ -189,61 +189,61 @@ context('2FA lookup secrets', () => { cy.get('button[name="lookup_secret_reveal"]').click() cy.getLookupSecrets().should((c) => { let newCodes = codes - newCodes[0] = 'Used' - newCodes[1] = 'Used' + newCodes[0] = "Used" + newCodes[1] = "Used" expect(c).to.eql(newCodes) }) // Regenerating the codes means the old one become invalid - cy.get('*[name=lookup_secret_regenerate]').click() - cy.get('*[name=lookup_secret_confirm]').should('exist') + cy.get("*[name=lookup_secret_regenerate]").click() + cy.get("*[name=lookup_secret_confirm]").should("exist") let regenCodes cy.getLookupSecrets().should((c) => { regenCodes = c }) // Confirm it - cy.get('*[name=lookup_secret_confirm]').click() + cy.get("*[name=lookup_secret_confirm]").click() cy.get('*[name="lookup_secret_reveal"]').click() cy.getLookupSecrets().should((c) => { expect(c).to.eql(regenCodes) }) // Log in and see if we can use the old / new keys - cy.visit(login + '?aal=aal2&refresh=true') - cy.location('pathname').should('contain', 'login') + cy.visit(login + "?aal=aal2&refresh=true") + cy.location("pathname").should("contain", "login") // Using an old code fails cy.get('input[name="lookup_secret"]').then(($e) => { cy.wrap($e).type(codes[3]) }) cy.get('*[name="method"][value="lookup_secret"]').click() - cy.get('[data-testid="ui/message/4000016"]').should('exist') + cy.get('[data-testid="ui/message/4000016"]').should("exist") // Using a new code succeeds cy.get('input[name="lookup_secret"]').then(($e) => { cy.wrap($e).type(regenCodes[0]) }) cy.get('*[name="method"][value="lookup_secret"]').click() - cy.location('pathname').should('not.contain', 'login') + cy.location("pathname").should("not.contain", "login") // Going back to the settings UI we should see that the codes have been "used" cy.visit(settings) cy.get('button[name="lookup_secret_reveal"]').click() cy.getLookupSecrets().should((c) => { let newCodes = regenCodes - newCodes[0] = 'Used' + newCodes[0] = "Used" expect(c).to.eql(newCodes) }) }) - it('should end up at login screen if trying to reveal without privileged session', () => { + it("should end up at login screen if trying to reveal without privileged session", () => { cy.shortPrivilegedSessionTime() cy.visit(settings) cy.get('button[name="lookup_secret_regenerate"]').click() cy.reauth({ expect: { email }, - type: { email: email, password: password } + type: { email: email, password: password }, }) let codes @@ -255,7 +255,7 @@ context('2FA lookup secrets', () => { cy.get('button[name="lookup_secret_confirm"]').click() cy.reauth({ expect: { email }, - type: { email: email, password: password } + type: { email: email, password: password }, }) cy.expectSettingsSaved() @@ -263,22 +263,22 @@ context('2FA lookup secrets', () => { cy.get('button[name="lookup_secret_reveal"]').click() cy.reauth({ expect: { email }, - type: { email: email, password: password } + type: { email: email, password: password }, }) cy.getLookupSecrets().should((c) => { expect(c).to.not.be.empty }) cy.getSession({ - expectAal: 'aal2' + expectAal: "aal2", }) }) - it('should not show lookup as an option if not configured', () => { - cy.visit(login + '?aal=aal2') - cy.get('*[name="method"][value="totp"]').should('not.exist') - cy.get('*[name="method"][value="lookup_secret"]').should('not.exist') - cy.get('*[name="method"][value="password"]').should('not.exist') - cy.get('h2').should('contain.text', 'Two-Factor Authentication') + it("should not show lookup as an option if not configured", () => { + cy.visit(login + "?aal=aal2") + cy.get('*[name="method"][value="totp"]').should("not.exist") + cy.get('*[name="method"][value="lookup_secret"]').should("not.exist") + cy.get('*[name="method"][value="password"]').should("not.exist") + cy.get("h2").should("contain.text", "Two-Factor Authentication") }) }) }) diff --git a/test/e2e/cypress/integration/profiles/mfa/mix.spec.ts b/test/e2e/cypress/integration/profiles/mfa/mix.spec.ts index 0e186c580d37..2fb63f181484 100644 --- a/test/e2e/cypress/integration/profiles/mfa/mix.spec.ts +++ b/test/e2e/cypress/integration/profiles/mfa/mix.spec.ts @@ -1,27 +1,27 @@ -import { APP_URL, appPrefix, gen, website } from '../../../helpers' -import { authenticator } from 'otplib' -import { routes as react } from '../../../helpers/react' -import { routes as express } from '../../../helpers/express' +import { APP_URL, appPrefix, gen, website } from "../../../helpers" +import { authenticator } from "otplib" +import { routes as react } from "../../../helpers/react" +import { routes as express } from "../../../helpers/express" -context('2FA with various methods', () => { +context("2FA with various methods", () => { beforeEach(() => { - cy.task('resetCRI', {}) + cy.task("resetCRI", {}) }) ;[ { login: react.login, settings: react.settings, base: react.base, - app: 'react' as 'react', - profile: 'spa' + app: "react" as "react", + profile: "spa", }, { login: express.login, settings: express.settings, base: express.base, - app: 'express' as 'express', - profile: 'mfa' - } + app: "express" as "express", + profile: "mfa", + }, ].forEach(({ settings, login, profile, app, base }) => { describe(`for app ${app}`, () => { before(() => { @@ -38,45 +38,45 @@ context('2FA with various methods', () => { cy.registerApi({ email, password, - fields: { 'traits.website': website } + fields: { "traits.website": website }, }) cy.clearAllCookies() cy.login({ email, password, cookieUrl: base }) cy.longPrivilegedSessionTime() - cy.task('sendCRI', { - query: 'WebAuthn.disable', - opts: {} + cy.task("sendCRI", { + query: "WebAuthn.disable", + opts: {}, }) }) - it('should set up an use all mfa combinations', () => { + it("should set up an use all mfa combinations", () => { cy.visit(settings) - cy.task('sendCRI', { - query: 'WebAuthn.enable', - opts: {} + cy.task("sendCRI", { + query: "WebAuthn.enable", + opts: {}, }).then(() => { - cy.task('sendCRI', { - query: 'WebAuthn.addVirtualAuthenticator', + cy.task("sendCRI", { + query: "WebAuthn.addVirtualAuthenticator", opts: { options: { - protocol: 'ctap2', - transport: 'usb', + protocol: "ctap2", + transport: "usb", hasResidentKey: true, hasUserVerification: true, - isUserVerified: true - } - } + isUserVerified: true, + }, + }, }).then(() => { cy.getSession({ - expectAal: 'aal1', - expectMethods: ['password'] + expectAal: "aal1", + expectMethods: ["password"], }) cy.visit(settings) // Set up TOTP let secret cy.get( - appPrefix(app) + '[data-testid="node/text/totp_secret_key/text"]' + appPrefix(app) + '[data-testid="node/text/totp_secret_key/text"]', ).then(($e) => { secret = $e.text().trim() }) @@ -86,8 +86,8 @@ context('2FA with various methods', () => { cy.get('[name="method"][value="totp"]').click() cy.expectSettingsSaved() cy.getSession({ - expectAal: 'aal2', - expectMethods: ['password', 'totp'] + expectAal: "aal2", + expectMethods: ["password", "totp"], }) // Set up lookup secrets @@ -100,73 +100,73 @@ context('2FA with various methods', () => { cy.get('[name="lookup_secret_confirm"]').click() cy.expectSettingsSaved() cy.getSession({ - expectAal: 'aal2', - expectMethods: ['password', 'totp', 'lookup_secret'] + expectAal: "aal2", + expectMethods: ["password", "totp", "lookup_secret"], }) // Set up WebAuthn cy.visit(settings) - cy.get('[name="webauthn_register_displayname"]').type('my-key') + cy.get('[name="webauthn_register_displayname"]').type("my-key") // We need a workaround here. So first we click, then we submit - cy.clickWebAuthButton('register') + cy.clickWebAuthButton("register") cy.expectSettingsSaved() cy.getSession({ - expectAal: 'aal2', - expectMethods: ['password', 'totp', 'webauthn', 'lookup_secret'] + expectAal: "aal2", + expectMethods: ["password", "totp", "webauthn", "lookup_secret"], }) - cy.visit(login + '?aal=aal2&refresh=true') + cy.visit(login + "?aal=aal2&refresh=true") cy.get('[name="totp_code"]').then(($e) => { cy.wrap($e).type(authenticator.generate(secret)) }) cy.get('[name="method"][value="totp"]').click() - cy.location('pathname').should('not.include', '/login') + cy.location("pathname").should("not.include", "/login") cy.getSession({ - expectAal: 'aal2', + expectAal: "aal2", expectMethods: [ - 'password', - 'totp', - 'webauthn', - 'lookup_secret', - 'totp' - ] + "password", + "totp", + "webauthn", + "lookup_secret", + "totp", + ], }) // Use TOTP - cy.visit(login + '?aal=aal2&refresh=true') - cy.clickWebAuthButton('login') + cy.visit(login + "?aal=aal2&refresh=true") + cy.clickWebAuthButton("login") cy.getSession({ - expectAal: 'aal2', + expectAal: "aal2", expectMethods: [ - 'password', - 'totp', - 'webauthn', - 'lookup_secret', - 'totp', - 'webauthn' - ] + "password", + "totp", + "webauthn", + "lookup_secret", + "totp", + "webauthn", + ], }) // Use lookup - cy.visit(login + '?aal=aal2&refresh=true') + cy.visit(login + "?aal=aal2&refresh=true") cy.get('[name="lookup_secret"]').then(($e) => { cy.wrap($e).type(codes[1]) }) cy.get('[name="method"][value="lookup_secret"]').click() - cy.location('pathname').should('not.include', '/login') + cy.location("pathname").should("not.include", "/login") cy.getSession({ - expectAal: 'aal2', + expectAal: "aal2", expectMethods: [ - 'password', - 'totp', - 'webauthn', - 'lookup_secret', - 'totp', - 'webauthn', - 'lookup_secret' - ] + "password", + "totp", + "webauthn", + "lookup_secret", + "totp", + "webauthn", + "lookup_secret", + ], }) }) }) diff --git a/test/e2e/cypress/integration/profiles/mfa/settings.spec.ts b/test/e2e/cypress/integration/profiles/mfa/settings.spec.ts index 9e1de8d58eb6..0947f574de05 100644 --- a/test/e2e/cypress/integration/profiles/mfa/settings.spec.ts +++ b/test/e2e/cypress/integration/profiles/mfa/settings.spec.ts @@ -1,21 +1,21 @@ -import { appPrefix, gen, website } from '../../../helpers' -import { routes as express } from '../../../helpers/express' -import { routes as react } from '../../../helpers/react' +import { appPrefix, gen, website } from "../../../helpers" +import { routes as express } from "../../../helpers/express" +import { routes as react } from "../../../helpers/react" -context('2FA UI settings tests', () => { +context("2FA UI settings tests", () => { ;[ { settings: react.settings, base: react.base, - app: 'react' as 'react', - profile: 'spa' + app: "react" as "react", + profile: "spa", }, { settings: express.settings, base: express.base, - app: 'express' as 'express', - profile: 'mfa' - } + app: "express" as "express", + profile: "mfa", + }, ].forEach(({ settings, profile, base, app }) => { describe(`for app ${app}`, () => { before(() => { @@ -30,7 +30,7 @@ context('2FA UI settings tests', () => { cy.registerApi({ email, password, - fields: { 'traits.website': website } + fields: { "traits.website": website }, }) }) @@ -40,24 +40,24 @@ context('2FA UI settings tests', () => { cy.visit(settings) }) - it('shows all settings forms', () => { - cy.get(appPrefix(app) + 'h3').should('contain.text', 'Profile Settings') - cy.get('h3').should('contain.text', 'Change Password') - cy.get('h3').should('contain.text', 'Manage 2FA Backup Recovery Codes') - cy.get('h3').should('contain.text', 'Manage 2FA TOTP Authenticator App') - cy.get('h3').should('contain.text', 'Manage Hardware Tokens') - cy.get('input[name="traits.email"]').should('contain.value', email) - cy.get('input[name="traits.website"]').should('contain.value', website) + it("shows all settings forms", () => { + cy.get(appPrefix(app) + "h3").should("contain.text", "Profile Settings") + cy.get("h3").should("contain.text", "Change Password") + cy.get("h3").should("contain.text", "Manage 2FA Backup Recovery Codes") + cy.get("h3").should("contain.text", "Manage 2FA TOTP Authenticator App") + cy.get("h3").should("contain.text", "Manage Hardware Tokens") + cy.get('input[name="traits.email"]').should("contain.value", email) + cy.get('input[name="traits.website"]').should("contain.value", website) cy.get('[data-testid="node/text/totp_secret_key/label"]').should( - 'contain.text', - 'This is your authenticator app secret' + "contain.text", + "This is your authenticator app secret", ) - cy.get('button').should( - 'contain.text', - 'Generate new backup recovery codes' + cy.get("button").should( + "contain.text", + "Generate new backup recovery codes", ) - cy.get('button').should('contain.text', 'Add security key') + cy.get("button").should("contain.text", "Add security key") }) }) }) diff --git a/test/e2e/cypress/integration/profiles/mfa/totp.spec.ts b/test/e2e/cypress/integration/profiles/mfa/totp.spec.ts index 073f38e4b293..075d1fd6bfcd 100644 --- a/test/e2e/cypress/integration/profiles/mfa/totp.spec.ts +++ b/test/e2e/cypress/integration/profiles/mfa/totp.spec.ts @@ -1,24 +1,24 @@ -import { gen, website } from '../../../helpers' -import { authenticator } from 'otplib' -import { routes as react } from '../../../helpers/react' -import { routes as express } from '../../../helpers/express' +import { gen, website } from "../../../helpers" +import { authenticator } from "otplib" +import { routes as react } from "../../../helpers/react" +import { routes as express } from "../../../helpers/express" -context('2FA lookup secrets', () => { +context("2FA lookup secrets", () => { ;[ { login: react.login, settings: react.settings, base: react.base, - app: 'react' as 'react', - profile: 'spa' + app: "react" as "react", + profile: "spa", }, { login: express.login, settings: express.settings, base: express.base, - app: 'express' as 'express', - profile: 'mfa' - } + app: "express" as "express", + profile: "mfa", + }, ].forEach(({ settings, login, profile, app, base }) => { describe(`for app ${app}`, () => { before(() => { @@ -38,11 +38,11 @@ context('2FA lookup secrets', () => { cy.register({ email, password, - fields: { 'traits.website': website } + fields: { "traits.website": website }, }) }) - it('should be be asked to sign in with 2fa if set up', () => { + it("should be be asked to sign in with 2fa if set up", () => { cy.visit(settings) cy.requireStrictAal() @@ -56,8 +56,8 @@ context('2FA lookup secrets', () => { cy.get('*[name="method"][value="totp"]').click() cy.expectSettingsSaved() cy.getSession({ - expectAal: 'aal2', - expectMethods: ['password', 'totp'] + expectAal: "aal2", + expectMethods: ["password", "totp"], }) cy.clearAllCookies() @@ -72,8 +72,8 @@ context('2FA lookup secrets', () => { // If we visit settings page we still end up at 2fa screen cy.visit(settings) - cy.location('pathname').should((loc) => { - expect(loc).to.include('/login') + cy.location("pathname").should((loc) => { + expect(loc).to.include("/login") }) cy.shouldShow2FAScreen() @@ -81,17 +81,17 @@ context('2FA lookup secrets', () => { cy.wrap($e).type(authenticator.generate(secret)) }) cy.get('*[name="method"][value="totp"]').click() - cy.location('pathname').should((loc) => { - expect(loc).to.oneOf(['/welcome', '/']) + cy.location("pathname").should((loc) => { + expect(loc).to.oneOf(["/welcome", "/"]) }) cy.getSession({ - expectAal: 'aal2', - expectMethods: ['password', 'totp'] + expectAal: "aal2", + expectMethods: ["password", "totp"], }) }) - it('signin with 2fa and be redirected', () => { - if (app !== 'express') { + it("signin with 2fa and be redirected", () => { + if (app !== "express") { return } @@ -108,8 +108,8 @@ context('2FA lookup secrets', () => { cy.get('*[name="method"][value="totp"]').click() cy.expectSettingsSaved() cy.getSession({ - expectAal: 'aal2', - expectMethods: ['password', 'totp'] + expectAal: "aal2", + expectMethods: ["password", "totp"], }) cy.clearAllCookies() @@ -120,13 +120,13 @@ context('2FA lookup secrets', () => { cy.submitPasswordForm() // MFA is now requested - cy.location('pathname').should((loc) => { - expect(loc).to.include('/login') + cy.location("pathname").should((loc) => { + expect(loc).to.include("/login") }) cy.shouldShow2FAScreen() - cy.location('pathname').should((loc) => { - expect(loc).to.include('/login') + cy.location("pathname").should((loc) => { + expect(loc).to.include("/login") }) cy.shouldShow2FAScreen() @@ -134,14 +134,14 @@ context('2FA lookup secrets', () => { cy.wrap($e).type(authenticator.generate(secret)) }) cy.get('*[name="method"][value="totp"]').click() - cy.url().should('eq', 'https://www.example.org/') + cy.url().should("eq", "https://www.example.org/") }) - it('should go through several totp lifecycles', () => { + it("should go through several totp lifecycles", () => { cy.visit(settings) - cy.get('[data-testid="node/text/totp_secret_key/text"]').should('exist') - cy.get('img[data-testid="node/image/totp_qr"]').should('exist') + cy.get('[data-testid="node/text/totp_secret_key/text"]').should("exist") + cy.get('img[data-testid="node/image/totp_qr"]').should("exist") // Set up TOTP let secret @@ -154,52 +154,52 @@ context('2FA lookup secrets', () => { cy.get('*[name="method"][value="totp"]').click() cy.expectSettingsSaved() cy.get('[data-testid="node/text/totp_secret_key/text"]').should( - 'not.exist' + "not.exist", ) - cy.get('img[data-testid="node/image/totp_qr"]').should('not.exist') - cy.get('*[name="method"][value="totp"]').should('not.exist') - cy.get('*[name="totp_unlink"]').should('exist') + cy.get('img[data-testid="node/image/totp_qr"]').should("not.exist") + cy.get('*[name="method"][value="totp"]').should("not.exist") + cy.get('*[name="totp_unlink"]').should("exist") // Let's try to do 2FA - cy.visit(login + '?aal=aal2&refresh=true') - cy.location('pathname').should((loc) => { - expect(loc).to.include('/login') + cy.visit(login + "?aal=aal2&refresh=true") + cy.location("pathname").should((loc) => { + expect(loc).to.include("/login") }) - cy.get('*[name="method"][value="password"]').should('not.exist') + cy.get('*[name="method"][value="password"]').should("not.exist") // Typing a wrong code leaves us with an error message - cy.get('*[name="totp_code"]').type('111111') + cy.get('*[name="totp_code"]').type("111111") cy.get('*[name="method"][value="totp"]').click() cy.get('[data-testid="ui/message/4000008"]').should( - 'contain.text', - 'The provided authentication code is invalid, please try again.' + "contain.text", + "The provided authentication code is invalid, please try again.", ) cy.get('input[name="totp_code"]').then(($e) => { cy.wrap($e).type(authenticator.generate(secret)) }) cy.get('*[name="method"][value="totp"]').click() - cy.location('pathname').should('not.contain', '/login') + cy.location("pathname").should("not.contain", "/login") cy.getSession({ - expectAal: 'aal2', - expectMethods: ['password', 'totp', 'totp'] + expectAal: "aal2", + expectMethods: ["password", "totp", "totp"], }) // Going to settings and unlinking the device cy.visit(settings) cy.get('*[name="totp_unlink"]').click() cy.expectSettingsSaved() - cy.get('[data-testid="node/text/totp_secret_key/text"]').should('exist') - cy.get('img[data-testid="node/image/totp_qr"]').should('exist') - cy.get('*[name="method"][value="totp"]').should('exist') - cy.get('*[name="totp_unlink"]').should('not.exist') + cy.get('[data-testid="node/text/totp_secret_key/text"]').should("exist") + cy.get('img[data-testid="node/image/totp_qr"]').should("exist") + cy.get('*[name="method"][value="totp"]').should("exist") + cy.get('*[name="totp_unlink"]').should("not.exist") // 2FA should be gone - cy.visit(login + '?aal=aal2&refresh=true') - cy.location('pathname').should((loc) => { - expect(loc).to.include('/login') + cy.visit(login + "?aal=aal2&refresh=true") + cy.location("pathname").should((loc) => { + expect(loc).to.include("/login") }) - cy.get('*[name="method"][value="totp"]').should('not.exist') + cy.get('*[name="method"][value="totp"]').should("not.exist") // Linking a new device works cy.visit(settings) @@ -214,17 +214,17 @@ context('2FA lookup secrets', () => { cy.expectSettingsSaved() // Old secret no longer works in login - cy.visit(login + '?aal=aal2&refresh=true') - cy.location('pathname').should((loc) => { - expect(loc).to.include('/login') + cy.visit(login + "?aal=aal2&refresh=true") + cy.location("pathname").should((loc) => { + expect(loc).to.include("/login") }) cy.get('input[name="totp_code"]').then(($e) => { cy.wrap($e).type(authenticator.generate(secret)) }) cy.get('*[name="method"][value="totp"]').click() cy.get('[data-testid="ui/message/4000008"]').should( - 'contain.text', - 'The provided authentication code is invalid, please try again.' + "contain.text", + "The provided authentication code is invalid, please try again.", ) // But new one does! @@ -232,43 +232,43 @@ context('2FA lookup secrets', () => { cy.wrap($e).type(authenticator.generate(newSecret)) }) cy.get('*[name="method"][value="totp"]').click() - cy.location('pathname').should((loc) => { - expect(loc).to.not.include('/login') + cy.location("pathname").should((loc) => { + expect(loc).to.not.include("/login") }) cy.getSession({ - expectAal: 'aal2', - expectMethods: ['password', 'totp', 'totp', 'totp', 'totp'] + expectAal: "aal2", + expectMethods: ["password", "totp", "totp", "totp", "totp"], }) }) - it('should not show totp as an option if not configured', () => { - cy.visit(login + '?aal=aal2') - cy.location('pathname').should((loc) => { - expect(loc).to.include('/login') + it("should not show totp as an option if not configured", () => { + cy.visit(login + "?aal=aal2") + cy.location("pathname").should((loc) => { + expect(loc).to.include("/login") }) - cy.get('*[name="method"][value="totp"]').should('not.exist') - cy.get('*[name="method"][value="password"]').should('not.exist') + cy.get('*[name="method"][value="totp"]').should("not.exist") + cy.get('*[name="method"][value="password"]').should("not.exist") cy.shouldShow2FAScreen() cy.get('[data-testid="logout-link"]').click() cy.location().should((loc) => { - expect(loc.href).to.include('/login') - expect(loc.search).to.not.include('aal') - expect(loc.search).to.not.include('refresh') + expect(loc.href).to.include("/login") + expect(loc.search).to.not.include("aal") + expect(loc.search).to.not.include("refresh") }) - cy.get('h2').should('contain.text', 'Sign In') + cy.get("h2").should("contain.text", "Sign In") cy.noSession() }) - it('should fail to set up totp if verify code is wrong', () => { + it("should fail to set up totp if verify code is wrong", () => { cy.visit(settings) - cy.get('input[name="totp_code"]').type('12345678') + cy.get('input[name="totp_code"]').type("12345678") cy.get('*[name="method"][value="totp"]').click() cy.get('[data-testid="ui/message/4000008"]').should( - 'contain.text', - 'The provided authentication code is invalid, please try again.' + "contain.text", + "The provided authentication code is invalid, please try again.", ) }) }) diff --git a/test/e2e/cypress/integration/profiles/mfa/webauthn.spec.ts b/test/e2e/cypress/integration/profiles/mfa/webauthn.spec.ts index 2be497f5d93d..bbacd55498a7 100644 --- a/test/e2e/cypress/integration/profiles/mfa/webauthn.spec.ts +++ b/test/e2e/cypress/integration/profiles/mfa/webauthn.spec.ts @@ -1,26 +1,26 @@ -import { appPrefix, gen, website } from '../../../helpers' -import { routes as react } from '../../../helpers/react' -import { routes as express } from '../../../helpers/express' +import { appPrefix, gen, website } from "../../../helpers" +import { routes as react } from "../../../helpers/react" +import { routes as express } from "../../../helpers/express" -context('2FA WebAuthn', () => { +context("2FA WebAuthn", () => { beforeEach(() => { - cy.task('resetCRI', {}) + cy.task("resetCRI", {}) }) ;[ { login: express.login, settings: express.settings, base: express.base, - app: 'express' as 'express', - profile: 'mfa' + app: "express" as "express", + profile: "mfa", }, { login: react.login, settings: react.settings, base: react.base, - app: 'react' as 'react', - profile: 'spa' - } + app: "react" as "react", + profile: "spa", + }, ].forEach(({ settings, login, profile, app, base }) => { describe(`for app ${app}`, () => { before(() => { @@ -39,88 +39,88 @@ context('2FA WebAuthn', () => { cy.registerApi({ email, password, - fields: { 'traits.website': website } + fields: { "traits.website": website }, }) cy.login({ email, password }) cy.longPrivilegedSessionTime() - cy.task('sendCRI', { - query: 'WebAuthn.disable', - opts: {} + cy.task("sendCRI", { + query: "WebAuthn.disable", + opts: {}, }) }) - it('should be able to identify if the authenticator is wrong', () => { + it("should be able to identify if the authenticator is wrong", () => { cy.visit(settings) // Set up virtual authenticator - cy.task('sendCRI', { - query: 'WebAuthn.enable', - opts: {} + cy.task("sendCRI", { + query: "WebAuthn.enable", + opts: {}, }).then(() => { - cy.task('sendCRI', { - query: 'WebAuthn.addVirtualAuthenticator', + cy.task("sendCRI", { + query: "WebAuthn.addVirtualAuthenticator", opts: { options: { - protocol: 'ctap2', - transport: 'usb', + protocol: "ctap2", + transport: "usb", hasResidentKey: true, hasUserVerification: true, - isUserVerified: true - } - } + isUserVerified: true, + }, + }, }).then((addResult) => { cy.get( - appPrefix(app) + '[name="webauthn_register_displayname"]' - ).type('key1') + appPrefix(app) + '[name="webauthn_register_displayname"]', + ).type("key1") - cy.clickWebAuthButton('register') + cy.clickWebAuthButton("register") - cy.get('*[name="webauthn_remove"]').should('have.length', 1) + cy.get('*[name="webauthn_remove"]').should("have.length", 1) - cy.task('sendCRI', { - query: 'WebAuthn.removeVirtualAuthenticator', - opts: addResult + cy.task("sendCRI", { + query: "WebAuthn.removeVirtualAuthenticator", + opts: addResult, }).then(() => { - cy.visit(login + '?aal=aal2&refresh=true') + cy.visit(login + "?aal=aal2&refresh=true") cy.location().should((loc) => { - expect(loc.href).to.include('/login') + expect(loc.href).to.include("/login") }) - cy.clickWebAuthButton('login') + cy.clickWebAuthButton("login") cy.location().should((loc) => { - expect(loc.href).to.include('/login') + expect(loc.href).to.include("/login") }) cy.getSession({ - expectAal: 'aal2', - expectMethods: ['password', 'webauthn'] + expectAal: "aal2", + expectMethods: ["password", "webauthn"], }) - cy.task('sendCRI', { - query: 'WebAuthn.addVirtualAuthenticator', + cy.task("sendCRI", { + query: "WebAuthn.addVirtualAuthenticator", opts: { options: { - protocol: 'ctap2', - transport: 'usb', + protocol: "ctap2", + transport: "usb", hasResidentKey: true, hasUserVerification: true, - isUserVerified: true - } - } + isUserVerified: true, + }, + }, }).then((addResult) => { - cy.visit(login + '?aal=aal2&refresh=true') + cy.visit(login + "?aal=aal2&refresh=true") cy.location().should((loc) => { - expect(loc.href).to.include('/login') + expect(loc.href).to.include("/login") }) - cy.clickWebAuthButton('login') + cy.clickWebAuthButton("login") cy.location().should((loc) => { - expect(loc.href).to.include('/login') + expect(loc.href).to.include("/login") }) cy.getSession({ - expectAal: 'aal2', - expectMethods: ['password', 'webauthn'] + expectAal: "aal2", + expectMethods: ["password", "webauthn"], }) }) }) @@ -128,135 +128,135 @@ context('2FA WebAuthn', () => { }) }) - it('should be able to link multiple authenticators', () => { + it("should be able to link multiple authenticators", () => { cy.visit(settings) // Set up virtual authenticator - cy.task('sendCRI', { - query: 'WebAuthn.enable', - opts: {} + cy.task("sendCRI", { + query: "WebAuthn.enable", + opts: {}, }).then(() => { - cy.task('sendCRI', { - query: 'WebAuthn.addVirtualAuthenticator', + cy.task("sendCRI", { + query: "WebAuthn.addVirtualAuthenticator", opts: { options: { - protocol: 'ctap2', - transport: 'usb', + protocol: "ctap2", + transport: "usb", hasResidentKey: true, hasUserVerification: true, - isUserVerified: true - } - } + isUserVerified: true, + }, + }, }).then((addResult) => { - cy.get('*[name="webauthn_register_displayname"]').type('key1') - cy.clickWebAuthButton('register') + cy.get('*[name="webauthn_register_displayname"]').type("key1") + cy.clickWebAuthButton("register") - cy.get('*[name="webauthn_register_displayname"]').type('key2') - cy.clickWebAuthButton('register') + cy.get('*[name="webauthn_register_displayname"]').type("key2") + cy.clickWebAuthButton("register") - cy.get('*[name="webauthn_remove"]').should('have.length', 2) + cy.get('*[name="webauthn_remove"]').should("have.length", 2) - cy.visit(login + '?aal=aal2&refresh=true') + cy.visit(login + "?aal=aal2&refresh=true") cy.location().should((loc) => { - expect(loc.href).to.include('/login') + expect(loc.href).to.include("/login") }) - cy.get('*[name="webauthn_login_trigger"]').should('have.length', 1) - cy.clickWebAuthButton('login') + cy.get('*[name="webauthn_login_trigger"]').should("have.length", 1) + cy.clickWebAuthButton("login") }) }) }) - it('should be not be able to link provider if webauth is not enabled', () => { + it("should be not be able to link provider if webauth is not enabled", () => { cy.visit(settings) - cy.get('*[name="webauthn_register_displayname"]').type('my-key') - cy.clickWebAuthButton('register') - cy.get('*[name="webauthn_remove"]').should('not.exist') + cy.get('*[name="webauthn_register_displayname"]').type("my-key") + cy.clickWebAuthButton("register") + cy.get('*[name="webauthn_remove"]').should("not.exist") }) - it('should be able to link a webauthn provider', () => { + it("should be able to link a webauthn provider", () => { cy.visit(settings) // Set up virtual authenticator - cy.task('sendCRI', { - query: 'WebAuthn.enable', - opts: {} + cy.task("sendCRI", { + query: "WebAuthn.enable", + opts: {}, }).then(() => { - cy.task('sendCRI', { - query: 'WebAuthn.addVirtualAuthenticator', + cy.task("sendCRI", { + query: "WebAuthn.addVirtualAuthenticator", opts: { options: { - protocol: 'ctap2', - transport: 'usb', + protocol: "ctap2", + transport: "usb", hasResidentKey: true, hasUserVerification: true, - isUserVerified: true - } - } + isUserVerified: true, + }, + }, }).then((addResult) => { // Signing up without a display name causes an error - cy.get('*[name="webauthn_remove"]').should('not.exist') + cy.get('*[name="webauthn_remove"]').should("not.exist") - cy.clickWebAuthButton('register') + cy.clickWebAuthButton("register") cy.get('[data-testid="ui/message/4000002"]').should( - 'contain.text', - 'Property webauthn_register_displayname is missing.' + "contain.text", + "Property webauthn_register_displayname is missing.", ) // Setting up with key works - cy.get('*[name="webauthn_register_displayname"]').type('my-key') + cy.get('*[name="webauthn_register_displayname"]').type("my-key") // We need a workaround here. So first we click, then we submit - cy.clickWebAuthButton('register') + cy.clickWebAuthButton("register") cy.expectSettingsSaved() - cy.get('*[name="webauthn_remove"]').should('exist') + cy.get('*[name="webauthn_remove"]').should("exist") // Login without refresh cy.login({ email, password }) - cy.visit(login + '?aal=aal2') + cy.visit(login + "?aal=aal2") cy.location().should((loc) => { - expect(loc.href).to.include('/login') + expect(loc.href).to.include("/login") }) - cy.get('*[name="webauthn_login_trigger"]').should('have.length', 1) - cy.clickWebAuthButton('login') + cy.get('*[name="webauthn_login_trigger"]').should("have.length", 1) + cy.clickWebAuthButton("login") cy.location().should((loc) => { - expect(loc.href).to.not.include('/login') + expect(loc.href).to.not.include("/login") }) cy.getSession({ - expectAal: 'aal2', - expectMethods: ['password', 'webauthn'] + expectAal: "aal2", + expectMethods: ["password", "webauthn"], }) // Login with refresh - cy.visit(login + '?aal=aal2&refresh=true') + cy.visit(login + "?aal=aal2&refresh=true") cy.location().should((loc) => { - expect(loc.href).to.include('/login') + expect(loc.href).to.include("/login") }) - cy.get('*[name="webauthn_login_trigger"]').should('have.length', 1) - cy.clickWebAuthButton('login') + cy.get('*[name="webauthn_login_trigger"]').should("have.length", 1) + cy.clickWebAuthButton("login") cy.location().should((loc) => { - expect(loc.href).to.not.include('/login') + expect(loc.href).to.not.include("/login") }) cy.getSession({ - expectAal: 'aal2', - expectMethods: ['password', 'webauthn', 'webauthn'] + expectAal: "aal2", + expectMethods: ["password", "webauthn", "webauthn"], }) cy.visit(settings) cy.get('*[name="webauthn_remove"]').click() - cy.get('*[name="webauthn_remove"]').should('not.exist') + cy.get('*[name="webauthn_remove"]').should("not.exist") - cy.visit(login + '?aal=aal2&refresh=true') + cy.visit(login + "?aal=aal2&refresh=true") cy.location().should((loc) => { - expect(loc.href).to.include('/login') + expect(loc.href).to.include("/login") }) - cy.get('button[name="webauthn_login_trigger"]').should('not.exist') - cy.get('[data-testid="ui/message/1010003"]').should('exist') + cy.get('button[name="webauthn_login_trigger"]').should("not.exist") + cy.get('[data-testid="ui/message/1010003"]').should("exist") }) }) }) diff --git a/test/e2e/cypress/integration/profiles/mobile/login/errors.spec.ts b/test/e2e/cypress/integration/profiles/mobile/login/errors.spec.ts index 8eb44b7c607a..a16be43ff03f 100644 --- a/test/e2e/cypress/integration/profiles/mobile/login/errors.spec.ts +++ b/test/e2e/cypress/integration/profiles/mobile/login/errors.spec.ts @@ -1,54 +1,54 @@ -import { gen, MOBILE_URL } from '../../../../helpers' +import { gen, MOBILE_URL } from "../../../../helpers" -context('Mobile Profile', () => { - describe('Login Flow Errors', () => { +context("Mobile Profile", () => { + describe("Login Flow Errors", () => { before(() => { cy.clearAllCookies() - cy.useConfigProfile('mobile') + cy.useConfigProfile("mobile") }) beforeEach(() => { - cy.visit(MOBILE_URL + '/Login') + cy.visit(MOBILE_URL + "/Login") }) - describe('shows validation errors when invalid signup data is used', () => { - it('should show an error when the identifier is missing', () => { + describe("shows validation errors when invalid signup data is used", () => { + it("should show an error when the identifier is missing", () => { cy.get('input[data-testid="password"]').type(gen.password()) cy.get('div[data-testid="submit-form"]').click() cy.get('*[data-testid="field/identifier"]').should( - 'contain.text', - 'Property identifier is missing.' + "contain.text", + "Property identifier is missing.", ) cy.get('*[data-testid="field/password"]').should( - 'not.contain.text', - 'Property password is missing.' + "not.contain.text", + "Property password is missing.", ) }) - it('should show an error when the password is missing', () => { + it("should show an error when the password is missing", () => { const email = gen.email() cy.get('input[data-testid="identifier"]') .type(email) - .should('have.value', email) + .should("have.value", email) cy.get('div[data-testid="submit-form"]').click() cy.get('*[data-testid="field/password"]').should( - 'contain.text', - 'Property password is missing.' + "contain.text", + "Property password is missing.", ) }) - it('should show fail to sign in', () => { + it("should show fail to sign in", () => { cy.get('input[data-testid="identifier"]').type(gen.email()) cy.get('input[data-testid="password"]').type(gen.password()) cy.get('*[data-testid="submit-form"]').click() cy.get('*[data-testid="form-messages"]').should( - 'contain.text', - 'credentials are invalid' + "contain.text", + "credentials are invalid", ) }) }) diff --git a/test/e2e/cypress/integration/profiles/mobile/login/success.spec.ts b/test/e2e/cypress/integration/profiles/mobile/login/success.spec.ts index 37d4cd391b79..94552b6eb3ff 100644 --- a/test/e2e/cypress/integration/profiles/mobile/login/success.spec.ts +++ b/test/e2e/cypress/integration/profiles/mobile/login/success.spec.ts @@ -1,29 +1,29 @@ -import { gen, MOBILE_URL, website } from '../../../../helpers' +import { gen, MOBILE_URL, website } from "../../../../helpers" -context('Mobile Profile', () => { - describe('Login Flow Success', () => { +context("Mobile Profile", () => { + describe("Login Flow Success", () => { before(() => { - cy.useConfigProfile('mobile') + cy.useConfigProfile("mobile") }) const email = gen.email() const password = gen.password() before(() => { - cy.registerApi({ email, password, fields: { 'traits.website': website } }) + cy.registerApi({ email, password, fields: { "traits.website": website } }) }) beforeEach(() => { - cy.visit(MOBILE_URL + '/Login') + cy.visit(MOBILE_URL + "/Login") }) - it('should sign up and be logged in', () => { + it("should sign up and be logged in", () => { cy.get('input[data-testid="identifier"]').type(email) cy.get('input[data-testid="password"]').type(password) cy.get('div[data-testid="submit-form"]').click() - cy.get('[data-testid="session-content"]').should('contain', email) - cy.get('[data-testid="session-token"]').should('not.be.empty') + cy.get('[data-testid="session-content"]').should("contain", email) + cy.get('[data-testid="session-token"]').should("not.be.empty") }) }) }) diff --git a/test/e2e/cypress/integration/profiles/mobile/mfa/backup.spec.ts b/test/e2e/cypress/integration/profiles/mobile/mfa/backup.spec.ts index 7a1a43f334f1..e92637552ad9 100644 --- a/test/e2e/cypress/integration/profiles/mobile/mfa/backup.spec.ts +++ b/test/e2e/cypress/integration/profiles/mobile/mfa/backup.spec.ts @@ -1,12 +1,12 @@ -import { gen, MOBILE_URL, website } from '../../../../helpers' +import { gen, MOBILE_URL, website } from "../../../../helpers" -context('Mobile Profile', () => { - describe('TOTP 2FA Flow', () => { +context("Mobile Profile", () => { + describe("TOTP 2FA Flow", () => { before(() => { - cy.useConfigProfile('mobile') + cy.useConfigProfile("mobile") }) - describe('password', () => { + describe("password", () => { let email = gen.email() let password = gen.password() @@ -21,91 +21,91 @@ context('Mobile Profile', () => { cy.registerApi({ email, password, - fields: { 'traits.website': website } + fields: { "traits.website": website }, }) cy.loginMobile({ email, password }) - cy.visit(MOBILE_URL + '/Settings') + cy.visit(MOBILE_URL + "/Settings") }) - it('should be able to lifecycle through lookup_secret flows', () => { - cy.get('[data-testid="field/lookup_secret_codes"]').should('not.exist') + it("should be able to lifecycle through lookup_secret flows", () => { + cy.get('[data-testid="field/lookup_secret_codes"]').should("not.exist") cy.get('[data-testid="field/lookup_secret_confirm/true"]').should( - 'not.exist' + "not.exist", ) cy.get('[data-testid="field/lookup_secret_reveal/true"]').should( - 'not.exist' + "not.exist", ) cy.get('[data-testid="field/lookup_secret_regenerate/true"]').click() cy.get('[data-testid="field/lookup_secret_reveal/true"]').should( - 'not.exist' + "not.exist", ) - cy.get('[data-testid="field/lookup_secret_codes"]').should('exist') + cy.get('[data-testid="field/lookup_secret_codes"]').should("exist") let codes cy.get('[data-testid="field/lookup_secret_codes/text"]').then(($e) => { - codes = $e.text().trim().split(', ') + codes = $e.text().trim().split(", ") }) cy.get('[data-testid="field/lookup_secret_confirm/true"]').click() cy.expectSettingsSaved() cy.get('[data-testid="field/lookup_secret_confirm/true"]').should( - 'not.exist' + "not.exist", ) cy.get('[data-testid="field/lookup_secret_regenerate/true"]').should( - 'not.exist' + "not.exist", ) cy.get('[data-testid="field/lookup_secret_codes/true"]').should( - 'not.exist' + "not.exist", ) cy.get('[data-testid="field/lookup_secret_reveal/true"]').click() cy.get('[data-testid="field/lookup_secret_regenerate/true"]').should( - 'exist' + "exist", ) cy.get('[data-testid="field/lookup_secret_codes/text"]').then(($e) => { - const actualCodes = $e.text().trim().split(', ') - expect(actualCodes.join(', ')).to.eq(codes.join(', ')) + const actualCodes = $e.text().trim().split(", ") + expect(actualCodes.join(", ")).to.eq(codes.join(", ")) }) let newCodes cy.get('[data-testid="field/lookup_secret_regenerate/true"]').click() cy.get( - '[data-testid="field/lookup_secret_regenerate/true"]:disabled' - ).should('not.exist') + '[data-testid="field/lookup_secret_regenerate/true"]:disabled', + ).should("not.exist") cy.get('[data-testid="field/lookup_secret_codes/text"]').then(($e) => { - newCodes = $e.text().trim().split(', ') - expect(newCodes.join(', ')).to.not.eq(codes.join(', ')) + newCodes = $e.text().trim().split(", ") + expect(newCodes.join(", ")).to.not.eq(codes.join(", ")) }) cy.get('[data-testid="field/lookup_secret_confirm/true"]').click() cy.expectSettingsSaved() cy.get('[data-testid="field/lookup_secret_reveal/true"]').click() cy.get('[data-testid="field/lookup_secret_codes/text"]').then(($e) => { - const actualCodes = $e.text().trim().split(', ') - expect(actualCodes.join(', ')).to.eq(newCodes.join(', ')) + const actualCodes = $e.text().trim().split(", ") + expect(actualCodes.join(", ")).to.eq(newCodes.join(", ")) }) - cy.visit(MOBILE_URL + '/Login?aal=aal2&refresh=true') + cy.visit(MOBILE_URL + "/Login?aal=aal2&refresh=true") // First use a wrong code - cy.get('[data-testid=lookup_secret]').then(($e) => { + cy.get("[data-testid=lookup_secret]").then(($e) => { console.log(codes) - cy.wrap($e).type('1234') + cy.wrap($e).type("1234") }) cy.get('[data-testid="field/method/lookup_secret"]').click() cy.get('[data-testid="form-messages"]').should( - 'contain.text', - 'The backup recovery code is not valid.' + "contain.text", + "The backup recovery code is not valid.", ) - cy.get('[data-testid=lookup_secret]').then(($e) => { + cy.get("[data-testid=lookup_secret]").then(($e) => { cy.wrap($e).type(newCodes[0]) }) cy.get('[data-testid="field/method/lookup_secret"]').click() - cy.get('[data-testid="session-content"]').should('contain', 'aal2') + cy.get('[data-testid="session-content"]').should("contain", "aal2") cy.get('[data-testid="session-content"]').should( - 'contain', - 'lookup_secret' + "contain", + "lookup_secret", ) }) }) diff --git a/test/e2e/cypress/integration/profiles/mobile/mfa/mix.spec.ts b/test/e2e/cypress/integration/profiles/mobile/mfa/mix.spec.ts index 31e8b7433498..93b288467d64 100644 --- a/test/e2e/cypress/integration/profiles/mobile/mfa/mix.spec.ts +++ b/test/e2e/cypress/integration/profiles/mobile/mfa/mix.spec.ts @@ -1,13 +1,13 @@ -import { APP_URL, gen, MOBILE_URL, website } from '../../../../helpers' -import { authenticator } from 'otplib' +import { APP_URL, gen, MOBILE_URL, website } from "../../../../helpers" +import { authenticator } from "otplib" -context('Mobile Profile', () => { - describe('TOTP 2FA Flow', () => { +context("Mobile Profile", () => { + describe("TOTP 2FA Flow", () => { before(() => { - cy.useConfigProfile('mobile') + cy.useConfigProfile("mobile") }) - describe('password', () => { + describe("password", () => { let email = gen.email() let password = gen.password() @@ -22,13 +22,13 @@ context('Mobile Profile', () => { cy.registerApi({ email, password, - fields: { 'traits.website': website } + fields: { "traits.website": website }, }) cy.loginMobile({ email, password }) - cy.visit(MOBILE_URL + '/Settings') + cy.visit(MOBILE_URL + "/Settings") }) - it('should be able to use both TOTP and lookup', () => { + it("should be able to use both TOTP and lookup", () => { // set up totp let totpSecret cy.get('*[data-testid="field/totp_secret_key/text"]').then(($e) => { @@ -44,35 +44,35 @@ context('Mobile Profile', () => { cy.get('*[data-testid="field/lookup_secret_regenerate/true"]').click() let recoveryCodes cy.get('*[data-testid="field/lookup_secret_codes/text"]').then(($e) => { - recoveryCodes = $e.text().trim().split(', ') + recoveryCodes = $e.text().trim().split(", ") }) cy.get('*[data-testid="field/lookup_secret_confirm/true"]').click() cy.expectSettingsSaved() // Lets sign in with TOTP - cy.visit(MOBILE_URL + '/Login?aal=aal2&refresh=true') + cy.visit(MOBILE_URL + "/Login?aal=aal2&refresh=true") cy.get('*[data-testid="field/totp_code"]').then(($e) => { cy.wrap($e).type(authenticator.generate(totpSecret)) }) cy.get('*[data-testid="field/method/totp"]').click() // We have AAL now - cy.get('[data-testid="session-content"]').should('contain', 'aal2') - cy.get('[data-testid="session-content"]').should('contain', 'totp') + cy.get('[data-testid="session-content"]').should("contain", "aal2") + cy.get('[data-testid="session-content"]').should("contain", "totp") // Lets sign in with lookup secret - cy.visit(MOBILE_URL + '/Login?aal=aal2&refresh=true') + cy.visit(MOBILE_URL + "/Login?aal=aal2&refresh=true") cy.get('*[data-testid="field/lookup_secret"]').then(($e) => { cy.wrap($e).type(recoveryCodes[0]) }) cy.get('*[data-testid="field/method/lookup_secret"]').click() // We have AAL now - cy.get('[data-testid="session-content"]').should('contain', 'aal2') - cy.get('[data-testid="session-content"]').should('contain', 'totp') + cy.get('[data-testid="session-content"]').should("contain", "aal2") + cy.get('[data-testid="session-content"]').should("contain", "totp") cy.get('[data-testid="session-content"]').should( - 'contain', - 'lookup_secret' + "contain", + "lookup_secret", ) }) }) diff --git a/test/e2e/cypress/integration/profiles/mobile/mfa/totp.spec.ts b/test/e2e/cypress/integration/profiles/mobile/mfa/totp.spec.ts index f24331139765..2fcdb937676b 100644 --- a/test/e2e/cypress/integration/profiles/mobile/mfa/totp.spec.ts +++ b/test/e2e/cypress/integration/profiles/mobile/mfa/totp.spec.ts @@ -1,13 +1,13 @@ -import { APP_URL, gen, MOBILE_URL, website } from '../../../../helpers' -import { authenticator } from 'otplib' +import { APP_URL, gen, MOBILE_URL, website } from "../../../../helpers" +import { authenticator } from "otplib" -context('Mobile Profile', () => { - describe('TOTP 2FA Flow', () => { +context("Mobile Profile", () => { + describe("TOTP 2FA Flow", () => { before(() => { - cy.useConfigProfile('mobile') + cy.useConfigProfile("mobile") }) - describe('password', () => { + describe("password", () => { let email = gen.email() let password = gen.password() @@ -22,22 +22,22 @@ context('Mobile Profile', () => { cy.registerApi({ email, password, - fields: { 'traits.website': website } + fields: { "traits.website": website }, }) cy.loginMobile({ email, password }) - cy.visit(MOBILE_URL + '/Settings') + cy.visit(MOBILE_URL + "/Settings") }) - it('should be able to lifecycle through TOTP flows', () => { - cy.get('*[data-testid="field/totp_qr"]').should('exist') - cy.get('*[data-testid="field/totp_code"]').should('exist') + it("should be able to lifecycle through TOTP flows", () => { + cy.get('*[data-testid="field/totp_qr"]').should("exist") + cy.get('*[data-testid="field/totp_code"]').should("exist") // Set up TOTP with invalid key - cy.get('*[data-testid="field/totp_code"]').type('111111') + cy.get('*[data-testid="field/totp_code"]').type("111111") cy.get('*[data-testid="field/method/totp"]').click() cy.get('*[data-testid="field/totp_code"]').should( - 'contain.text', - 'The provided authentication code is invalid, please try again.' + "contain.text", + "The provided authentication code is invalid, please try again.", ) // Set up TOTP with valid key @@ -53,21 +53,21 @@ context('Mobile Profile', () => { // Form should look different now cy.get('*[data-testid="field/totp_secret_key/text"]').should( - 'not.exist' + "not.exist", ) - cy.get('*[data-testid="field/totp_code"]').should('not.exist') - cy.get('*[data-testid="field/totp_qr"]').should('not.exist') - cy.get('*[data-testid="field/totp_unlink/true"]').should('exist') + cy.get('*[data-testid="field/totp_code"]').should("not.exist") + cy.get('*[data-testid="field/totp_qr"]').should("not.exist") + cy.get('*[data-testid="field/totp_unlink/true"]').should("exist") // Lets sign in - cy.visit(MOBILE_URL + '/Login?aal=aal2&refresh=true') + cy.visit(MOBILE_URL + "/Login?aal=aal2&refresh=true") // First use a wrong code - cy.get('*[data-testid="field/totp_code"]').type('111111') + cy.get('*[data-testid="field/totp_code"]').type("111111") cy.get('*[data-testid="field/method/totp"]').click() cy.get('*[data-testid="form-messages"]').should( - 'contain.text', - 'The provided authentication code is invalid, please try again.' + "contain.text", + "The provided authentication code is invalid, please try again.", ) // Use the correct code @@ -77,15 +77,15 @@ context('Mobile Profile', () => { cy.get('*[data-testid="field/method/totp"]').click() // We have AAL now - cy.get('[data-testid="session-content"]').should('contain', 'aal2') - cy.get('[data-testid="session-content"]').should('contain', 'totp') + cy.get('[data-testid="session-content"]').should("contain", "aal2") + cy.get('[data-testid="session-content"]').should("contain", "totp") // Go back to settings and unlink - cy.visit(MOBILE_URL + '/Settings') + cy.visit(MOBILE_URL + "/Settings") cy.get('*[data-testid="field/totp_unlink/true"]').click() - cy.get('*[data-testid="field/totp_unlink/true"]').should('not.exist') - cy.get('*[data-testid="field/totp_qr"]').should('exist') - cy.get('*[data-testid="field/totp_code"]').should('exist') + cy.get('*[data-testid="field/totp_unlink/true"]').should("not.exist") + cy.get('*[data-testid="field/totp_qr"]').should("exist") + cy.get('*[data-testid="field/totp_code"]').should("exist") }) }) }) diff --git a/test/e2e/cypress/integration/profiles/mobile/registration/errors.spec.ts b/test/e2e/cypress/integration/profiles/mobile/registration/errors.spec.ts index c5e3d04cd93d..180a7b8da224 100644 --- a/test/e2e/cypress/integration/profiles/mobile/registration/errors.spec.ts +++ b/test/e2e/cypress/integration/profiles/mobile/registration/errors.spec.ts @@ -1,93 +1,93 @@ -import { gen, MOBILE_URL, website } from '../../../../helpers' +import { gen, MOBILE_URL, website } from "../../../../helpers" -context('Mobile Profile', () => { - describe('Registration Flow Errors', () => { +context("Mobile Profile", () => { + describe("Registration Flow Errors", () => { before(() => { - cy.useConfigProfile('mobile') + cy.useConfigProfile("mobile") }) beforeEach(() => { - cy.visit(MOBILE_URL + '/Registration') + cy.visit(MOBILE_URL + "/Registration") }) const email = gen.email() const password = gen.password() - describe('show errors when invalid signup data is used', () => { - it('should show an error when the password has leaked before', () => { + describe("show errors when invalid signup data is used", () => { + it("should show an error when the password has leaked before", () => { cy.get('input[data-testid="traits.email"]').type(email) - cy.get('input[data-testid="password"]').type('12345678') + cy.get('input[data-testid="password"]').type("12345678") cy.get('input[data-testid="traits.website"]').type(website) cy.get('div[data-testid="submit-form"]').click() cy.get('*[data-testid="field/password"]').should( - 'contain.text', - 'data breaches' + "contain.text", + "data breaches", ) }) - it('should show an error when the password is too similar', () => { + it("should show an error when the password is too similar", () => { cy.get('input[data-testid="traits.email"]').type(email) cy.get('input[data-testid="password"]').type(email) cy.get('input[data-testid="traits.website"]').type(website) cy.get('div[data-testid="submit-form"]').click() cy.get('*[data-testid="field/password"]').should( - 'contain.text', - 'too similar' + "contain.text", + "too similar", ) }) - it('should show an error when the password is empty', () => { + it("should show an error when the password is empty", () => { cy.get('input[data-testid="traits.website"]').type(website) cy.get('input[data-testid="traits.email"]').type(email) cy.get('div[data-testid="submit-form"]').click() cy.get('*[data-testid="field/password"]').should( - 'contain.text', - 'Property password is missing' + "contain.text", + "Property password is missing", ) }) - it('should show an error when the email is empty', () => { - cy.get('input[data-testid="traits.website"]').type('https://www.ory.sh') + it("should show an error when the email is empty", () => { + cy.get('input[data-testid="traits.website"]').type("https://www.ory.sh") cy.get('input[data-testid="password"]').type(password) cy.get('div[data-testid="submit-form"]').click() cy.get('*[data-testid="field/traits.email"]').should( - 'contain.text', - 'Property email is missing' + "contain.text", + "Property email is missing", ) }) - it('should show an error when the email is not an email', () => { - cy.get('input[data-testid="traits.website"]').type('https://www.ory.sh') - cy.get('input[data-testid="traits.email"]').type('not-an-email') + it("should show an error when the email is not an email", () => { + cy.get('input[data-testid="traits.website"]').type("https://www.ory.sh") + cy.get('input[data-testid="traits.email"]').type("not-an-email") cy.get('input[data-testid="password"]').type(password) cy.get('div[data-testid="submit-form"]').click() cy.get('*[data-testid="field/traits.email"]').should( - 'contain.text', - 'valid "email"' + "contain.text", + 'valid "email"', ) }) - it('should show a missing indicator if no fields are set', () => { + it("should show a missing indicator if no fields are set", () => { cy.get('div[data-testid="submit-form"]').click() cy.get('*[data-testid="field/password"]').should( - 'contain.text', - 'Property password is missing' + "contain.text", + "Property password is missing", ) }) - it('should show an error when the website is too short', () => { - cy.get('input[data-testid="traits.website"]').type('http://s') + it("should show an error when the website is too short", () => { + cy.get('input[data-testid="traits.website"]').type("http://s") cy.get('input[data-testid="traits.email"]').type(email) cy.get('div[data-testid="submit-form"]').click() cy.get('*[data-testid="field/traits.website"]').should( - 'contain.text', - 'length must be >= 10' + "contain.text", + "length must be >= 10", ) }) }) diff --git a/test/e2e/cypress/integration/profiles/mobile/registration/success.spec.ts b/test/e2e/cypress/integration/profiles/mobile/registration/success.spec.ts index 47af10321ace..06b1c842080b 100644 --- a/test/e2e/cypress/integration/profiles/mobile/registration/success.spec.ts +++ b/test/e2e/cypress/integration/profiles/mobile/registration/success.spec.ts @@ -1,16 +1,16 @@ -import { MOBILE_URL, gen, website } from '../../../../helpers' +import { MOBILE_URL, gen, website } from "../../../../helpers" -context('Mobile Profile', () => { - describe('Login Flow Success', () => { +context("Mobile Profile", () => { + describe("Login Flow Success", () => { before(() => { - cy.useConfigProfile('mobile') + cy.useConfigProfile("mobile") }) beforeEach(() => { - cy.visit(MOBILE_URL + '/Registration') + cy.visit(MOBILE_URL + "/Registration") }) - it('should sign up and be logged in', () => { + it("should sign up and be logged in", () => { const email = gen.email() const password = gen.password() @@ -19,8 +19,8 @@ context('Mobile Profile', () => { cy.get('input[data-testid="traits.website"]').type(website) cy.get('div[data-testid="submit-form"]').click() - cy.get('[data-testid="session-content"]').should('contain', email) - cy.get('[data-testid="session-token"]').should('not.be.empty') + cy.get('[data-testid="session-content"]').should("contain", email) + cy.get('[data-testid="session-token"]').should("not.be.empty") }) }) }) diff --git a/test/e2e/cypress/integration/profiles/mobile/settings/errors.spec.ts b/test/e2e/cypress/integration/profiles/mobile/settings/errors.spec.ts index 4a3a3b41dcb3..d159dff2eeaa 100644 --- a/test/e2e/cypress/integration/profiles/mobile/settings/errors.spec.ts +++ b/test/e2e/cypress/integration/profiles/mobile/settings/errors.spec.ts @@ -1,9 +1,9 @@ -import { gen, MOBILE_URL, website } from '../../../../helpers' +import { gen, MOBILE_URL, website } from "../../../../helpers" -context('Mobile Profile', () => { - describe('Settings Flow Errors', () => { +context("Mobile Profile", () => { + describe("Settings Flow Errors", () => { before(() => { - cy.useConfigProfile('mobile') + cy.useConfigProfile("mobile") }) let email, password @@ -11,35 +11,35 @@ context('Mobile Profile', () => { before(() => { email = gen.email() password = gen.password() - cy.registerApi({ email, password, fields: { 'traits.website': website } }) + cy.registerApi({ email, password, fields: { "traits.website": website } }) }) beforeEach(() => { cy.loginMobile({ email, password }) - cy.visit(MOBILE_URL + '/Settings') + cy.visit(MOBILE_URL + "/Settings") }) - describe('profile', () => { - it('fails with validation errors', () => { + describe("profile", () => { + it("fails with validation errors", () => { cy.get( - '*[data-testid="settings-profile"] input[data-testid="traits.website"]' + '*[data-testid="settings-profile"] input[data-testid="traits.website"]', ) .clear() - .type('http://s') + .type("http://s") cy.get( - '*[data-testid="settings-profile"] div[data-testid="submit-form"]' + '*[data-testid="settings-profile"] div[data-testid="submit-form"]', ).click() cy.get( - '*[data-testid="settings-profile"] div[data-testid="submit-form"]' - ).should('have.attr', 'data-focusable', 'true') + '*[data-testid="settings-profile"] div[data-testid="submit-form"]', + ).should("have.attr", "data-focusable", "true") cy.get('*[data-testid="field/traits.website"]').should( - 'contain.text', - 'length must be >= 10' + "contain.text", + "length must be >= 10", ) - cy.get('*[data-testid="settings-password"]').should('exist') + cy.get('*[data-testid="settings-password"]').should("exist") }) }) }) diff --git a/test/e2e/cypress/integration/profiles/mobile/settings/success.spec.ts b/test/e2e/cypress/integration/profiles/mobile/settings/success.spec.ts index 6e410350249b..193ce29475fa 100644 --- a/test/e2e/cypress/integration/profiles/mobile/settings/success.spec.ts +++ b/test/e2e/cypress/integration/profiles/mobile/settings/success.spec.ts @@ -1,14 +1,14 @@ -import { gen, MOBILE_URL, website } from '../../../../helpers' +import { gen, MOBILE_URL, website } from "../../../../helpers" -context('Mobile Profile', () => { - describe('Login Flow Success', () => { +context("Mobile Profile", () => { + describe("Login Flow Success", () => { before(() => { - cy.useConfigProfile('mobile') + cy.useConfigProfile("mobile") }) const up = (value) => `not-${value}` - describe('password', () => { + describe("password", () => { const email = gen.email() const password = gen.password() @@ -16,40 +16,40 @@ context('Mobile Profile', () => { cy.registerApi({ email, password, - fields: { 'traits.website': website } + fields: { "traits.website": website }, }) }) beforeEach(() => { cy.loginMobile({ email, password }) - cy.visit(MOBILE_URL + '/Settings') + cy.visit(MOBILE_URL + "/Settings") }) - it('modifies the password', () => { + it("modifies the password", () => { const newPassword = up(password) cy.get( - '*[data-testid="settings-password"] input[data-testid="password"]' + '*[data-testid="settings-password"] input[data-testid="password"]', ) .clear() .type(newPassword) cy.get( - '*[data-testid="settings-password"] div[data-testid="submit-form"]' + '*[data-testid="settings-password"] div[data-testid="submit-form"]', ).click() cy.get( - '*[data-testid="settings-password"] div[data-testid="submit-form"]' - ).should('have.attr', 'data-focusable', 'true') + '*[data-testid="settings-password"] div[data-testid="submit-form"]', + ).should("have.attr", "data-focusable", "true") cy.get('*[data-testid="logout"]').click() - cy.visit(MOBILE_URL + '/Home') + cy.visit(MOBILE_URL + "/Home") cy.loginMobile({ email, password }) - cy.get('[data-testid="session-token"]').should('not.exist') + cy.get('[data-testid="session-token"]').should("not.exist") cy.loginMobile({ email, password: newPassword }) - cy.get('[data-testid="session-token"]').should('not.be.empty') + cy.get('[data-testid="session-token"]').should("not.be.empty") }) }) - describe('profile', () => { + describe("profile", () => { const email = gen.email() const password = gen.password() @@ -57,51 +57,51 @@ context('Mobile Profile', () => { cy.registerApi({ email, password, - fields: { 'traits.website': website } + fields: { "traits.website": website }, }) }) beforeEach(() => { cy.loginMobile({ email, password }) - cy.visit(MOBILE_URL + '/Settings') + cy.visit(MOBILE_URL + "/Settings") }) - it('modifies an unprotected trait', () => { + it("modifies an unprotected trait", () => { cy.get( - '*[data-testid="settings-profile"] input[data-testid="traits.website"]' + '*[data-testid="settings-profile"] input[data-testid="traits.website"]', ) .clear() - .type('https://github.com/ory') + .type("https://github.com/ory") cy.get( - '*[data-testid="settings-profile"] div[data-testid="submit-form"]' + '*[data-testid="settings-profile"] div[data-testid="submit-form"]', ).click() cy.get( - '*[data-testid="settings-profile"] div[data-testid="submit-form"]' - ).should('have.attr', 'data-focusable', 'true') + '*[data-testid="settings-profile"] div[data-testid="submit-form"]', + ).should("have.attr", "data-focusable", "true") - cy.visit(MOBILE_URL + '/Home') + cy.visit(MOBILE_URL + "/Home") cy.get('[data-testid="session-content"]').should( - 'contain', - 'https://github.com/ory' + "contain", + "https://github.com/ory", ) }) - it('modifies a protected trait', () => { + it("modifies a protected trait", () => { const newEmail = up(email) cy.get( - '*[data-testid="settings-profile"] input[data-testid="traits.email"]' + '*[data-testid="settings-profile"] input[data-testid="traits.email"]', ) .clear() .type(newEmail) cy.get( - '*[data-testid="settings-profile"] div[data-testid="submit-form"]' + '*[data-testid="settings-profile"] div[data-testid="submit-form"]', ).click() cy.get( - '*[data-testid="settings-profile"] div[data-testid="submit-form"]' - ).should('have.attr', 'data-focusable', 'true') + '*[data-testid="settings-profile"] div[data-testid="submit-form"]', + ).should("have.attr", "data-focusable", "true") - cy.visit(MOBILE_URL + '/Home') - cy.get('[data-testid="session-content"]').should('contain', newEmail) + cy.visit(MOBILE_URL + "/Home") + cy.get('[data-testid="session-content"]').should("contain", newEmail) }) }) }) diff --git a/test/e2e/cypress/integration/profiles/network/errors.spec.ts b/test/e2e/cypress/integration/profiles/network/errors.spec.ts index f551106fb833..427f090d9c6e 100644 --- a/test/e2e/cypress/integration/profiles/network/errors.spec.ts +++ b/test/e2e/cypress/integration/profiles/network/errors.spec.ts @@ -1,51 +1,51 @@ -import { routes as express } from '../../../helpers/express' -import { gen } from '../../../helpers' +import { routes as express } from "../../../helpers/express" +import { gen } from "../../../helpers" -describe('Registration failures with email profile', () => { +describe("Registration failures with email profile", () => { before(() => { - cy.useConfigProfile('network') - cy.proxy('express') + cy.useConfigProfile("network") + cy.proxy("express") }) - it('should not be able to register if we need a localhost schema', () => { - cy.setDefaultIdentitySchema('localhost') + it("should not be able to register if we need a localhost schema", () => { + cy.setDefaultIdentitySchema("localhost") cy.visit(express.registration, { failOnStatusCode: false }) - cy.get('.code-box').should( - 'contain.text', - 'ip 127.0.0.1 is in the 127.0.0.0/8' + cy.get(".code-box").should( + "contain.text", + "ip 127.0.0.1 is in the 127.0.0.0/8", ) }) - it('should not be able to register if we schema has a local ref', () => { - cy.setDefaultIdentitySchema('ref') + it("should not be able to register if we schema has a local ref", () => { + cy.setDefaultIdentitySchema("ref") cy.visit(express.registration, { failOnStatusCode: false }) - cy.get('.code-box').should( - 'contain.text', - 'ip 192.168.178.1 is in the 192.168.0.0/16 range' + cy.get(".code-box").should( + "contain.text", + "ip 192.168.178.1 is in the 192.168.0.0/16 range", ) }) - it('should not be able to login because pre webhook uses local url', () => { - cy.setDefaultIdentitySchema('working') + it("should not be able to login because pre webhook uses local url", () => { + cy.setDefaultIdentitySchema("working") cy.visit(express.login, { failOnStatusCode: false }) - cy.get('.code-box').should( - 'contain.text', - 'ip 192.168.178.2 is in the 192.168.0.0/16 range' + cy.get(".code-box").should( + "contain.text", + "ip 192.168.178.2 is in the 192.168.0.0/16 range", ) }) - it('should not be able to verify because post webhook uses local jsonnet', () => { - cy.setDefaultIdentitySchema('working') + it("should not be able to verify because post webhook uses local jsonnet", () => { + cy.setDefaultIdentitySchema("working") cy.visit(express.registration, { failOnStatusCode: false }) cy.get('[data-testid="node/input/traits.email"] input').type(gen.email()) cy.get('[data-testid="node/input/traits.website"] input').type( - 'https://google.com/' + "https://google.com/", ) cy.get('[data-testid="node/input/password"] input').type(gen.password()) cy.get('[type="submit"]').click() - cy.get('.code-box').should( - 'contain.text', - 'ip 192.168.178.3 is in the 192.168.0.0/16 range' + cy.get(".code-box").should( + "contain.text", + "ip 192.168.178.3 is in the 192.168.0.0/16 range", ) }) }) diff --git a/test/e2e/cypress/integration/profiles/oidc/login/error.spec.ts b/test/e2e/cypress/integration/profiles/oidc/login/error.spec.ts index 47bb7dae43be..83d84c157e54 100644 --- a/test/e2e/cypress/integration/profiles/oidc/login/error.spec.ts +++ b/test/e2e/cypress/integration/profiles/oidc/login/error.spec.ts @@ -1,19 +1,19 @@ -import { appPrefix, gen, website } from '../../../../helpers' -import { routes as react } from '../../../../helpers/react' -import { routes as express } from '../../../../helpers/express' +import { appPrefix, gen, website } from "../../../../helpers" +import { routes as react } from "../../../../helpers/react" +import { routes as express } from "../../../../helpers/express" -context('Social Sign In Errors', () => { +context("Social Sign In Errors", () => { ;[ { login: react.login, - app: 'react' as 'react', - profile: 'spa' + app: "react" as "react", + profile: "spa", }, { login: express.login, - app: 'express' as 'express', - profile: 'oidc' - } + app: "express" as "express", + profile: "oidc", + }, ].forEach(({ login, profile, app }) => { describe(`for app ${app}`, () => { before(() => { @@ -26,62 +26,62 @@ context('Social Sign In Errors', () => { cy.visit(login) }) - it('should fail when the login request is rejected', () => { + it("should fail when the login request is rejected", () => { cy.triggerOidc(app) - cy.get('#reject').click() - cy.location('pathname').should('equal', '/login') + cy.get("#reject").click() + cy.location("pathname").should("equal", "/login") cy.get(appPrefix(app) + '[data-testid="ui/message/4000001"]').should( - 'contain.text', - 'login rejected request' + "contain.text", + "login rejected request", ) cy.noSession() }) - it('should fail when the consent request is rejected', () => { + it("should fail when the consent request is rejected", () => { const email = gen.email() cy.triggerOidc(app) - cy.get('#username').type(email) - cy.get('#accept').click() - cy.get('#reject').click() - cy.location('pathname').should('equal', '/login') + cy.get("#username").type(email) + cy.get("#accept").click() + cy.get("#reject").click() + cy.location("pathname").should("equal", "/login") cy.get('[data-testid="ui/message/4000001"]').should( - 'contain.text', - 'consent rejected request' + "contain.text", + "consent rejected request", ) cy.noSession() }) - it('should fail when the id_token is missing', () => { + it("should fail when the id_token is missing", () => { const email = gen.email() cy.triggerOidc(app) - cy.get('#username').type(email) - cy.get('#accept').click() - cy.get('#website').type(website) - cy.get('#accept').click() - cy.location('pathname').should('equal', '/login') + cy.get("#username").type(email) + cy.get("#accept").click() + cy.get("#website").type(website) + cy.get("#accept").click() + cy.location("pathname").should("equal", "/login") cy.get('[data-testid="ui/message/4000001"]').should( - 'contain.text', - 'no id_token' + "contain.text", + "no id_token", ) }) - it('should fail to convert a sign in flow to a sign up flow when registration is disabled', () => { + it("should fail to convert a sign in flow to a sign up flow when registration is disabled", () => { cy.disableRegistration() const email = gen.email() cy.visit(login) cy.triggerOidc(app) - cy.get('#username').clear().type(email) - cy.get('#remember').click() - cy.get('#accept').click() + cy.get("#username").clear().type(email) + cy.get("#remember").click() + cy.get("#accept").click() cy.get('[name="scope"]').each(($el) => cy.wrap($el).click()) - cy.get('#remember').click() - cy.get('#accept').click() + cy.get("#remember").click() + cy.get("#accept").click() cy.get('[data-testid="ui/message/4000001"]').should( - 'contain.text', - 'Registration is not allowed because it was disabled' + "contain.text", + "Registration is not allowed because it was disabled", ) cy.noSession() diff --git a/test/e2e/cypress/integration/profiles/oidc/login/success.spec.ts b/test/e2e/cypress/integration/profiles/oidc/login/success.spec.ts index 4abd1b77b60e..442185815075 100644 --- a/test/e2e/cypress/integration/profiles/oidc/login/success.spec.ts +++ b/test/e2e/cypress/integration/profiles/oidc/login/success.spec.ts @@ -1,21 +1,21 @@ -import { gen, website } from '../../../../helpers' -import { routes as react } from '../../../../helpers/react' -import { routes as express } from '../../../../helpers/express' +import { gen, website } from "../../../../helpers" +import { routes as react } from "../../../../helpers/react" +import { routes as express } from "../../../../helpers/express" -context('Social Sign In Successes', () => { +context("Social Sign In Successes", () => { ;[ { login: react.login, registration: react.registration, - app: 'react' as 'react', - profile: 'spa' + app: "react" as "react", + profile: "spa", }, { login: express.login, registration: express.registration, - app: 'express' as 'express', - profile: 'oidc' - } + app: "express" as "express", + profile: "oidc", + }, ].forEach(({ login, registration, profile, app }) => { describe(`for app ${app}`, () => { before(() => { @@ -27,7 +27,7 @@ context('Social Sign In Successes', () => { cy.clearAllCookies() }) - it('should be able to sign up, sign out, and then sign in', () => { + it("should be able to sign up, sign out, and then sign in", () => { const email = gen.email() cy.registerOidc({ email, website, route: registration }) cy.logout() @@ -35,18 +35,18 @@ context('Social Sign In Successes', () => { cy.loginOidc({ url: login }) }) - it('should be able to sign up with redirects', () => { + it("should be able to sign up with redirects", () => { const email = gen.email() cy.registerOidc({ email, website, - route: registration + '?return_to=https://www.example.org/' + route: registration + "?return_to=https://www.example.org/", }) - cy.location('href').should('eq', 'https://www.example.org/') + cy.location("href").should("eq", "https://www.example.org/") cy.logout() cy.noSession() - cy.loginOidc({ url: login + '?return_to=https://www.example.org/' }) - cy.location('href').should('eq', 'https://www.example.org/') + cy.loginOidc({ url: login + "?return_to=https://www.example.org/" }) + cy.location("href").should("eq", "https://www.example.org/") }) }) }) diff --git a/test/e2e/cypress/integration/profiles/oidc/logout/success.spec.ts b/test/e2e/cypress/integration/profiles/oidc/logout/success.spec.ts index 26efcf214201..ea4a07dd2091 100644 --- a/test/e2e/cypress/integration/profiles/oidc/logout/success.spec.ts +++ b/test/e2e/cypress/integration/profiles/oidc/logout/success.spec.ts @@ -1,21 +1,21 @@ -import { appPrefix, gen, website } from '../../../../helpers' -import { routes as react } from '../../../../helpers/react' -import { routes as express } from '../../../../helpers/express' +import { appPrefix, gen, website } from "../../../../helpers" +import { routes as react } from "../../../../helpers/react" +import { routes as express } from "../../../../helpers/express" -context('Social Sign Out Successes', () => { +context("Social Sign Out Successes", () => { ;[ { base: react.base, registration: react.registration, - app: 'react' as 'react', - profile: 'spa' + app: "react" as "react", + profile: "spa", }, { base: express.base, registration: express.registration, - app: 'express' as 'express', - profile: 'oidc' - } + app: "express" as "express", + profile: "oidc", + }, ].forEach(({ base, registration, profile, app }) => { describe(`for app ${app}`, () => { before(() => { @@ -33,10 +33,10 @@ context('Social Sign Out Successes', () => { cy.registerOidc({ email, website, route: registration }) }) - it('should sign out and be able to sign in again', () => { + it("should sign out and be able to sign in again", () => { cy.get(`${appPrefix(app)} [data-testid="logout"]:not(disabled)`).click() cy.noSession() - cy.url().should('include', '/login') + cy.url().should("include", "/login") }) }) }) diff --git a/test/e2e/cypress/integration/profiles/oidc/registration/error.spec.ts b/test/e2e/cypress/integration/profiles/oidc/registration/error.spec.ts index b323ef1dfb5e..793c67d0c760 100644 --- a/test/e2e/cypress/integration/profiles/oidc/registration/error.spec.ts +++ b/test/e2e/cypress/integration/profiles/oidc/registration/error.spec.ts @@ -1,19 +1,19 @@ -import { appPrefix, gen, website } from '../../../../helpers' -import { routes as react } from '../../../../helpers/react' -import { routes as express } from '../../../../helpers/express' +import { appPrefix, gen, website } from "../../../../helpers" +import { routes as react } from "../../../../helpers/react" +import { routes as express } from "../../../../helpers/express" -context('Social Sign Up Errors', () => { +context("Social Sign Up Errors", () => { ;[ { registration: react.registration, - app: 'react' as 'react', - profile: 'spa' + app: "react" as "react", + profile: "spa", }, { registration: express.registration, - app: 'express' as 'express', - profile: 'oidc' - } + app: "express" as "express", + profile: "oidc", + }, ].forEach(({ registration, profile, app }) => { describe(`for app ${app}`, () => { before(() => { @@ -26,42 +26,42 @@ context('Social Sign Up Errors', () => { cy.visit(registration) }) - it('should fail when the login request is rejected', () => { + it("should fail when the login request is rejected", () => { cy.triggerOidc(app) - cy.get('#reject').click() - cy.location('pathname').should('equal', '/registration') + cy.get("#reject").click() + cy.location("pathname").should("equal", "/registration") cy.get(appPrefix(app) + '[data-testid="ui/message/4000001"]').should( - 'contain.text', - 'login rejected request' + "contain.text", + "login rejected request", ) cy.noSession() }) - it('should fail when the consent request is rejected', () => { + it("should fail when the consent request is rejected", () => { const email = gen.email() cy.triggerOidc(app) - cy.get('#username').type(email) - cy.get('#accept').click() - cy.get('#reject').click() - cy.location('pathname').should('equal', '/registration') + cy.get("#username").type(email) + cy.get("#accept").click() + cy.get("#reject").click() + cy.location("pathname").should("equal", "/registration") cy.get('[data-testid="ui/message/4000001"]').should( - 'contain.text', - 'consent rejected request' + "contain.text", + "consent rejected request", ) cy.noSession() }) - it('should fail when the id_token is missing', () => { + it("should fail when the id_token is missing", () => { const email = gen.email() cy.triggerOidc(app) - cy.get('#username').type(email) - cy.get('#accept').click() - cy.get('#website').type(website) - cy.get('#accept').click() - cy.location('pathname').should('equal', '/registration') + cy.get("#username").type(email) + cy.get("#accept").click() + cy.get("#website").type(website) + cy.get("#accept").click() + cy.location("pathname").should("equal", "/registration") cy.get('[data-testid="ui/message/4000001"]').should( - 'contain.text', - 'no id_token' + "contain.text", + "no id_token", ) }) }) diff --git a/test/e2e/cypress/integration/profiles/oidc/registration/success.spec.ts b/test/e2e/cypress/integration/profiles/oidc/registration/success.spec.ts index bb0385a36f62..3536dc0b8a8f 100644 --- a/test/e2e/cypress/integration/profiles/oidc/registration/success.spec.ts +++ b/test/e2e/cypress/integration/profiles/oidc/registration/success.spec.ts @@ -1,21 +1,21 @@ -import { appPrefix, gen, website } from '../../../../helpers' -import { routes as react } from '../../../../helpers/react' -import { routes as express } from '../../../../helpers/express' +import { appPrefix, gen, website } from "../../../../helpers" +import { routes as react } from "../../../../helpers/react" +import { routes as express } from "../../../../helpers/express" -context('Social Sign Up Successes', () => { +context("Social Sign Up Successes", () => { ;[ { login: react.login, registration: react.registration, - app: 'react' as 'react', - profile: 'spa' + app: "react" as "react", + profile: "spa", }, { login: express.login, registration: express.registration, - app: 'express' as 'express', - profile: 'oidc' - } + app: "express" as "express", + profile: "oidc", + }, ].forEach(({ registration, login, profile, app }) => { describe(`for app ${app}`, () => { before(() => { @@ -27,7 +27,7 @@ context('Social Sign Up Successes', () => { cy.clearAllCookies() cy.visit(registration) cy.setIdentitySchema( - 'file://test/e2e/profiles/oidc/identity.traits.schema.json' + "file://test/e2e/profiles/oidc/identity.traits.schema.json", ) }) @@ -38,54 +38,54 @@ context('Social Sign Up Successes', () => { expect(identity.traits.email).to.equal(email) } - it('should be able to sign up with incomplete data and finally be signed in', () => { + it("should be able to sign up with incomplete data and finally be signed in", () => { const email = gen.email() cy.registerOidc({ email, expectSession: false, route: registration }) - cy.get('#registration-password').should('not.exist') + cy.get("#registration-password").should("not.exist") cy.get(appPrefix(app) + '[name="traits.email"]').should( - 'have.value', - email + "have.value", + email, ) cy.get('[data-testid="ui/message/4000002"]').should( - 'contain.text', - 'Property website is missing' + "contain.text", + "Property website is missing", ) cy.get('[name="traits.consent"][type="checkbox"]') - .siblings('label') + .siblings("label") .click() cy.get('[name="traits.newsletter"][type="checkbox"]') - .siblings('label') + .siblings("label") .click() - cy.get('[name="traits.website"]').type('http://s') + cy.get('[name="traits.website"]').type("http://s") cy.get('[name="provider"]') - .should('have.length', 1) - .should('have.value', 'hydra') - .should('contain.text', 'Continue') + .should("have.length", 1) + .should("have.value", "hydra") + .should("contain.text", "Continue") .click() - cy.get('#registration-password').should('not.exist') - cy.get('[name="traits.email"]').should('have.value', email) - cy.get('[name="traits.website"]').should('have.value', 'http://s') + cy.get("#registration-password").should("not.exist") + cy.get('[name="traits.email"]').should("have.value", email) + cy.get('[name="traits.website"]').should("have.value", "http://s") cy.get('[data-testid="ui/message/4000001"]').should( - 'contain.text', - 'length must be >= 10' + "contain.text", + "length must be >= 10", ) cy.get('[name="traits.website"]') - .should('have.value', 'http://s') + .should("have.value", "http://s") .clear() .type(website) - cy.get('[name="traits.consent"]').should('be.checked') - cy.get('[name="traits.newsletter"]').should('be.checked') + cy.get('[name="traits.consent"]').should("be.checked") + cy.get('[name="traits.newsletter"]').should("be.checked") cy.triggerOidc(app) - cy.location('pathname').should((loc) => { - expect(loc).to.be.oneOf(['/welcome', '/']) + cy.location("pathname").should((loc) => { + expect(loc).to.be.oneOf(["/welcome", "/"]) }) cy.getSession().should((session) => { @@ -94,14 +94,14 @@ context('Social Sign Up Successes', () => { }) }) - it('should be able to sign up with complete data', () => { + it("should be able to sign up with complete data", () => { const email = gen.email() cy.registerOidc({ email, website, route: registration }) cy.getSession().should(shouldSession(email)) }) - it('should be able to convert a sign up flow to a sign in flow', () => { + it("should be able to convert a sign up flow to a sign in flow", () => { const email = gen.email() cy.registerOidc({ email, website, route: registration }) @@ -110,63 +110,63 @@ context('Social Sign Up Successes', () => { cy.visit(registration) cy.triggerOidc(app) - cy.location('pathname').should((path) => { - expect(path).to.oneOf(['/', '/welcome']) + cy.location("pathname").should((path) => { + expect(path).to.oneOf(["/", "/welcome"]) }) cy.getSession().should(shouldSession(email)) }) - it('should be able to convert a sign in flow to a sign up flow', () => { + it("should be able to convert a sign in flow to a sign up flow", () => { cy.setIdentitySchema( - 'file://test/e2e/profiles/oidc/identity-required.traits.schema.json' + "file://test/e2e/profiles/oidc/identity-required.traits.schema.json", ) const email = gen.email() cy.visit(login) cy.triggerOidc(app) - cy.get('#username').clear().type(email) - cy.get('#remember').click() - cy.get('#accept').click() + cy.get("#username").clear().type(email) + cy.get("#remember").click() + cy.get("#accept").click() cy.get('[name="scope"]').each(($el) => cy.wrap($el).click()) - cy.get('#remember').click() - cy.get('#accept').click() + cy.get("#remember").click() + cy.get("#accept").click() cy.get('[data-testid="ui/message/4000002"]').should( - 'contain.text', - 'Property website is missing' + "contain.text", + "Property website is missing", ) - cy.get('[name="traits.website"]').type('http://s') + cy.get('[name="traits.website"]').type("http://s") cy.triggerOidc(app) cy.get('[data-testid="ui/message/4000001"]').should( - 'contain.text', - 'length must be >= 10' + "contain.text", + "length must be >= 10", ) - cy.get('[name="traits.requirednested"]').should('not.exist') - cy.get('[name="traits.requirednested.a"]').siblings('label').click() - cy.get('[name="traits.consent"]').siblings('label').click() + cy.get('[name="traits.requirednested"]').should("not.exist") + cy.get('[name="traits.requirednested.a"]').siblings("label").click() + cy.get('[name="traits.consent"]').siblings("label").click() cy.get('[name="traits.website"]') - .should('have.value', 'http://s') + .should("have.value", "http://s") .clear() .type(website) cy.triggerOidc(app) - cy.location('pathname').should('not.contain', '/registration') + cy.location("pathname").should("not.contain", "/registration") cy.getSession().should(shouldSession(email)) }) - it('should be able to sign up with redirects', () => { + it("should be able to sign up with redirects", () => { const email = gen.email() cy.registerOidc({ email, website, - route: registration + '?return_to=https://www.ory.sh/' + route: registration + "?return_to=https://www.ory.sh/", }) - cy.location('href').should('eq', 'https://www.ory.sh/') + cy.location("href").should("eq", "https://www.ory.sh/") cy.logout() }) }) diff --git a/test/e2e/cypress/integration/profiles/oidc/settings/error.spec.ts b/test/e2e/cypress/integration/profiles/oidc/settings/error.spec.ts index bcaf48ae13a4..efb08096611c 100644 --- a/test/e2e/cypress/integration/profiles/oidc/settings/error.spec.ts +++ b/test/e2e/cypress/integration/profiles/oidc/settings/error.spec.ts @@ -1,21 +1,21 @@ -import { APP_URL, appPrefix, gen, website } from '../../../../helpers' -import { routes as react } from '../../../../helpers/react' -import { routes as express } from '../../../../helpers/express' +import { APP_URL, appPrefix, gen, website } from "../../../../helpers" +import { routes as react } from "../../../../helpers/react" +import { routes as express } from "../../../../helpers/express" -context('Social Sign In Settings Errors', () => { +context("Social Sign In Settings Errors", () => { ;[ { registration: react.registration, settings: react.settings, - app: 'react' as 'react', - profile: 'spa' + app: "react" as "react", + profile: "spa", }, { registration: express.registration, settings: express.settings, - app: 'express' as 'express', - profile: 'oidc' - } + app: "express" as "express", + profile: "oidc", + }, ].forEach(({ registration, profile, app, settings }) => { describe(`for app ${app}`, () => { before(() => { @@ -32,20 +32,20 @@ context('Social Sign In Settings Errors', () => { email, expectSession: true, website, - route: registration + route: registration, }) cy.visit(settings) }) - describe('oidc', () => { - it('should fail to link google because id token is missing', () => { + describe("oidc", () => { + it("should fail to link google because id token is missing", () => { cy.get(appPrefix(app) + 'button[value="google"]').click() - cy.get('#remember').click() - cy.get('#accept').click() + cy.get("#remember").click() + cy.get("#accept").click() cy.get('[data-testid="ui/message/4000001"]').should( - 'contain.text', - 'Authentication failed because no id_token was returned. Please accept the "openid" permission and try again.' + "contain.text", + 'Authentication failed because no id_token was returned. Please accept the "openid" permission and try again.', ) }) }) diff --git a/test/e2e/cypress/integration/profiles/oidc/settings/success.spec.ts b/test/e2e/cypress/integration/profiles/oidc/settings/success.spec.ts index 4746520753ad..23ed564a439b 100644 --- a/test/e2e/cypress/integration/profiles/oidc/settings/success.spec.ts +++ b/test/e2e/cypress/integration/profiles/oidc/settings/success.spec.ts @@ -1,23 +1,23 @@ -import { appPrefix, gen, website } from '../../../../helpers' -import { routes as react } from '../../../../helpers/react' -import { routes as express } from '../../../../helpers/express' +import { appPrefix, gen, website } from "../../../../helpers" +import { routes as react } from "../../../../helpers/react" +import { routes as express } from "../../../../helpers/express" -context('Social Sign In Settings Success', () => { +context("Social Sign In Settings Success", () => { ;[ { registration: react.registration, settings: react.settings, login: react.login, - app: 'react' as 'react', - profile: 'spa' + app: "react" as "react", + profile: "spa", }, { registration: express.registration, settings: express.settings, login: express.login, - app: 'express' as 'express', - profile: 'oidc' - } + app: "express" as "express", + profile: "oidc", + }, ].forEach(({ registration, login, profile, app, settings }) => { describe(`for app ${app}`, () => { before(() => { @@ -32,16 +32,16 @@ context('Social Sign In Settings Success', () => { cy.visit(login) cy.get(appPrefix(app) + '[value="hydra"]').click() - cy.get('#username').type(email) - cy.get('#remember').click() - cy.get('#accept').click() + cy.get("#username").type(email) + cy.get("#remember").click() + cy.get("#accept").click() cy.get('input[name="traits.website"]').clear().type(website) - cy.triggerOidc(app, 'hydra') + cy.triggerOidc(app, "hydra") cy.get('[data-testid="ui/message/4000007"]').should( - 'contain.text', - 'An account with the same identifier' + "contain.text", + "An account with the same identifier", ) cy.noSession() @@ -55,53 +55,53 @@ context('Social Sign In Settings Success', () => { email, expectSession: true, website, - route: registration + route: registration, }) cy.visit(settings) }) - describe('oidc', () => { + describe("oidc", () => { beforeEach(() => { cy.longRecoveryLifespan() cy.longVerificationLifespan() cy.longPrivilegedSessionTime() }) - it('should show the correct options', () => { - cy.get('[value="hydra"]').should('not.exist') + it("should show the correct options", () => { + cy.get('[value="hydra"]').should("not.exist") cy.get('[value="google"]') - .should('have.attr', 'name', 'link') - .should('contain.text', 'Link google') + .should("have.attr", "name", "link") + .should("contain.text", "Link google") cy.get('[value="github"]') - .should('have.attr', 'name', 'link') - .should('contain.text', 'Link github') + .should("have.attr", "name", "link") + .should("contain.text", "Link github") }) - it('should show the unlink once password is set', () => { - cy.get('[value="hydra"]').should('not.exist') + it("should show the unlink once password is set", () => { + cy.get('[value="hydra"]').should("not.exist") cy.get('input[name="password"]').type(gen.password()) cy.get('button[value="password"]').click() cy.get('[value="hydra"]') - .should('have.attr', 'name', 'unlink') - .should('contain.text', 'Unlink hydra') + .should("have.attr", "name", "unlink") + .should("contain.text", "Unlink hydra") }) - it('should link google', () => { + it("should link google", () => { cy.get('[value="google"]').click() cy.get('input[name="scope"]').each(($el) => cy.wrap($el).click()) - cy.get('#remember').click() - cy.get('#accept').click() + cy.get("#remember").click() + cy.get("#accept").click() cy.visit(settings) cy.get('[value="google"]') - .should('have.attr', 'name', 'unlink') - .should('contain.text', 'Unlink google') + .should("have.attr", "name", "unlink") + .should("contain.text", "Unlink google") cy.logout() @@ -110,39 +110,39 @@ context('Social Sign In Settings Success', () => { cy.getSession() }) - it('should link google after re-auth', () => { + it("should link google after re-auth", () => { cy.shortPrivilegedSessionTime() cy.get('[value="google"]').click() - cy.location('pathname').should('equal', '/login') + cy.location("pathname").should("equal", "/login") cy.longPrivilegedSessionTime() cy.get('[value="hydra"]').click() // prompt=login means that we need to re-auth! - cy.get('#username').type(email) - cy.get('#accept').click() + cy.get("#username").type(email) + cy.get("#accept").click() // we re-authed, now we do the google oauth2 dance - cy.get('#username').type(gen.email()) - cy.get('#accept').click() + cy.get("#username").type(gen.email()) + cy.get("#accept").click() cy.get('input[name="scope"]').each(($el) => cy.wrap($el).click()) - cy.get('#accept').click() + cy.get("#accept").click() cy.expectSettingsSaved() cy.get('[value="google"]') - .should('have.attr', 'name', 'unlink') - .should('contain.text', 'Unlink google') + .should("have.attr", "name", "unlink") + .should("contain.text", "Unlink google") cy.visit(settings) cy.get('[value="google"]') - .should('have.attr', 'name', 'unlink') - .should('contain.text', 'Unlink google') + .should("have.attr", "name", "unlink") + .should("contain.text", "Unlink google") }) - it('should unlink hydra and no longer be able to sign in', () => { - cy.get('[value="hydra"]').should('not.exist') + it("should unlink hydra and no longer be able to sign in", () => { + cy.get('[value="hydra"]').should("not.exist") cy.get('input[name="password"]').type(gen.password()) cy.get('[value="password"]').click() cy.expectSettingsSaved() @@ -157,8 +157,8 @@ context('Social Sign In Settings Success', () => { hydraReauthFails() }) - it('should unlink hydra after reauth', () => { - cy.get('[value="hydra"]').should('not.exist') + it("should unlink hydra after reauth", () => { + cy.get('[value="hydra"]').should("not.exist") cy.get('input[name="password"]').type(gen.password()) cy.get('[value="password"]').click() @@ -169,12 +169,12 @@ context('Social Sign In Settings Success', () => { cy.get('[value="hydra"]').click() cy.longPrivilegedSessionTime() - cy.location('pathname').should('equal', '/login') + cy.location("pathname").should("equal", "/login") cy.get('[value="hydra"]').click() // prompt=login means that we need to re-auth! - cy.get('#username').type(email) - cy.get('#accept').click() + cy.get("#username").type(email) + cy.get("#accept").click() cy.expectSettingsSaved() hydraReauthFails() diff --git a/test/e2e/cypress/integration/profiles/passwordless/flows.spec.ts b/test/e2e/cypress/integration/profiles/passwordless/flows.spec.ts index e10be28b1235..ed3e25daa7e6 100644 --- a/test/e2e/cypress/integration/profiles/passwordless/flows.spec.ts +++ b/test/e2e/cypress/integration/profiles/passwordless/flows.spec.ts @@ -1,29 +1,29 @@ -import { appPrefix, gen } from '../../../helpers' -import { routes as express } from '../../../helpers/express' -import { routes as react } from '../../../helpers/react' +import { appPrefix, gen } from "../../../helpers" +import { routes as express } from "../../../helpers/express" +import { routes as react } from "../../../helpers/react" const signup = (registration: string, email = gen.email()) => { cy.visit(registration) - cy.get('[name="webauthn_register_displayname"]').type('key1') + cy.get('[name="webauthn_register_displayname"]').type("key1") cy.get('[name="traits.email"]').type(email) - cy.get('[name="traits.website"]').type('https://www.ory.sh') - cy.clickWebAuthButton('register') + cy.get('[name="traits.website"]').type("https://www.ory.sh") + cy.clickWebAuthButton("register") cy.getSession({ - expectAal: 'aal1', - expectMethods: ['webauthn'] + expectAal: "aal1", + expectMethods: ["webauthn"], }).then((session) => { expect(session.identity.traits.email).to.equal(email) - expect(session.identity.traits.website).to.equal('https://www.ory.sh') + expect(session.identity.traits.website).to.equal("https://www.ory.sh") }) } -context('Passwordless registration', () => { +context("Passwordless registration", () => { before(() => { - cy.task('resetCRI', {}) + cy.task("resetCRI", {}) }) after(() => { - cy.task('resetCRI', {}) + cy.task("resetCRI", {}) }) ;[ { @@ -31,17 +31,17 @@ context('Passwordless registration', () => { registration: express.registration, settings: react.settings, base: react.base, - app: 'react' as 'react', - profile: 'passwordless' + app: "react" as "react", + profile: "passwordless", }, { login: express.login, registration: express.registration, settings: express.settings, base: express.base, - app: 'express' as 'express', - profile: 'passwordless' - } + app: "express" as "express", + profile: "passwordless", + }, ].forEach(({ registration, login, profile, app, base, settings }) => { describe(`for app ${app}`, () => { let authenticator @@ -59,74 +59,74 @@ context('Passwordless registration', () => { }) after(() => { - cy.task('sendCRI', { - query: 'WebAuthn.removeVirtualAuthenticator', - opts: authenticator + cy.task("sendCRI", { + query: "WebAuthn.removeVirtualAuthenticator", + opts: authenticator, }) }) - it('should register after validation errors', () => { + it("should register after validation errors", () => { cy.visit(registration) cy.get(appPrefix(app) + '[name="webauthn_register_displayname"]').type( - 'key1' + "key1", ) - cy.get('[name="traits.website"]').type('b') - cy.clickWebAuthButton('register') + cy.get('[name="traits.website"]').type("b") + cy.clickWebAuthButton("register") - cy.get('[data-testid="ui/message/4000002"]').should('to.exist') - cy.get('[data-testid="ui/message/4000001"]').should('to.exist') - cy.get('[name="traits.website"]').should('have.value', 'b') + cy.get('[data-testid="ui/message/4000002"]').should("to.exist") + cy.get('[data-testid="ui/message/4000001"]').should("to.exist") + cy.get('[name="traits.website"]').should("have.value", "b") const email = gen.email() cy.get('[name="traits.email"]').type(email) - cy.clickWebAuthButton('register') + cy.clickWebAuthButton("register") - cy.get('[data-testid="ui/message/4000001"]').should('to.exist') - cy.get('[name="traits.website"]').should('have.value', 'b') - cy.get('[name="traits.email"]').should('have.value', email) - cy.get('[name="traits.website"]').clear().type('https://www.ory.sh') - cy.clickWebAuthButton('register') + cy.get('[data-testid="ui/message/4000001"]').should("to.exist") + cy.get('[name="traits.website"]').should("have.value", "b") + cy.get('[name="traits.email"]').should("have.value", email) + cy.get('[name="traits.website"]').clear().type("https://www.ory.sh") + cy.clickWebAuthButton("register") cy.getSession({ - expectAal: 'aal1', - expectMethods: ['webauthn'] + expectAal: "aal1", + expectMethods: ["webauthn"], }).then((session) => { expect(session.identity.traits.email).to.equal(email) - expect(session.identity.traits.website).to.equal('https://www.ory.sh') + expect(session.identity.traits.website).to.equal("https://www.ory.sh") }) }) - it('should be able to login with registered account', () => { + it("should be able to login with registered account", () => { const email = gen.email() signup(registration, email) cy.logout() cy.visit(login) cy.get('[name="identifier"]').type(email) cy.get('[value="webauthn"]').click() - cy.get('[data-testid="ui/message/1010012"]').should('to.exist') - cy.get('[name="password"]').should('to.not.exist') - cy.clickWebAuthButton('login') + cy.get('[data-testid="ui/message/1010012"]').should("to.exist") + cy.get('[name="password"]').should("to.not.exist") + cy.clickWebAuthButton("login") cy.getSession({ - expectAal: 'aal1', - expectMethods: ['webauthn'] + expectAal: "aal1", + expectMethods: ["webauthn"], }).then((session) => { expect(session.identity.traits.email).to.equal(email) - expect(session.identity.traits.website).to.equal('https://www.ory.sh') + expect(session.identity.traits.website).to.equal("https://www.ory.sh") }) }) - it('should not be able to unlink last security key', () => { + it("should not be able to unlink last security key", () => { const email = gen.email() signup(registration, email) cy.visit(settings) - cy.get('[name="webauthn_remove"]').should('not.exist') + cy.get('[name="webauthn_remove"]').should("not.exist") }) - it('should be able to link password and use both methods for sign in', () => { + it("should be able to link password and use both methods for sign in", () => { const email = gen.email() const password = gen.password() signup(registration, email) cy.visit(settings) - cy.get('[name="webauthn_remove"]').should('not.exist') + cy.get('[name="webauthn_remove"]').should("not.exist") cy.get('[name="password"]').type(password) cy.get('[value="password"]').click() cy.expectSettingsSaved() @@ -136,108 +136,108 @@ context('Passwordless registration', () => { cy.visit(login) cy.get('[name="identifier"]').type(email) cy.get('[value="webauthn"]').click() - cy.get('[data-testid="ui/message/4000015"]').should('to.exist') - cy.get('[name="identifier"]').should('exist') - cy.get('[name="password"]').should('exist') - cy.get('[value="password"]').should('exist') + cy.get('[data-testid="ui/message/4000015"]').should("to.exist") + cy.get('[name="identifier"]').should("exist") + cy.get('[name="password"]').should("exist") + cy.get('[value="password"]').should("exist") }) - it('should be able to refresh', () => { + it("should be able to refresh", () => { const email = gen.email() signup(registration, email) - cy.visit(login + '?refresh=true') - cy.get('[name="identifier"][type="hidden"]').should('exist') - cy.get('[name="identifier"][type="input"]').should('not.exist') - cy.get('[name="password"]').should('not.exist') - cy.get('[value="password"]').should('not.exist') - cy.clickWebAuthButton('login') + cy.visit(login + "?refresh=true") + cy.get('[name="identifier"][type="hidden"]').should("exist") + cy.get('[name="identifier"][type="input"]').should("not.exist") + cy.get('[name="password"]').should("not.exist") + cy.get('[value="password"]').should("not.exist") + cy.clickWebAuthButton("login") cy.getSession({ - expectAal: 'aal1', - expectMethods: ['webauthn', 'webauthn'] + expectAal: "aal1", + expectMethods: ["webauthn", "webauthn"], }).then((session) => { expect(session.identity.traits.email).to.equal(email) - expect(session.identity.traits.website).to.equal('https://www.ory.sh') + expect(session.identity.traits.website).to.equal("https://www.ory.sh") }) }) - it('should not be able to use for MFA', () => { + it("should not be able to use for MFA", () => { const email = gen.email() signup(registration, email) - cy.visit(login + '?aal=aal2') - cy.get('[value="webauthn"]').should('not.exist') - cy.get('[name="webauthn_login_trigger"]').should('not.exist') + cy.visit(login + "?aal=aal2") + cy.get('[value="webauthn"]').should("not.exist") + cy.get('[name="webauthn_login_trigger"]').should("not.exist") }) - it('should be able to add method later and try a variety of refresh flows', () => { + it("should be able to add method later and try a variety of refresh flows", () => { const email = gen.email() const password = gen.password() cy.visit(registration) cy.get('[name="traits.email"]').type(email) cy.get('[name="password"]').type(password) - cy.get('[name="traits.website"]').type('https://www.ory.sh') + cy.get('[name="traits.website"]').type("https://www.ory.sh") cy.get('[value="password"]').click() - cy.location('pathname').should('not.contain', '/registration') + cy.location("pathname").should("not.contain", "/registration") cy.getSession({ - expectAal: 'aal1', - expectMethods: ['password'] + expectAal: "aal1", + expectMethods: ["password"], }) cy.visit(settings) - cy.get('[name="webauthn_register_displayname"]').type('key2') - cy.clickWebAuthButton('register') + cy.get('[name="webauthn_register_displayname"]').type("key2") + cy.clickWebAuthButton("register") cy.expectSettingsSaved() - cy.visit(login + '?refresh=true') - cy.get('[name="password"]').should('exist') - cy.clickWebAuthButton('login') - cy.location('pathname').should('not.contain', '/login') + cy.visit(login + "?refresh=true") + cy.get('[name="password"]').should("exist") + cy.clickWebAuthButton("login") + cy.location("pathname").should("not.contain", "/login") cy.getSession({ - expectAal: 'aal1', - expectMethods: ['password', 'webauthn', 'webauthn'] + expectAal: "aal1", + expectMethods: ["password", "webauthn", "webauthn"], }) - cy.visit(login + '?refresh=true') + cy.visit(login + "?refresh=true") cy.get('[name="password"]').type(password) cy.get('[value="password"]').click() cy.getSession({ - expectAal: 'aal1', - expectMethods: ['password', 'webauthn', 'webauthn', 'password'] + expectAal: "aal1", + expectMethods: ["password", "webauthn", "webauthn", "password"], }) cy.logout() cy.visit(login) cy.get('[name="identifier"]').type(email) cy.get('[value="webauthn"]').click() - cy.clickWebAuthButton('login') + cy.clickWebAuthButton("login") cy.getSession({ - expectAal: 'aal1', - expectMethods: ['webauthn'] + expectAal: "aal1", + expectMethods: ["webauthn"], }) }) - it('should not be able to use for MFA even when passwordless is false', () => { + it("should not be able to use for MFA even when passwordless is false", () => { const email = gen.email() signup(registration, email) cy.updateConfigFile((config) => { config.selfservice.methods.webauthn.config.passwordless = false return config }) - cy.visit(login + '?aal=aal2') - cy.get('[value="webauthn"]').should('not.exist') - cy.get('[name="webauthn_login_trigger"]').should('not.exist') + cy.visit(login + "?aal=aal2") + cy.get('[value="webauthn"]').should("not.exist") + cy.get('[name="webauthn_login_trigger"]').should("not.exist") cy.visit(settings) - cy.get('[name="webauthn_remove"]').should('not.exist') - cy.get('[name="webauthn_register_displayname"]').type('key2') - cy.clickWebAuthButton('register') + cy.get('[name="webauthn_remove"]').should("not.exist") + cy.get('[name="webauthn_register_displayname"]').type("key2") + cy.clickWebAuthButton("register") cy.expectSettingsSaved() - cy.visit(login + '?aal=aal2&refresh=true') - cy.clickWebAuthButton('login') + cy.visit(login + "?aal=aal2&refresh=true") + cy.clickWebAuthButton("login") cy.getSession({ - expectAal: 'aal2', - expectMethods: ['webauthn', 'webauthn', 'webauthn'] + expectAal: "aal2", + expectMethods: ["webauthn", "webauthn", "webauthn"], }) }) }) diff --git a/test/e2e/cypress/integration/profiles/recovery/recovery/errors.spec.ts b/test/e2e/cypress/integration/profiles/recovery/recovery/errors.spec.ts index 0d98f2563c2a..4fafa0f14e1e 100644 --- a/test/e2e/cypress/integration/profiles/recovery/recovery/errors.spec.ts +++ b/test/e2e/cypress/integration/profiles/recovery/recovery/errors.spec.ts @@ -1,19 +1,19 @@ -import { APP_URL, appPrefix, gen, parseHtml } from '../../../../helpers' -import { routes as react } from '../../../../helpers/react' -import { routes as express } from '../../../../helpers/express' +import { APP_URL, appPrefix, gen, parseHtml } from "../../../../helpers" +import { routes as react } from "../../../../helpers/react" +import { routes as express } from "../../../../helpers/express" -context('Account Recovery Errors', () => { +context("Account Recovery Errors", () => { ;[ { recovery: react.recovery, - app: 'react' as 'react', - profile: 'spa' + app: "react" as "react", + profile: "spa", }, { recovery: express.recovery, - app: 'express' as 'express', - profile: 'recovery' - } + app: "express" as "express", + profile: "recovery", + }, ].forEach(({ recovery, profile, app }) => { describe(`for app ${app}`, () => { before(() => { @@ -30,7 +30,7 @@ context('Account Recovery Errors', () => { cy.enableRecovery() }) - it('responds with a HTML response on link click of an API flow if the link is expired', () => { + it("responds with a HTML response on link click of an API flow if the link is expired", () => { cy.visit(recovery) cy.shortLinkLifespan() @@ -41,18 +41,18 @@ context('Account Recovery Errors', () => { cy.recoverEmailButExpired({ expect: { email: identity.email } }) cy.get('[data-testid="ui/message/4060005"]').should( - 'contain.text', - 'The recovery flow expired' + "contain.text", + "The recovery flow expired", ) cy.noSession() }) - it('responds with a HTML response on link click of an API flow if the flow is expired', () => { + it("responds with a HTML response on link click of an API flow if the flow is expired", () => { cy.visit(recovery) cy.updateConfigFile((config) => { - config.selfservice.flows.recovery.lifespan = '1s' + config.selfservice.flows.recovery.lifespan = "1s" return config }) @@ -62,75 +62,75 @@ context('Account Recovery Errors', () => { cy.wait(1000) cy.getMail().should((message) => { - expect(message.subject).to.equal('Recover access to your account') + expect(message.subject).to.equal("Recover access to your account") expect(message.toAddresses[0].trim()).to.equal(identity.email) - const link = parseHtml(message.body).querySelector('a') + const link = parseHtml(message.body).querySelector("a") cy.longRecoveryLifespan() cy.visit(link.href) }) cy.get('[data-testid="ui/message/4060005"]').should( - 'contain.text', - 'The recovery flow expired' + "contain.text", + "The recovery flow expired", ) cy.noSession() }) - it('should receive a stub email when recovering a non-existent account', () => { + it("should receive a stub email when recovering a non-existent account", () => { cy.visit(recovery) const email = gen.email() cy.get(appPrefix(app) + 'input[name="email"]').type(email) cy.get('button[value="link"]').click() - cy.location('pathname').should('eq', '/recovery') + cy.location("pathname").should("eq", "/recovery") cy.get('[data-testid="ui/message/1060002"]').should( - 'have.text', - 'An email containing a recovery link has been sent to the email address you provided.' + "have.text", + "An email containing a recovery link has been sent to the email address you provided.", ) - cy.get('input[name="email"]').should('have.value', email) + cy.get('input[name="email"]').should("have.value", email) cy.getMail().should((message) => { - expect(message.subject).to.equal('Account access attempted') - expect(message.fromAddress.trim()).to.equal('no-reply@ory.kratos.sh') + expect(message.subject).to.equal("Account access attempted") + expect(message.fromAddress.trim()).to.equal("no-reply@ory.kratos.sh") expect(message.toAddresses).to.have.length(1) expect(message.toAddresses[0].trim()).to.equal(email) - const link = parseHtml(message.body).querySelector('a') + const link = parseHtml(message.body).querySelector("a") expect(link).to.be.null }) }) - it('should cause form errors', () => { + it("should cause form errors", () => { cy.visit(recovery) cy.get('button[value="link"]').click() cy.get('[data-testid="ui/message/4000002"]').should( - 'contain.text', - 'Property email is missing.' + "contain.text", + "Property email is missing.", ) - cy.get('[name="method"][value="link"]').should('exist') + cy.get('[name="method"][value="link"]').should("exist") }) - it('should cause non-repeating form errors after submitting empty form twice. see: #2512', () => { + it("should cause non-repeating form errors after submitting empty form twice. see: #2512", () => { cy.visit(recovery) cy.get('button[value="link"]').click() - cy.location('pathname').should('eq', '/recovery') + cy.location("pathname").should("eq", "/recovery") cy.get('button[value="link"]').click() cy.get('[data-testid="ui/message/4000002"]').should( - 'contain.text', - 'Property email is missing.' + "contain.text", + "Property email is missing.", ) - cy.get('form') + cy.get("form") .find('[data-testid="ui/message/4000002"]') - .should('have.length', 1) - cy.get('[name="method"][value="link"]').should('exist') + .should("have.length", 1) + cy.get('[name="method"][value="link"]').should("exist") }) - it('is unable to recover the email address if the code is expired', () => { + it("is unable to recover the email address if the code is expired", () => { cy.shortLinkLifespan() const identity = gen.identityWithWebsite() cy.registerApi(identity) @@ -138,37 +138,37 @@ context('Account Recovery Errors', () => { cy.recoverEmailButExpired({ expect: { email: identity.email } }) cy.get('[data-testid="ui/message/4060005"]').should( - 'contain.text', - 'The recovery flow expired' + "contain.text", + "The recovery flow expired", ) cy.noSession() }) - it('is unable to recover the account if the code is incorrect', () => { + it("is unable to recover the account if the code is incorrect", () => { const identity = gen.identityWithWebsite() cy.registerApi(identity) cy.recoverApi({ email: identity.email }) cy.getMail().then((mail) => { console.log(mail) - const link = parseHtml(mail.body).querySelector('a') - cy.visit(link.href + '-not') // add random stuff to the confirm challenge + const link = parseHtml(mail.body).querySelector("a") + cy.visit(link.href + "-not") // add random stuff to the confirm challenge cy.get('[data-testid="ui/message/4060004"]').should( - 'have.text', - 'The recovery token is invalid or has already been used. Please retry the flow.' + "have.text", + "The recovery token is invalid or has already been used. Please retry the flow.", ) cy.noSession() }) }) - it('is unable to recover the account using the token twice', () => { + it("is unable to recover the account using the token twice", () => { const identity = gen.identityWithWebsite() cy.registerApi(identity) cy.recoverApi({ email: identity.email }) cy.getMail().then((mail) => { - const link = parseHtml(mail.body).querySelector('a') + const link = parseHtml(mail.body).querySelector("a") // Workaround for cypress cy.visit limitation. cy.request(link.href).should((response) => { @@ -180,21 +180,21 @@ context('Account Recovery Errors', () => { cy.visit(link.href) cy.get('[data-testid="ui/message/4060004"]').should( - 'have.text', - 'The recovery token is invalid or has already been used. Please retry the flow.' + "have.text", + "The recovery token is invalid or has already been used. Please retry the flow.", ) cy.noSession() }) }) - it('invalid remote recovery email template', () => { + it("invalid remote recovery email template", () => { cy.remoteCourierRecoveryTemplates() const identity = gen.identityWithWebsite() cy.recoverApi({ email: identity.email }) cy.getMail().then((mail) => { expect(mail.body).to.include( - 'this is a remote invalid recovery template' + "this is a remote invalid recovery template", ) }) }) diff --git a/test/e2e/cypress/integration/profiles/recovery/recovery/success.spec.ts b/test/e2e/cypress/integration/profiles/recovery/recovery/success.spec.ts index 15fd59aed50c..20a00bcdf6a5 100644 --- a/test/e2e/cypress/integration/profiles/recovery/recovery/success.spec.ts +++ b/test/e2e/cypress/integration/profiles/recovery/recovery/success.spec.ts @@ -1,21 +1,21 @@ -import { appPrefix, assertRecoveryAddress, gen } from '../../../../helpers' -import { routes as react } from '../../../../helpers/react' -import { routes as express } from '../../../../helpers/express' +import { appPrefix, assertRecoveryAddress, gen } from "../../../../helpers" +import { routes as react } from "../../../../helpers/react" +import { routes as express } from "../../../../helpers/express" -context('Account Recovery Success', () => { +context("Account Recovery Success", () => { ;[ { recovery: react.recovery, base: react.base, - app: 'react' as 'react', - profile: 'spa' + app: "react" as "react", + profile: "spa", }, { recovery: express.recovery, base: express.base, - app: 'express' as 'express', - profile: 'recovery' - } + app: "express" as "express", + profile: "recovery", + }, ].forEach(({ recovery, profile, base, app }) => { describe(`for app ${app}`, () => { before(() => { @@ -37,19 +37,19 @@ context('Account Recovery Success', () => { cy.registerApi(identity) }) - it('should contain the recovery address in the session', () => { + it("should contain the recovery address in the session", () => { cy.visit(recovery) cy.login({ ...identity, cookieUrl: base }) cy.getSession().should(assertRecoveryAddress(identity)) }) - it('should perform a recovery flow', () => { + it("should perform a recovery flow", () => { cy.recoverApi({ email: identity.email }) cy.recoverEmail({ expect: identity }) cy.getSession() - cy.location('pathname').should('eq', '/settings') + cy.location("pathname").should("eq", "/settings") const newPassword = gen.password() cy.get(appPrefix(app) + 'input[name="password"]') @@ -57,23 +57,23 @@ context('Account Recovery Success', () => { .type(newPassword) cy.get('button[value="password"]').click() cy.expectSettingsSaved() - cy.get('input[name="password"]').should('be.empty') + cy.get('input[name="password"]').should("be.empty") cy.logout() cy.login({ email: identity.email, password: newPassword, - cookieUrl: base + cookieUrl: base, }) }) }) }) - it('should recover, set password and be redirected', () => { - const app = 'express' as 'express' + it("should recover, set password and be redirected", () => { + const app = "express" as "express" cy.deleteMail() - cy.useConfigProfile('recovery') + cy.useConfigProfile("recovery") cy.proxy(app) cy.deleteMail() @@ -85,25 +85,25 @@ context('Account Recovery Success', () => { const identity = gen.identityWithWebsite() cy.registerApi(identity) - cy.recoverApi({ email: identity.email, returnTo: 'https://www.ory.sh/' }) + cy.recoverApi({ email: identity.email, returnTo: "https://www.ory.sh/" }) cy.recoverEmail({ expect: identity }) cy.getSession() - cy.location('pathname').should('eq', '/settings') + cy.location("pathname").should("eq", "/settings") cy.get(appPrefix(app) + 'input[name="password"]') .clear() .type(gen.password()) cy.get('button[value="password"]').click() - cy.url().should('eq', 'https://www.ory.sh/') + cy.url().should("eq", "https://www.ory.sh/") }) - it('should recover even if already logged into another account', () => { - const app = 'express' as 'express' + it("should recover even if already logged into another account", () => { + const app = "express" as "express" cy.deleteMail() - cy.useConfigProfile('recovery') + cy.useConfigProfile("recovery") cy.proxy(app) cy.deleteMail() @@ -124,14 +124,14 @@ context('Account Recovery Success', () => { cy.get('input[name="password"]').type(identity1.password) cy.get('button[value="password"]').click() - cy.location('pathname').should('not.contain', '/login') + cy.location("pathname").should("not.contain", "/login") // then recover identity2, while still logged in as identity1 cy.recoverEmail({ expect: identity2 }) cy.getSession() - cy.location('pathname').should('eq', '/settings') - cy.get('input[name="traits.email"]').should('have.value', identity2.email) + cy.location("pathname").should("eq", "/settings") + cy.get('input[name="traits.email"]').should("have.value", identity2.email) }) }) diff --git a/test/e2e/cypress/integration/profiles/recovery/settings/success.spec.ts b/test/e2e/cypress/integration/profiles/recovery/settings/success.spec.ts index 8d931b67026e..e6cfd2103324 100644 --- a/test/e2e/cypress/integration/profiles/recovery/settings/success.spec.ts +++ b/test/e2e/cypress/integration/profiles/recovery/settings/success.spec.ts @@ -1,21 +1,21 @@ -import { appPrefix, assertRecoveryAddress, gen } from '../../../../helpers' -import { routes as react } from '../../../../helpers/react' -import { routes as express } from '../../../../helpers/express' +import { appPrefix, assertRecoveryAddress, gen } from "../../../../helpers" +import { routes as react } from "../../../../helpers/react" +import { routes as express } from "../../../../helpers/express" -context('Account Recovery Success', () => { +context("Account Recovery Success", () => { ;[ { settings: react.settings, base: react.base, - app: 'react' as 'react', - profile: 'spa' + app: "react" as "react", + profile: "spa", }, { settings: express.settings, base: express.base, - app: 'express' as 'express', - profile: 'recovery' - } + app: "express" as "express", + profile: "recovery", + }, ].forEach(({ settings, profile, base, app }) => { describe(`for app ${app}`, () => { before(() => { @@ -38,7 +38,7 @@ context('Account Recovery Success', () => { cy.login({ ...identity, cookieUrl: base }) }) - it('should update the recovery address when updating the email', () => { + it("should update the recovery address when updating the email", () => { cy.visit(settings) const email = gen.email() cy.get(appPrefix(app) + 'input[name="traits.email"]') @@ -46,12 +46,12 @@ context('Account Recovery Success', () => { .type(email) cy.get('button[value="profile"]').click() cy.expectSettingsSaved() - cy.get('input[name="traits.email"]').should('contain.value', email) + cy.get('input[name="traits.email"]').should("contain.value", email) cy.getSession().should(assertRecoveryAddress({ email })) }) - xit('should not show an immediate error when a recovery address already exists', () => { + xit("should not show an immediate error when a recovery address already exists", () => { // account enumeration prevention, needs to be implemented. }) }) diff --git a/test/e2e/cypress/integration/profiles/verification/login/errors.spec.ts b/test/e2e/cypress/integration/profiles/verification/login/errors.spec.ts index 560953f7207a..708de14430d4 100644 --- a/test/e2e/cypress/integration/profiles/verification/login/errors.spec.ts +++ b/test/e2e/cypress/integration/profiles/verification/login/errors.spec.ts @@ -1,19 +1,19 @@ -import { appPrefix, gen } from '../../../../helpers' -import { routes as react } from '../../../../helpers/react' -import { routes as express } from '../../../../helpers/express' +import { appPrefix, gen } from "../../../../helpers" +import { routes as react } from "../../../../helpers/react" +import { routes as express } from "../../../../helpers/express" -context('Account Verification Login Errors', () => { +context("Account Verification Login Errors", () => { ;[ { login: react.login, - app: 'react' as 'react', - profile: 'verification' + app: "react" as "react", + profile: "verification", }, { login: express.login, - app: 'express' as 'express', - profile: 'verification' - } + app: "express" as "express", + profile: "verification", + }, ].forEach(({ profile, login, app }) => { describe(`for app ${app}`, () => { before(() => { @@ -23,7 +23,7 @@ context('Account Verification Login Errors', () => { cy.proxy(app) }) - it('is unable to login as long as the email is not verified', () => { + it("is unable to login as long as the email is not verified", () => { cy.deleteMail() const identity = gen.identityWithWebsite() @@ -35,7 +35,7 @@ context('Account Verification Login Errors', () => { cy.get('[value="password"]').click() cy.get('[data-testid="ui/message/4000010"]').contains( - 'Account not active yet' + "Account not active yet", ) cy.noSession() diff --git a/test/e2e/cypress/integration/profiles/verification/login/success.spec.ts b/test/e2e/cypress/integration/profiles/verification/login/success.spec.ts index 9bb83bc704ee..58247bdda0b0 100644 --- a/test/e2e/cypress/integration/profiles/verification/login/success.spec.ts +++ b/test/e2e/cypress/integration/profiles/verification/login/success.spec.ts @@ -1,19 +1,19 @@ -import { appPrefix, gen } from '../../../../helpers' -import { routes as react } from '../../../../helpers/react' -import { routes as express } from '../../../../helpers/express' +import { appPrefix, gen } from "../../../../helpers" +import { routes as react } from "../../../../helpers/react" +import { routes as express } from "../../../../helpers/express" -context('Account Verification Login Success', () => { +context("Account Verification Login Success", () => { ;[ { login: react.login, - app: 'react' as 'react', - profile: 'verification' + app: "react" as "react", + profile: "verification", }, { login: express.login, - app: 'express' as 'express', - profile: 'verification' - } + app: "express" as "express", + profile: "verification", + }, ].forEach(({ profile, login, app }) => { describe(`for app ${app}`, () => { before(() => { @@ -23,7 +23,7 @@ context('Account Verification Login Success', () => { cy.proxy(app) }) - it('is able to login after successful email verification', () => { + it("is able to login after successful email verification", () => { cy.deleteMail() const identity = gen.identityWithWebsite() @@ -36,7 +36,7 @@ context('Account Verification Login Success', () => { cy.get('input[name="password"]').type(identity.password) cy.get('button[value="password"]').click() - cy.location('pathname').should('not.contain', '/login') + cy.location("pathname").should("not.contain", "/login") cy.getSession() }) diff --git a/test/e2e/cypress/integration/profiles/verification/registration/errors.spec.ts b/test/e2e/cypress/integration/profiles/verification/registration/errors.spec.ts index b45193f83c56..948b0c029b0a 100644 --- a/test/e2e/cypress/integration/profiles/verification/registration/errors.spec.ts +++ b/test/e2e/cypress/integration/profiles/verification/registration/errors.spec.ts @@ -3,24 +3,24 @@ import { assertVerifiableAddress, gen, parseHtml, - verifyHrefPattern -} from '../../../../helpers' + verifyHrefPattern, +} from "../../../../helpers" -import { routes as react } from '../../../../helpers/react' -import { routes as express } from '../../../../helpers/express' +import { routes as react } from "../../../../helpers/react" +import { routes as express } from "../../../../helpers/express" -context('Account Verification Registration Errors', () => { +context("Account Verification Registration Errors", () => { ;[ { login: react.login, - app: 'react' as 'react', - profile: 'verification' + app: "react" as "react", + profile: "verification", }, { login: express.login, - app: 'express' as 'express', - profile: 'verification' - } + app: "express" as "express", + profile: "verification", + }, ].forEach(({ profile, login, app }) => { describe(`for app ${app}`, () => { before(() => { @@ -43,38 +43,38 @@ context('Account Verification Registration Errors', () => { cy.login(identity) }) - it('is unable to verify the email address if the code is no longer valid and resend the code', () => { + it("is unable to verify the email address if the code is no longer valid and resend the code", () => { cy.shortLinkLifespan() cy.verifyEmailButExpired({ - expect: { email: identity.email, password: identity.password } + expect: { email: identity.email, password: identity.password }, }) cy.longLinkLifespan() - cy.get(appPrefix(app) + 'input[name="email"]').should('be.empty') + cy.get(appPrefix(app) + 'input[name="email"]').should("be.empty") cy.get('input[name="email"]').type(identity.email) cy.get('button[value="link"]').click() cy.get('[data-testid="ui/message/1080001"]').should( - 'contain.text', - 'An email containing a verification' + "contain.text", + "An email containing a verification", ) cy.verifyEmail({ - expect: { email: identity.email, password: identity.password } + expect: { email: identity.email, password: identity.password }, }) }) - it('is unable to verify the email address if the code is incorrect', () => { + it("is unable to verify the email address if the code is incorrect", () => { cy.getMail().then((mail) => { - const link = parseHtml(mail.body).querySelector('a') + const link = parseHtml(mail.body).querySelector("a") expect(verifyHrefPattern.test(link.href)).to.be.true - cy.visit(link.href + '-not') // add random stuff to the confirm challenge + cy.visit(link.href + "-not") // add random stuff to the confirm challenge cy.getSession().should((session) => assertVerifiableAddress({ isVerified: false, - email: identity.email - })(session) + email: identity.email, + })(session), ) }) }) diff --git a/test/e2e/cypress/integration/profiles/verification/registration/success.spec.ts b/test/e2e/cypress/integration/profiles/verification/registration/success.spec.ts index fe0eaa77af71..f3064b3df286 100644 --- a/test/e2e/cypress/integration/profiles/verification/registration/success.spec.ts +++ b/test/e2e/cypress/integration/profiles/verification/registration/success.spec.ts @@ -1,20 +1,20 @@ -import { assertVerifiableAddress, gen } from '../../../../helpers' +import { assertVerifiableAddress, gen } from "../../../../helpers" -import { routes as react } from '../../../../helpers/react' -import { routes as express } from '../../../../helpers/express' +import { routes as react } from "../../../../helpers/react" +import { routes as express } from "../../../../helpers/express" -context('Account Verification Registration Success', () => { +context("Account Verification Registration Success", () => { ;[ { registration: react.registration, - app: 'react' as 'react', - profile: 'verification' + app: "react" as "react", + profile: "verification", }, { registration: express.registration, - app: 'express' as 'express', - profile: 'verification' - } + app: "express" as "express", + profile: "verification", + }, ].forEach(({ profile, registration, app }) => { describe(`for app ${app}`, () => { before(() => { @@ -35,7 +35,7 @@ context('Account Verification Registration Success', () => { const up = (value) => `up-${value}` const { email, password } = gen.identity() - it('is able to verify the email address after sign up', () => { + it("is able to verify the email address after sign up", () => { const identity = gen.identityWithWebsite() const { email, password } = identity cy.registerApi(identity) @@ -43,14 +43,14 @@ context('Account Verification Registration Success', () => { cy.getSession().should((session) => assertVerifiableAddress({ isVerified: false, - email - })(session) + email, + })(session), ) cy.verifyEmail({ expect: { email, password } }) }) - xit('sends the warning email on double sign up', () => { + xit("sends the warning email on double sign up", () => { // FIXME https://github.com/ory/kratos/issues/133 cy.clearAllCookies() cy.register({ email, password: up(password) }) @@ -60,7 +60,7 @@ context('Account Verification Registration Success', () => { cy.verifyEmail({ expect: { email, password } }) }) - it('is redirected to after_verification_return_to after verification', () => { + it("is redirected to after_verification_return_to after verification", () => { cy.clearAllCookies() const { email, password } = gen.identity() cy.register({ @@ -68,16 +68,16 @@ context('Account Verification Registration Success', () => { password, query: { after_verification_return_to: - 'http://localhost:4455/verification_callback' - } + "http://localhost:4455/verification_callback", + }, }) cy.login({ email, password }) cy.verifyEmail({ expect: { email, password, - redirectTo: 'http://localhost:4455/verification_callback' - } + redirectTo: "http://localhost:4455/verification_callback", + }, }) }) }) diff --git a/test/e2e/cypress/integration/profiles/verification/settings/error.spec.ts b/test/e2e/cypress/integration/profiles/verification/settings/error.spec.ts index 6065f9eb4629..8967b9bd1250 100644 --- a/test/e2e/cypress/integration/profiles/verification/settings/error.spec.ts +++ b/test/e2e/cypress/integration/profiles/verification/settings/error.spec.ts @@ -3,26 +3,26 @@ import { assertVerifiableAddress, gen, parseHtml, - verifyHrefPattern -} from '../../../../helpers' + verifyHrefPattern, +} from "../../../../helpers" -import { routes as react } from '../../../../helpers/react' -import { routes as express } from '../../../../helpers/express' +import { routes as react } from "../../../../helpers/react" +import { routes as express } from "../../../../helpers/express" -context('Account Verification Settings Error', () => { +context("Account Verification Settings Error", () => { ;[ { settings: react.settings, base: react.base, - app: 'react' as 'react', - profile: 'verification' + app: "react" as "react", + profile: "verification", }, { settings: express.settings, base: express.base, - app: 'express' as 'express', - profile: 'verification' - } + app: "express" as "express", + profile: "verification", + }, ].forEach(({ profile, settings, app, base }) => { describe(`for app ${app}`, () => { before(() => { @@ -31,7 +31,7 @@ context('Account Verification Settings Error', () => { cy.proxy(app) }) - describe('error flow', () => { + describe("error flow", () => { let identity before(() => { cy.deleteMail() @@ -48,7 +48,7 @@ context('Account Verification Settings Error', () => { cy.visit(settings) }) - it('is unable to verify the email address if the code is no longer valid', () => { + it("is unable to verify the email address if the code is no longer valid", () => { cy.shortLinkLifespan() cy.visit(settings) @@ -59,29 +59,29 @@ context('Account Verification Settings Error', () => { cy.get('button[value="profile"]').click() cy.verifyEmailButExpired({ - expect: { email, password: identity.password } + expect: { email, password: identity.password }, }) }) - it('is unable to verify the email address if the code is incorrect', () => { + it("is unable to verify the email address if the code is incorrect", () => { const email = `not-${identity.email}` cy.get('input[name="traits.email"]').clear().type(email) cy.get('button[value="profile"]').click() cy.getMail().then((mail) => { - const link = parseHtml(mail.body).querySelector('a') + const link = parseHtml(mail.body).querySelector("a") expect(verifyHrefPattern.test(link.href)).to.be.true - cy.visit(link.href + '-not') // add random stuff to the confirm challenge + cy.visit(link.href + "-not") // add random stuff to the confirm challenge cy.log(link.href) cy.getSession().then( - assertVerifiableAddress({ isVerified: false, email }) + assertVerifiableAddress({ isVerified: false, email }), ) }) }) - xit('should not update the traits until the email has been verified and the old email has accepted the change', () => { + xit("should not update the traits until the email has been verified and the old email has accepted the change", () => { // FIXME https://github.com/ory/kratos/issues/292 }) }) diff --git a/test/e2e/cypress/integration/profiles/verification/settings/success.spec.ts b/test/e2e/cypress/integration/profiles/verification/settings/success.spec.ts index ce0ad1e48218..cbd78400b5c2 100644 --- a/test/e2e/cypress/integration/profiles/verification/settings/success.spec.ts +++ b/test/e2e/cypress/integration/profiles/verification/settings/success.spec.ts @@ -2,23 +2,23 @@ import { APP_URL, appPrefix, assertVerifiableAddress, - gen -} from '../../../../helpers' -import { routes as react } from '../../../../helpers/react' -import { routes as express } from '../../../../helpers/express' + gen, +} from "../../../../helpers" +import { routes as react } from "../../../../helpers/react" +import { routes as express } from "../../../../helpers/express" -context('Account Verification Settings Success', () => { +context("Account Verification Settings Success", () => { ;[ { settings: react.settings, - app: 'react' as 'react', - profile: 'verification' + app: "react" as "react", + profile: "verification", }, { settings: express.settings, - app: 'express' as 'express', - profile: 'verification' - } + app: "express" as "express", + profile: "verification", + }, ].forEach(({ profile, settings, app }) => { describe(`for app ${app}`, () => { before(() => { @@ -41,22 +41,22 @@ context('Account Verification Settings Success', () => { cy.visit(settings) }) - it('should update the verify address and request a verification email', () => { + it("should update the verify address and request a verification email", () => { const email = `not-${identity.email}` cy.get(appPrefix(app) + 'input[name="traits.email"]') .clear() .type(email) cy.get('[value="profile"]').click() cy.expectSettingsSaved() - cy.get('input[name="traits.email"]').should('contain.value', email) + cy.get('input[name="traits.email"]').should("contain.value", email) cy.getSession().then( - assertVerifiableAddress({ isVerified: false, email }) + assertVerifiableAddress({ isVerified: false, email }), ) cy.verifyEmail({ expect: { email } }) }) - xit('should should be able to allow or deny (and revert?) the address change', () => { + xit("should should be able to allow or deny (and revert?) the address change", () => { // FIXME https://github.com/ory/kratos/issues/292 }) }) diff --git a/test/e2e/cypress/integration/profiles/verification/verify/errors.spec.ts b/test/e2e/cypress/integration/profiles/verification/verify/errors.spec.ts index a9418784b6f7..586f2da9390d 100644 --- a/test/e2e/cypress/integration/profiles/verification/verify/errors.spec.ts +++ b/test/e2e/cypress/integration/profiles/verification/verify/errors.spec.ts @@ -3,25 +3,25 @@ import { assertVerifiableAddress, gen, parseHtml, - verifyHrefPattern -} from '../../../../helpers' -import { routes as react } from '../../../../helpers/react' -import { routes as express } from '../../../../helpers/express' + verifyHrefPattern, +} from "../../../../helpers" +import { routes as react } from "../../../../helpers/react" +import { routes as express } from "../../../../helpers/express" -context('Account Verification Error', () => { +context("Account Verification Error", () => { ;[ { verification: react.verification, base: react.base, - app: 'react' as 'react', - profile: 'verification' + app: "react" as "react", + profile: "verification", }, { verification: express.verification, base: express.base, - app: 'express' as 'express', - profile: 'verification' - } + app: "express" as "express", + profile: "verification", + }, ].forEach(({ profile, verification, app, base }) => { describe(`for app ${app}`, () => { before(() => { @@ -43,53 +43,53 @@ context('Account Verification Error', () => { cy.visit(verification) }) - it('responds with a HTML response on link click of an API flow if the flow is expired', () => { + it("responds with a HTML response on link click of an API flow if the flow is expired", () => { cy.updateConfigFile((config) => { - config.selfservice.flows.verification.lifespan = '1s' + config.selfservice.flows.verification.lifespan = "1s" return config }) cy.verificationApi({ - email: identity.email + email: identity.email, }) cy.wait(1000) cy.shortVerificationLifespan() cy.getMail().then((message) => { - expect(message.subject).to.equal('Please verify your email address') + expect(message.subject).to.equal("Please verify your email address") expect(message.toAddresses[0].trim()).to.equal(identity.email) - const link = parseHtml(message.body).querySelector('a') + const link = parseHtml(message.body).querySelector("a") cy.longVerificationLifespan() cy.visit(link.href) cy.get('[data-testid="ui/message/4070005"]').should( - 'contain.text', - 'verification flow expired' + "contain.text", + "verification flow expired", ) cy.getSession().should((session) => { assertVerifiableAddress({ isVerified: false, - email: identity.email + email: identity.email, })(session) }) }) }) - it('responds with a HTML response on link click of an API flow if the link is expired', () => { + it("responds with a HTML response on link click of an API flow if the link is expired", () => { cy.shortLinkLifespan() // Init expired flow cy.verificationApi({ - email: identity.email + email: identity.email, }) cy.verifyEmailButExpired({ expect: { email: identity.email } }) }) - it('is unable to verify the email address if the code is expired', () => { + it("is unable to verify the email address if the code is expired", () => { cy.shortLinkLifespan() cy.visit(verification) @@ -97,43 +97,43 @@ context('Account Verification Error', () => { cy.get('button[value="link"]').click() cy.get('[data-testid="ui/message/1080001"]').should( - 'contain.text', - 'An email containing a verification' + "contain.text", + "An email containing a verification", ) - cy.get('[name="method"][value="link"]').should('exist') + cy.get('[name="method"][value="link"]').should("exist") cy.verifyEmailButExpired({ expect: { email: identity.email } }) }) - it('is unable to verify the email address if the code is incorrect', () => { + it("is unable to verify the email address if the code is incorrect", () => { cy.get('input[name="email"]').type(identity.email) cy.get('button[value="link"]').click() cy.get('[data-testid="ui/message/1080001"]').should( - 'contain.text', - 'An email containing a verification' + "contain.text", + "An email containing a verification", ) cy.getMail().then((mail) => { - const link = parseHtml(mail.body).querySelector('a') + const link = parseHtml(mail.body).querySelector("a") expect(verifyHrefPattern.test(link.href)).to.be.true - cy.visit(link.href + '-not') // add random stuff to the confirm challenge + cy.visit(link.href + "-not") // add random stuff to the confirm challenge cy.getSession().then( assertVerifiableAddress({ isVerified: false, - email: identity.email - }) + email: identity.email, + }), ) }) }) - it('unable to verify non-existent account', async () => { + it("unable to verify non-existent account", async () => { cy.get('input[name="email"]').type(gen.identity().email) cy.get('button[value="link"]').click() cy.getMail().then((mail) => { expect(mail.subject).eq( - 'Someone tried to verify this email address (remote)' + "Someone tried to verify this email address (remote)", ) }) }) diff --git a/test/e2e/cypress/integration/profiles/verification/verify/success.spec.ts b/test/e2e/cypress/integration/profiles/verification/verify/success.spec.ts index 58d540ed9c63..367e144f4e64 100644 --- a/test/e2e/cypress/integration/profiles/verification/verify/success.spec.ts +++ b/test/e2e/cypress/integration/profiles/verification/verify/success.spec.ts @@ -1,19 +1,19 @@ -import { APP_URL, assertVerifiableAddress, gen } from '../../../../helpers' -import { routes as react } from '../../../../helpers/react' -import { routes as express } from '../../../../helpers/express' +import { APP_URL, assertVerifiableAddress, gen } from "../../../../helpers" +import { routes as react } from "../../../../helpers/react" +import { routes as express } from "../../../../helpers/express" -context('Account Verification Settings Success', () => { +context("Account Verification Settings Success", () => { ;[ { verification: react.verification, - app: 'react' as 'react', - profile: 'verification' + app: "react" as "react", + profile: "verification", }, { verification: express.verification, - app: 'express' as 'express', - profile: 'verification' - } + app: "express" as "express", + profile: "verification", + }, ].forEach(({ profile, verification, app }) => { describe(`for app ${app}`, () => { before(() => { @@ -33,45 +33,45 @@ context('Account Verification Settings Success', () => { cy.visit(verification) }) - it('should request verification and receive an email and verify it', () => { + it("should request verification and receive an email and verify it", () => { cy.get('input[name="email"]').type(identity.email) cy.get('button[value="link"]').click() cy.get('[data-testid="ui/message/1080001"]').should( - 'contain.text', - 'An email containing a verification' + "contain.text", + "An email containing a verification", ) - cy.get('[name="method"][value="link"]').should('exist') + cy.get('[name="method"][value="link"]').should("exist") cy.verifyEmail({ expect: { email: identity.email } }) }) - it('should request verification for an email that does not exist yet', () => { + it("should request verification for an email that does not exist yet", () => { const email = `not-${identity.email}` cy.get('input[name="email"]').type(email) cy.get('button[value="link"]').click() cy.get('[data-testid="ui/message/1080001"]').should( - 'contain.text', - 'An email containing a verification' + "contain.text", + "An email containing a verification", ) cy.getMail().should((message) => { expect(message.subject.trim()).to.equal( - 'Someone tried to verify this email address' + "Someone tried to verify this email address", ) - expect(message.fromAddress.trim()).to.equal('no-reply@ory.kratos.sh') + expect(message.fromAddress.trim()).to.equal("no-reply@ory.kratos.sh") expect(message.toAddresses).to.have.length(1) expect(message.toAddresses[0].trim()).to.equal(email) }) cy.getSession().then( - assertVerifiableAddress({ isVerified: false, email: identity.email }) + assertVerifiableAddress({ isVerified: false, email: identity.email }), ) }) - it('should not verify email when clicking on link received on different address', () => { + it("should not verify email when clicking on link received on different address", () => { cy.get('input[name="email"]').type(identity.email) cy.get('button[value="link"]').click() @@ -87,7 +87,7 @@ context('Account Verification Settings Success', () => { cy.login(identity2) - cy.visit(APP_URL + '/verification') + cy.visit(APP_URL + "/verification") // request verification link for identity cy.get('input[name="email"]').type(identity.email) @@ -97,11 +97,14 @@ context('Account Verification Settings Success', () => { // expect current session to still not have a verified email address cy.getSession().should( - assertVerifiableAddress({ email: identity2.email, isVerified: false }) + assertVerifiableAddress({ + email: identity2.email, + isVerified: false, + }), ) }) - it('should redirect to return_to after completing verification', () => { + it("should redirect to return_to after completing verification", () => { cy.clearAllCookies() // registered with other email address const identity2 = gen.identity() @@ -110,8 +113,8 @@ context('Account Verification Settings Success', () => { cy.login(identity2) - cy.visit(APP_URL + '/self-service/verification/browser', { - qs: { return_to: 'http://localhost:4455/verification_callback' } + cy.visit(APP_URL + "/self-service/verification/browser", { + qs: { return_to: "http://localhost:4455/verification_callback" }, }) // request verification link for identity cy.get('input[name="email"]').type(identity2.email) @@ -119,8 +122,8 @@ context('Account Verification Settings Success', () => { cy.verifyEmail({ expect: { email: identity2.email, - redirectTo: 'http://localhost:4455/verification_callback' - } + redirectTo: "http://localhost:4455/verification_callback", + }, }) }) }) diff --git a/test/e2e/cypress/integration/profiles/webhoooks/login/error.spec.ts b/test/e2e/cypress/integration/profiles/webhoooks/login/error.spec.ts index acd6b9b649a8..6a30594b70fd 100644 --- a/test/e2e/cypress/integration/profiles/webhoooks/login/error.spec.ts +++ b/test/e2e/cypress/integration/profiles/webhoooks/login/error.spec.ts @@ -1,13 +1,13 @@ -import { gen } from '../../../../helpers' -import { routes as express } from '../../../../helpers/express' +import { gen } from "../../../../helpers" +import { routes as express } from "../../../../helpers/express" -describe('Basic email profile with failing login flows with webhooks', () => { +describe("Basic email profile with failing login flows with webhooks", () => { ;[ { route: express.login, - app: 'express' as 'express', - profile: 'webhooks' - } + app: "express" as "express", + profile: "webhooks", + }, ].forEach(({ route, profile, app }) => { describe(`for app ${app}`, () => { before(() => { @@ -20,7 +20,7 @@ describe('Basic email profile with failing login flows with webhooks', () => { cy.visit(route) }) - it('should show fail to sign in when webhooks rejects login', () => { + it("should show fail to sign in when webhooks rejects login", () => { const email = gen.blockedEmail() const password = gen.password() @@ -30,8 +30,8 @@ describe('Basic email profile with failing login flows with webhooks', () => { cy.submitPasswordForm() cy.get('*[data-testid="ui/message/1234"]').should( - 'contain.text', - 'email could not be validated' + "contain.text", + "email could not be validated", ) }) }) diff --git a/test/e2e/cypress/integration/profiles/webhoooks/login/success.spec.ts b/test/e2e/cypress/integration/profiles/webhoooks/login/success.spec.ts index deb4a544df02..99f950e8d84d 100644 --- a/test/e2e/cypress/integration/profiles/webhoooks/login/success.spec.ts +++ b/test/e2e/cypress/integration/profiles/webhoooks/login/success.spec.ts @@ -1,19 +1,19 @@ -import { APP_URL, appPrefix, gen, website } from '../../../../helpers' -import { routes as express } from '../../../../helpers/express' +import { APP_URL, appPrefix, gen, website } from "../../../../helpers" +import { routes as express } from "../../../../helpers/express" -describe('Basic email profile with succeeding login flows with webhooks', () => { +describe("Basic email profile with succeeding login flows with webhooks", () => { const email = gen.email() const password = gen.password() before(() => { - cy.registerApi({ email, password, fields: { 'traits.website': website } }) + cy.registerApi({ email, password, fields: { "traits.website": website } }) }) ;[ { route: express.login, - app: 'express' as 'express', - profile: 'webhooks' - } + app: "express" as "express", + profile: "webhooks", + }, ].forEach(({ route, profile, app }) => { describe(`for app ${app}`, () => { before(() => { @@ -26,16 +26,16 @@ describe('Basic email profile with succeeding login flows with webhooks', () => cy.visit(route) }) - it('should sign in and be logged in', () => { + it("should sign in and be logged in", () => { cy.get(`${appPrefix(app)}input[name="identifier"]`).type(email) cy.get('input[name="password"]').type(password) cy.submitPasswordForm() - cy.location('pathname').should('not.contain', '/login') + cy.location("pathname").should("not.contain", "/login") cy.getSession().should((session) => { const { identity } = session expect(identity.id).to.not.be.empty - expect(identity.schema_id).to.equal('default') + expect(identity.schema_id).to.equal("default") expect(identity.schema_url).to.equal(`${APP_URL}/schemas/ZGVmYXVsdA`) expect(identity.traits.email).to.equal(email) }) diff --git a/test/e2e/cypress/integration/profiles/webhoooks/registration/errors.spec.ts b/test/e2e/cypress/integration/profiles/webhoooks/registration/errors.spec.ts index 4bd2637a9134..98a6704c4eb1 100644 --- a/test/e2e/cypress/integration/profiles/webhoooks/registration/errors.spec.ts +++ b/test/e2e/cypress/integration/profiles/webhoooks/registration/errors.spec.ts @@ -1,13 +1,13 @@ -import { gen } from '../../../../helpers' -import { routes as express } from '../../../../helpers/express' +import { gen } from "../../../../helpers" +import { routes as express } from "../../../../helpers/express" -describe('Registration failures with email profile with webhooks', () => { +describe("Registration failures with email profile with webhooks", () => { ;[ { route: express.registration, - app: 'express' as 'express', - profile: 'webhooks' - } + app: "express" as "express", + profile: "webhooks", + }, ].forEach(({ route, profile, app }) => { describe(`for app ${app}`, () => { before(() => { @@ -22,18 +22,18 @@ describe('Registration failures with email profile with webhooks', () => { const blockedIdentity = gen.blockedEmail() const password = gen.password() - it('should show an error when the webhook is blocking registration', () => { + it("should show an error when the webhook is blocking registration", () => { cy.get('input[name="traits.email"]').type(blockedIdentity) cy.get('input[name="password"]').type(password) cy.submitPasswordForm() cy.get('input[name="traits.email"]').should( - 'have.value', - blockedIdentity + "have.value", + blockedIdentity, ) cy.get('*[data-testid="ui/message/1234"]').should( - 'contain.text', - 'email could not be validated' + "contain.text", + "email could not be validated", ) }) }) diff --git a/test/e2e/cypress/integration/profiles/webhoooks/registration/success.spec.ts b/test/e2e/cypress/integration/profiles/webhoooks/registration/success.spec.ts index b9d8bc5f6a52..026020699ed5 100644 --- a/test/e2e/cypress/integration/profiles/webhoooks/registration/success.spec.ts +++ b/test/e2e/cypress/integration/profiles/webhoooks/registration/success.spec.ts @@ -1,13 +1,13 @@ -import { APP_URL, appPrefix, gen } from '../../../../helpers' -import { routes as express } from '../../../../helpers/express' +import { APP_URL, appPrefix, gen } from "../../../../helpers" +import { routes as express } from "../../../../helpers/express" -context('Registration success with email profile with webhooks', () => { +context("Registration success with email profile with webhooks", () => { ;[ { route: express.registration, - app: 'express' as 'express', - profile: 'webhooks' - } + app: "express" as "express", + profile: "webhooks", + }, ].forEach(({ route, profile, app }) => { describe(`for app ${app}`, () => { before(() => { @@ -20,21 +20,21 @@ context('Registration success with email profile with webhooks', () => { cy.visit(route) }) - it('should sign up and be logged in', () => { + it("should sign up and be logged in", () => { const email = gen.email() const password = gen.password() - cy.get(appPrefix(app) + 'input[name="traits"]').should('not.exist') + cy.get(appPrefix(app) + 'input[name="traits"]').should("not.exist") cy.get('input[name="traits.email"]').type(email) cy.get('input[name="password"]').type(password) cy.submitPasswordForm() - cy.get('pre').should('contain.text', email) + cy.get("pre").should("contain.text", email) cy.getSession().should((session) => { const { identity } = session expect(identity.id).to.not.be.empty - expect(identity.schema_id).to.equal('default') + expect(identity.schema_id).to.equal("default") expect(identity.schema_url).to.equal(`${APP_URL}/schemas/ZGVmYXVsdA`) expect(identity.traits.email).to.equal(email) }) diff --git a/test/e2e/cypress/plugins/index.js b/test/e2e/cypress/plugins/index.js index 6f7c44ee22a2..c62ffbe0b5ff 100644 --- a/test/e2e/cypress/plugins/index.js +++ b/test/e2e/cypress/plugins/index.js @@ -1,7 +1,7 @@ /// -const got = require('got') -const CRI = require('chrome-remote-interface') +const got = require("got") +const CRI = require("chrome-remote-interface") let criPort = 0, criClient = null @@ -15,11 +15,11 @@ module.exports = (on) => { function ensureRdpPort(args) { const existing = args.find( - (arg) => arg.slice(0, 23) === '--remote-debugging-port' + (arg) => arg.slice(0, 23) === "--remote-debugging-port", ) if (existing) { - return Number(existing.split('=')[1]) + return Number(existing.split("=")[1]) } const port = 40000 + Math.round(Math.random() * 25000) diff --git a/test/e2e/cypress/support/commands.ts b/test/e2e/cypress/support/commands.ts index deb093b2d462..e80e0fc69205 100644 --- a/test/e2e/cypress/support/commands.ts +++ b/test/e2e/cypress/support/commands.ts @@ -8,19 +8,19 @@ import { MOBILE_URL, parseHtml, pollInterval, - privilegedLifespan -} from '../helpers' + privilegedLifespan, +} from "../helpers" -import dayjs from 'dayjs' -import YAML from 'yamljs' -import { Session } from '@ory/kratos-client' +import dayjs from "dayjs" +import YAML from "yamljs" +import { Session } from "@ory/kratos-client" -const configFile = 'kratos.generated.yml' +const configFile = "kratos.generated.yml" const mergeFields = (form, fields) => { const result = {} form.nodes.forEach(({ attributes, type }) => { - if (type === 'input') { + if (type === "input") { result[attributes.name] = attributes.value } }) @@ -30,12 +30,12 @@ const mergeFields = (form, fields) => { function checkConfigVersion(previous, tries = 0) { cy.wait(50) - cy.request('GET', KRATOS_ADMIN + '/health/config').then(({ body }) => { + cy.request("GET", KRATOS_ADMIN + "/health/config").then(({ body }) => { if (previous !== body) { return } else if (tries > 8) { console.warn( - 'Config version did not change after 5 tries, maybe the changes did not have an effect?' + "Config version did not change after 5 tries, maybe the changes did not have an effect?", ) return } @@ -45,7 +45,7 @@ function checkConfigVersion(previous, tries = 0) { } const updateConfigFile = (cb: (arg: any) => any) => { - cy.request('GET', KRATOS_ADMIN + '/health/config').then(({ body }) => { + cy.request("GET", KRATOS_ADMIN + "/health/config").then(({ body }) => { cy.readFile(configFile).then((contents) => { cy.writeFile(configFile, YAML.stringify(cb(YAML.parse(contents)))) cy.wait(500) @@ -54,34 +54,34 @@ const updateConfigFile = (cb: (arg: any) => any) => { }) } -Cypress.Commands.add('useConfigProfile', (profile: string) => { - cy.request('GET', KRATOS_ADMIN + '/health/config').then(({ body }) => { - console.log('Switching config profile to:', profile) +Cypress.Commands.add("useConfigProfile", (profile: string) => { + cy.request("GET", KRATOS_ADMIN + "/health/config").then(({ body }) => { + console.log("Switching config profile to:", profile) cy.readFile(`kratos.${profile}.yml`).then((contents) => - cy.writeFile(configFile, contents) + cy.writeFile(configFile, contents), ) checkConfigVersion(body) }) }) -Cypress.Commands.add('proxy', (app: string) => { - console.log('Switching proxy profile to:', app) +Cypress.Commands.add("proxy", (app: string) => { + console.log("Switching proxy profile to:", app) cy.writeFile(`proxy.json`, `"${app}"`) - cy.request(APP_URL + '/') - .its('body', { log: false }) + cy.request(APP_URL + "/") + .its("body", { log: false }) .then((body) => { expect(body.indexOf(`data-testid="app-${app}"`) > -1).to.be.true }) }) -Cypress.Commands.add('shortPrivilegedSessionTime', ({} = {}) => { +Cypress.Commands.add("shortPrivilegedSessionTime", ({} = {}) => { updateConfigFile((config) => { - config.selfservice.flows.settings.privileged_session_max_age = '1ms' + config.selfservice.flows.settings.privileged_session_max_age = "1ms" return config }) }) -Cypress.Commands.add('setIdentitySchema', (schema: string) => { +Cypress.Commands.add("setIdentitySchema", (schema: string) => { updateConfigFile((config) => { const id = gen.password() config.identity.default_schema_id = id @@ -89,189 +89,189 @@ Cypress.Commands.add('setIdentitySchema', (schema: string) => { ...(config.identity.schemas || []), { id, - url: schema - } + url: schema, + }, ] return config }) }) -Cypress.Commands.add('setDefaultIdentitySchema', (id: string) => { +Cypress.Commands.add("setDefaultIdentitySchema", (id: string) => { updateConfigFile((config) => { config.identity.default_schema_id = id return config }) }) -Cypress.Commands.add('longPrivilegedSessionTime', ({} = {}) => { +Cypress.Commands.add("longPrivilegedSessionTime", ({} = {}) => { updateConfigFile((config) => { - config.selfservice.flows.settings.privileged_session_max_age = '5m' + config.selfservice.flows.settings.privileged_session_max_age = "5m" return config }) }) -Cypress.Commands.add('longVerificationLifespan', ({} = {}) => { +Cypress.Commands.add("longVerificationLifespan", ({} = {}) => { updateConfigFile((config) => { - config.selfservice.flows.verification.lifespan = '1m' + config.selfservice.flows.verification.lifespan = "1m" return config }) }) -Cypress.Commands.add('shortVerificationLifespan', ({} = {}) => { +Cypress.Commands.add("shortVerificationLifespan", ({} = {}) => { updateConfigFile((config) => { - config.selfservice.flows.verification.lifespan = '1ms' + config.selfservice.flows.verification.lifespan = "1ms" return config }) }) -Cypress.Commands.add('sessionRequiresNo2fa', ({} = {}) => { +Cypress.Commands.add("sessionRequiresNo2fa", ({} = {}) => { updateConfigFile((config) => { - config.session.whoami.required_aal = 'aal1' + config.session.whoami.required_aal = "aal1" return config }) }) -Cypress.Commands.add('sessionRequires2fa', ({} = {}) => { +Cypress.Commands.add("sessionRequires2fa", ({} = {}) => { updateConfigFile((config) => { - config.session.whoami.required_aal = 'highest_available' + config.session.whoami.required_aal = "highest_available" return config }) }) -Cypress.Commands.add('shortLinkLifespan', ({} = {}) => { +Cypress.Commands.add("shortLinkLifespan", ({} = {}) => { updateConfigFile((config) => { - config.selfservice.methods.link.config.lifespan = '1ms' + config.selfservice.methods.link.config.lifespan = "1ms" return config }) }) -Cypress.Commands.add('longLinkLifespan', ({} = {}) => { +Cypress.Commands.add("longLinkLifespan", ({} = {}) => { updateConfigFile((config) => { - config.selfservice.methods.link.config.lifespan = '1m' + config.selfservice.methods.link.config.lifespan = "1m" return config }) }) -Cypress.Commands.add('longRecoveryLifespan', ({} = {}) => { +Cypress.Commands.add("longRecoveryLifespan", ({} = {}) => { updateConfigFile((config) => { - config.selfservice.flows.recovery.lifespan = '1m' + config.selfservice.flows.recovery.lifespan = "1m" return config }) }) -Cypress.Commands.add('enableLoginForVerifiedAddressOnly', () => { +Cypress.Commands.add("enableLoginForVerifiedAddressOnly", () => { updateConfigFile((config) => { - config.selfservice.flows.login['after'] = { - password: { hooks: [{ hook: 'require_verified_address' }] } + config.selfservice.flows.login["after"] = { + password: { hooks: [{ hook: "require_verified_address" }] }, } return config }) }) -Cypress.Commands.add('shortLoginLifespan', ({} = {}) => { +Cypress.Commands.add("shortLoginLifespan", ({} = {}) => { updateConfigFile((config) => { - config.selfservice.flows.login.lifespan = '100ms' + config.selfservice.flows.login.lifespan = "100ms" return config }) }) -Cypress.Commands.add('longLoginLifespan', ({} = {}) => { +Cypress.Commands.add("longLoginLifespan", ({} = {}) => { updateConfigFile((config) => { - config.selfservice.flows.login.lifespan = '1h' + config.selfservice.flows.login.lifespan = "1h" return config }) }) -Cypress.Commands.add('shortRecoveryLifespan', ({} = {}) => { +Cypress.Commands.add("shortRecoveryLifespan", ({} = {}) => { updateConfigFile((config) => { - config.selfservice.flows.recovery.lifespan = '1ms' + config.selfservice.flows.recovery.lifespan = "1ms" return config }) }) -Cypress.Commands.add('requireStrictAal', () => { +Cypress.Commands.add("requireStrictAal", () => { updateConfigFile((config) => { - config.selfservice.flows.settings.required_aal = 'highest_available' - config.session.whoami.required_aal = 'highest_available' + config.selfservice.flows.settings.required_aal = "highest_available" + config.session.whoami.required_aal = "highest_available" return config }) }) -Cypress.Commands.add('useLaxAal', ({} = {}) => { +Cypress.Commands.add("useLaxAal", ({} = {}) => { updateConfigFile((config) => { - config.selfservice.flows.settings.required_aal = 'aal1' - config.session.whoami.required_aal = 'aal1' + config.selfservice.flows.settings.required_aal = "aal1" + config.session.whoami.required_aal = "aal1" return config }) }) -Cypress.Commands.add('disableVerification', ({} = {}) => { +Cypress.Commands.add("disableVerification", ({} = {}) => { updateConfigFile((config) => { config.selfservice.flows.verification.enabled = false return config }) }) -Cypress.Commands.add('enableVerification', ({} = {}) => { +Cypress.Commands.add("enableVerification", ({} = {}) => { updateConfigFile((config) => { config.selfservice.flows.verification.enabled = true return config }) }) -Cypress.Commands.add('enableRecovery', ({} = {}) => { +Cypress.Commands.add("enableRecovery", ({} = {}) => { updateConfigFile((config) => { config.selfservice.flows.recovery.enabled = true return config }) }) -Cypress.Commands.add('disableRecovery', ({} = {}) => { +Cypress.Commands.add("disableRecovery", ({} = {}) => { updateConfigFile((config) => { config.selfservice.flows.recovery.enabled = false return config }) }) -Cypress.Commands.add('disableRegistration', ({} = {}) => { +Cypress.Commands.add("disableRegistration", ({} = {}) => { updateConfigFile((config) => { config.selfservice.flows.registration.enabled = false return config }) }) -Cypress.Commands.add('enableRegistration', ({} = {}) => { +Cypress.Commands.add("enableRegistration", ({} = {}) => { updateConfigFile((config) => { config.selfservice.flows.registration.enabled = true return config }) }) -Cypress.Commands.add('useLaxAal', ({} = {}) => { +Cypress.Commands.add("useLaxAal", ({} = {}) => { updateConfigFile((config) => { - config.selfservice.flows.settings.required_aal = 'aal1' - config.session.whoami.required_aal = 'aal1' + config.selfservice.flows.settings.required_aal = "aal1" + config.session.whoami.required_aal = "aal1" return config }) }) -Cypress.Commands.add('updateConfigFile', (cb: (arg: any) => any) => { +Cypress.Commands.add("updateConfigFile", (cb: (arg: any) => any) => { updateConfigFile(cb) }) Cypress.Commands.add( - 'register', + "register", ({ email = gen.email(), password = gen.password(), query = {}, - fields = {} + fields = {}, } = {}) => { - console.log('Creating user account: ', { email, password }) + console.log("Creating user account: ", { email, password }) // see https://github.com/cypress-io/cypress/issues/408 cy.clearAllCookies() cy.request({ - url: APP_URL + '/self-service/registration/browser', + url: APP_URL + "/self-service/registration/browser", followRedirect: false, headers: { - Accept: 'application/json' + Accept: "application/json", }, - qs: query + qs: query, }) .then(({ body, status }) => { expect(status).to.eq(200) @@ -280,26 +280,26 @@ Cypress.Commands.add( method: form.method, body: mergeFields(form, { ...fields, - 'traits.email': email, + "traits.email": email, password, - method: 'password' + method: "password", }), url: form.action, - followRedirect: false + followRedirect: false, }) }) .then(({ body }) => { expect(body.identity.traits.email).to.contain(email) }) - } + }, ) Cypress.Commands.add( - 'registerApi', + "registerApi", ({ email = gen.email(), password = gen.password(), fields = {} } = {}) => cy .request({ - url: APP_URL + '/self-service/registration/api' + url: APP_URL + "/self-service/registration/api", }) .then(({ body }) => { const form = body.ui @@ -307,42 +307,42 @@ Cypress.Commands.add( method: form.method, body: mergeFields(form, { ...fields, - 'traits.email': email, + "traits.email": email, password, - method: 'password' + method: "password", }), - url: form.action + url: form.action, }) }) .then(({ body }) => { expect(body.identity.traits.email).to.contain(email) - }) + }), ) -Cypress.Commands.add('settingsApi', ({ fields = {} } = {}) => +Cypress.Commands.add("settingsApi", ({ fields = {} } = {}) => cy .request({ - url: APP_URL + '/self-service/settings/api' + url: APP_URL + "/self-service/settings/api", }) .then(({ body }) => { const form = body.ui return cy.request({ method: form.method, body: mergeFields(form, { - ...fields + ...fields, }), - url: form.action + url: form.action, }) }) .then(({ body }) => { expect(body.statusCode).to.eq(200) - }) + }), ) -Cypress.Commands.add('loginApi', ({ email, password } = {}) => +Cypress.Commands.add("loginApi", ({ email, password } = {}) => cy .request({ - url: APP_URL + '/self-service/login/api' + url: APP_URL + "/self-service/login/api", }) .then(({ body }) => { const form = body.ui @@ -351,36 +351,36 @@ Cypress.Commands.add('loginApi', ({ email, password } = {}) => body: mergeFields(form, { identifier: email, password, - method: 'password' + method: "password", }), - url: form.action + url: form.action, }) }) .then(({ body }) => { expect(body.session.identity.traits.email).to.contain(email) - }) + }), ) -Cypress.Commands.add('loginApiWithoutCookies', ({ email, password } = {}) => { - cy.task('httpRequest', { - url: APP_URL + '/self-service/login/api', +Cypress.Commands.add("loginApiWithoutCookies", ({ email, password } = {}) => { + cy.task("httpRequest", { + url: APP_URL + "/self-service/login/api", headers: { - Accept: 'application/json' + Accept: "application/json", }, - responseType: 'json' + responseType: "json", }).should((body: any) => { - cy.task('httpRequest', { + cy.task("httpRequest", { method: body.ui.method, json: mergeFields(body.ui, { identifier: email, password, - method: 'password' + method: "password", }), headers: { - Accept: 'application/json' + Accept: "application/json", }, - responseType: 'json', - url: body.ui.action + responseType: "json", + url: body.ui.action, }).should((body: any) => { expect(body.session.identity.traits.email).to.contain(email) return body @@ -388,10 +388,10 @@ Cypress.Commands.add('loginApiWithoutCookies', ({ email, password } = {}) => { }) }) -Cypress.Commands.add('recoverApi', ({ email, returnTo }) => { - let url = APP_URL + '/self-service/recovery/api' +Cypress.Commands.add("recoverApi", ({ email, returnTo }) => { + let url = APP_URL + "/self-service/recovery/api" if (returnTo) { - url += '?return_to=' + returnTo + url += "?return_to=" + returnTo } cy.request({ url }) .then(({ body }) => { @@ -399,23 +399,23 @@ Cypress.Commands.add('recoverApi', ({ email, returnTo }) => { // label should still exist after request, for more detail: #2591 expect(form.nodes[1].meta).to.not.be.null expect(form.nodes[1].meta.label).to.not.be.null - expect(form.nodes[1].meta.label.text).to.equal('Email') + expect(form.nodes[1].meta.label.text).to.equal("Email") return cy.request({ method: form.method, - body: mergeFields(form, { email, method: 'link' }), - url: form.action + body: mergeFields(form, { email, method: "link" }), + url: form.action, }) }) .then(({ body }) => { - expect(body.state).to.contain('sent_email') + expect(body.state).to.contain("sent_email") }) }) -Cypress.Commands.add('verificationApi', ({ email, returnTo }) => { - let url = APP_URL + '/self-service/verification/api' +Cypress.Commands.add("verificationApi", ({ email, returnTo }) => { + let url = APP_URL + "/self-service/verification/api" if (returnTo) { - url += '?return_to=' + returnTo + url += "?return_to=" + returnTo } cy.request({ url }) .then(({ body }) => { @@ -423,88 +423,88 @@ Cypress.Commands.add('verificationApi', ({ email, returnTo }) => { // label should still exist after request, for more detail: #2591 expect(form.nodes[1].meta).to.not.be.null expect(form.nodes[1].meta.label).to.not.be.null - expect(form.nodes[1].meta.label.text).to.equal('Email') + expect(form.nodes[1].meta.label.text).to.equal("Email") return cy.request({ method: form.method, - body: mergeFields(form, { email, method: 'link' }), - url: form.action + body: mergeFields(form, { email, method: "link" }), + url: form.action, }) }) .then(({ body }) => { - expect(body.state).to.contain('sent_email') + expect(body.state).to.contain("sent_email") }) }) -Cypress.Commands.add('verificationApiExpired', ({ email, returnTo }) => { +Cypress.Commands.add("verificationApiExpired", ({ email, returnTo }) => { cy.shortVerificationLifespan() - let url = APP_URL + '/self-service/verification/api' + let url = APP_URL + "/self-service/verification/api" if (returnTo) { - url += '?return_to=' + returnTo + url += "?return_to=" + returnTo } cy.request({ url }) .then(({ body }) => { const form = body.ui return cy.request({ method: form.method, - body: mergeFields(form, { email, method: 'link' }), + body: mergeFields(form, { email, method: "link" }), url: form.action, - failOnStatusCode: false + failOnStatusCode: false, }) }) .then((response) => { expect(response.status).to.eq(410) expect(response.body.error.reason).to.eq( - 'The verification flow has expired. Redirect the user to the verification flow init endpoint to initialize a new verification flow.' + "The verification flow has expired. Redirect the user to the verification flow init endpoint to initialize a new verification flow.", ) expect(response.body.error.details.redirect_to).to.eq( - 'http://localhost:4455/self-service/verification/browser' + "http://localhost:4455/self-service/verification/browser", ) }) }) -Cypress.Commands.add('verificationBrowser', ({ email, returnTo }) => { - let url = APP_URL + '/self-service/verification/browser' +Cypress.Commands.add("verificationBrowser", ({ email, returnTo }) => { + let url = APP_URL + "/self-service/verification/browser" if (returnTo) { - url += '?return_to=' + returnTo + url += "?return_to=" + returnTo } cy.request({ url }) .then(({ body }) => { const form = body.ui return cy.request({ method: form.method, - body: mergeFields(form, { email, method: 'link' }), - url: form.action + body: mergeFields(form, { email, method: "link" }), + url: form.action, }) }) .then(({ body }) => { - expect(body.state).to.contain('sent_email') + expect(body.state).to.contain("sent_email") }) }) -Cypress.Commands.add('addVirtualAuthenticator', () => +Cypress.Commands.add("addVirtualAuthenticator", () => cy - .task('sendCRI', { - query: 'WebAuthn.enable', - opts: {} + .task("sendCRI", { + query: "WebAuthn.enable", + opts: {}, }) .then(() => - cy.task('sendCRI', { - query: 'WebAuthn.addVirtualAuthenticator', + cy.task("sendCRI", { + query: "WebAuthn.addVirtualAuthenticator", opts: { options: { - protocol: 'ctap2', - transport: 'usb', + protocol: "ctap2", + transport: "usb", hasResidentKey: true, hasUserVerification: true, - isUserVerified: true - } - } - }) - ) + isUserVerified: true, + }, + }, + }), + ), ) Cypress.Commands.add( - 'registerOidc', + "registerOidc", ({ email, website, @@ -514,128 +514,128 @@ Cypress.Commands.add( acceptLogin = true, acceptConsent = true, expectSession = true, - route = APP_URL + '/registration' + route = APP_URL + "/registration", }) => { cy.visit(route) cy.triggerOidc() - cy.get('#username').type(email) + cy.get("#username").type(email) if (rememberLogin) { - cy.get('#remember').click() + cy.get("#remember").click() } if (acceptLogin) { - cy.get('#accept').click() + cy.get("#accept").click() } else { - cy.get('#reject').click() + cy.get("#reject").click() } if (scopes) { scopes.forEach((scope) => { - cy.get('#' + scope).click() + cy.get("#" + scope).click() }) } else { cy.get('input[name="scope"]').each(($el) => cy.wrap($el).click()) } if (website) { - cy.get('#website').clear().type(website) + cy.get("#website").clear().type(website) } if (rememberConsent) { - cy.get('#remember').click() + cy.get("#remember").click() } if (acceptConsent) { - cy.get('#accept').click() + cy.get("#accept").click() } else { - cy.get('#reject').click() + cy.get("#reject").click() } - cy.location('pathname').should('not.include', 'consent') + cy.location("pathname").should("not.include", "consent") if (expectSession) { cy.getSession() } else { cy.noSession() } - } + }, ) -Cypress.Commands.add('shortRegisterLifespan', ({} = {}) => { +Cypress.Commands.add("shortRegisterLifespan", ({} = {}) => { updateConfigFile((config) => { - config.selfservice.flows.registration.lifespan = '100ms' + config.selfservice.flows.registration.lifespan = "100ms" return config }) }) -Cypress.Commands.add('longRegisterLifespan', ({} = {}) => { +Cypress.Commands.add("longRegisterLifespan", ({} = {}) => { updateConfigFile((config) => { - config.selfservice.flows.registration.lifespan = '1h' + config.selfservice.flows.registration.lifespan = "1h" return config }) }) -Cypress.Commands.add('browserReturnUrlOry', ({} = {}) => { +Cypress.Commands.add("browserReturnUrlOry", ({} = {}) => { updateConfigFile((config) => { config.selfservice.allowed_return_urls = [ - 'https://www.ory.sh/', - 'https://www.example.org/' + "https://www.ory.sh/", + "https://www.example.org/", ] return config }) }) -Cypress.Commands.add('remoteCourierRecoveryTemplates', ({} = {}) => { +Cypress.Commands.add("remoteCourierRecoveryTemplates", ({} = {}) => { updateConfigFile((config) => { config.courier.templates = { recovery: { invalid: { email: { body: { - html: 'base64://SGksCgp0aGlzIGlzIGEgcmVtb3RlIGludmFsaWQgcmVjb3ZlcnkgdGVtcGxhdGU=', + html: "base64://SGksCgp0aGlzIGlzIGEgcmVtb3RlIGludmFsaWQgcmVjb3ZlcnkgdGVtcGxhdGU=", plaintext: - 'base64://SGksCgp0aGlzIGlzIGEgcmVtb3RlIGludmFsaWQgcmVjb3ZlcnkgdGVtcGxhdGU=' + "base64://SGksCgp0aGlzIGlzIGEgcmVtb3RlIGludmFsaWQgcmVjb3ZlcnkgdGVtcGxhdGU=", }, - subject: 'base64://QWNjb3VudCBBY2Nlc3MgQXR0ZW1wdGVk' - } + subject: "base64://QWNjb3VudCBBY2Nlc3MgQXR0ZW1wdGVk", + }, }, valid: { email: { body: { - html: 'base64://SGksCgp0aGlzIGlzIGEgcmVtb3RlIHRlbXBsYXRlCnBsZWFzZSByZWNvdmVyIGFjY2VzcyB0byB5b3VyIGFjY291bnQgYnkgY2xpY2tpbmcgdGhlIGZvbGxvd2luZyBsaW5rOgo8YSBocmVmPSJ7eyAuUmVjb3ZlcnlVUkwgfX0iPnt7IC5SZWNvdmVyeVVSTCB9fTwvYT4=', + html: "base64://SGksCgp0aGlzIGlzIGEgcmVtb3RlIHRlbXBsYXRlCnBsZWFzZSByZWNvdmVyIGFjY2VzcyB0byB5b3VyIGFjY291bnQgYnkgY2xpY2tpbmcgdGhlIGZvbGxvd2luZyBsaW5rOgo8YSBocmVmPSJ7eyAuUmVjb3ZlcnlVUkwgfX0iPnt7IC5SZWNvdmVyeVVSTCB9fTwvYT4=", plaintext: - 'base64://SGksCgp0aGlzIGlzIGEgcmVtb3RlIHRlbXBsYXRlCnBsZWFzZSByZWNvdmVyIGFjY2VzcyB0byB5b3VyIGFjY291bnQgYnkgY2xpY2tpbmcgdGhlIGZvbGxvd2luZyBsaW5rOgp7eyAuUmVjb3ZlcnlVUkwgfX0=' + "base64://SGksCgp0aGlzIGlzIGEgcmVtb3RlIHRlbXBsYXRlCnBsZWFzZSByZWNvdmVyIGFjY2VzcyB0byB5b3VyIGFjY291bnQgYnkgY2xpY2tpbmcgdGhlIGZvbGxvd2luZyBsaW5rOgp7eyAuUmVjb3ZlcnlVUkwgfX0=", }, - subject: 'base64://UmVjb3ZlciBhY2Nlc3MgdG8geW91ciBhY2NvdW50' - } - } - } + subject: "base64://UmVjb3ZlciBhY2Nlc3MgdG8geW91ciBhY2NvdW50", + }, + }, + }, } return config }) }) Cypress.Commands.add( - 'loginOidc', - ({ expectSession = true, url = APP_URL + '/login' }) => { + "loginOidc", + ({ expectSession = true, url = APP_URL + "/login" }) => { cy.visit(url) - cy.triggerOidc('hydra') - cy.location('href').should('not.eq', '/consent') + cy.triggerOidc("hydra") + cy.location("href").should("not.eq", "/consent") if (expectSession) { cy.getSession() } else { cy.noSession() } - } + }, ) Cypress.Commands.add( - 'login', + "login", ({ email, password, expectSession = true, cookieUrl = APP_URL }) => { if (expectSession) { - console.log('Singing in user: ', { email, password }) + console.log("Singing in user: ", { email, password }) } else { - console.log('Attempting user sign in: ', { email, password }) + console.log("Attempting user sign in: ", { email, password }) } // see https://github.com/cypress-io/cypress/issues/408 @@ -644,12 +644,12 @@ Cypress.Commands.add( cy.longPrivilegedSessionTime() cy.request({ - url: APP_URL + '/self-service/login/browser', + url: APP_URL + "/self-service/login/browser", followRedirect: false, failOnStatusCode: false, headers: { - Accept: 'application/json' - } + Accept: "application/json", + }, }) .then(({ body, status }) => { expect(status).to.eq(200) @@ -659,21 +659,21 @@ Cypress.Commands.add( body: mergeFields(form, { identifier: email, password, - method: 'password' + method: "password", }), headers: { - Accept: 'application/json' + Accept: "application/json", }, url: form.action, followRedirect: false, - failOnStatusCode: false + failOnStatusCode: false, }) }) .then(({ status }) => { - console.log('Login sequence completed: ', { + console.log("Login sequence completed: ", { email, password, - expectSession + expectSession, }) if (expectSession) { expect(status).to.eq(200) @@ -683,20 +683,20 @@ Cypress.Commands.add( return cy.noSession() } }) - } + }, ) -Cypress.Commands.add('loginMobile', ({ email, password }) => { - cy.visit(MOBILE_URL + '/Login') +Cypress.Commands.add("loginMobile", ({ email, password }) => { + cy.visit(MOBILE_URL + "/Login") cy.get('input[data-testid="identifier"]').type(email) cy.get('input[data-testid="password"]').type(password) cy.get('div[data-testid="submit-form"]').click() }) -Cypress.Commands.add('logout', () => { +Cypress.Commands.add("logout", () => { cy.getCookies().should((cookies) => { const c = cookies.find( - ({ name }) => name.indexOf('ory_kratos_session') > -1 + ({ name }) => name.indexOf("ory_kratos_session") > -1, ) expect(c).to.not.be.undefined cy.clearCookie(c.name) @@ -705,27 +705,27 @@ Cypress.Commands.add('logout', () => { }) Cypress.Commands.add( - 'reauthWithOtherAccount', + "reauthWithOtherAccount", ({ previousUrl, expect: { email, success = true }, type: { email: temail, password: tpassword } = { email: undefined, - password: undefined - } + password: undefined, + }, }) => { - cy.location('pathname').should('contain', '/login') + cy.location("pathname").should("contain", "/login") cy.location().then((loc) => { const uri = new URLSearchParams(loc.search) - const flow = uri.get('flow') + const flow = uri.get("flow") expect(flow).to.not.be.empty cy.request({ url: APP_URL + `/self-service/login/flows?id=${flow}`, followRedirect: false, failOnStatusCode: false, headers: { - Accept: 'application/json' - } + Accept: "application/json", + }, }).then(({ body, status }) => { expect(status).to.eq(200) const form = body.ui @@ -736,15 +736,15 @@ Cypress.Commands.add( body: mergeFields(form, { identifier: temail || email, password: tpassword, - method: 'password' + method: "password", }), headers: { - Accept: 'application/json', - ContentType: 'application/json' + Accept: "application/json", + ContentType: "application/json", }, url: form.action, followRedirect: false, - failOnStatusCode: false + failOnStatusCode: false, }) .then((res) => { expect(res.status).to.eq(200) @@ -752,21 +752,21 @@ Cypress.Commands.add( }) }) }) - } + }, ) Cypress.Commands.add( - 'reauth', + "reauth", ({ expect: { email, success = true }, type: { email: temail, password: tpassword } = { email: undefined, - password: undefined - } + password: undefined, + }, }) => { - cy.location('pathname').should('contain', '/login') - cy.get('input[name="identifier"]').should('have.value', email) + cy.location("pathname").should("contain", "/login") + cy.get('input[name="identifier"]').should("have.value", email) if (temail) { - cy.get('input[name="identifier"]').invoke('attr', 'value', temail) + cy.get('input[name="identifier"]').invoke("attr", "value", temail) } if (tpassword) { cy.get('input[name="password"]').clear().type(tpassword) @@ -774,22 +774,22 @@ Cypress.Commands.add( cy.longPrivilegedSessionTime() cy.get('button[value="password"]').click() if (success) { - cy.location('pathname').should('not.contain', '/login') + cy.location("pathname").should("not.contain", "/login") } - } + }, ) -Cypress.Commands.add('deleteMail', ({ atLeast = 0 } = {}) => { +Cypress.Commands.add("deleteMail", ({ atLeast = 0 } = {}) => { let tries = 0 let count = 0 const req = () => cy - .request('DELETE', `${MAIL_API}/mail`, { pruneCode: 'all' }) + .request("DELETE", `${MAIL_API}/mail`, { pruneCode: "all" }) .then(({ body }) => { count += parseInt(body) if (count < atLeast && tries < 100) { cy.log( - `Expected at least ${atLeast} messages but deleteted only ${count} so far (body: ${body})` + `Expected at least ${atLeast} messages but deleteted only ${count} so far (body: ${body})`, ) tries++ cy.wait(pollInterval) @@ -803,27 +803,27 @@ Cypress.Commands.add('deleteMail', ({ atLeast = 0 } = {}) => { }) Cypress.Commands.add( - 'getSession', - ({ expectAal = 'aal1', expectMethods = [] } = {}) => { + "getSession", + ({ expectAal = "aal1", expectMethods = [] } = {}) => { // Do the request once to ensure we have a session (with retry) - cy.request('GET', `${KRATOS_PUBLIC}/sessions/whoami`) - .its('status') - .should('eq', 200) + cy.request("GET", `${KRATOS_PUBLIC}/sessions/whoami`) + .its("status") + .should("eq", 200) // Return the session for further propagation return cy - .request('GET', `${KRATOS_PUBLIC}/sessions/whoami`) + .request("GET", `${KRATOS_PUBLIC}/sessions/whoami`) .then((response) => { expect(response.body.id).to.not.be.empty expect(dayjs().isBefore(dayjs(response.body.expires_at))).to.be.true // Add a grace second for MySQL which does not support millisecs. - expect(dayjs().isAfter(dayjs(response.body.issued_at).subtract(1, 's'))) + expect(dayjs().isAfter(dayjs(response.body.issued_at).subtract(1, "s"))) .to.be.true expect( dayjs().isAfter( - dayjs(response.body.authenticated_at).subtract(1, 's') - ) + dayjs(response.body.authenticated_at).subtract(1, "s"), + ), ).to.be.true expect(response.body.identity).to.exist @@ -831,60 +831,60 @@ Cypress.Commands.add( expect(response.body.authenticator_assurance_level).to.equal(expectAal) if (expectMethods.length > 0) { expect(response.body.authentication_methods).to.have.lengthOf( - expectMethods.length + expectMethods.length, ) expectMethods.forEach((value) => { expect( response.body.authentication_methods.find( - ({ method }) => method === value - ) + ({ method }) => method === value, + ), ).to.exist }) } return response.body }) - } + }, ) -Cypress.Commands.add('noSession', () => +Cypress.Commands.add("noSession", () => cy .request({ - method: 'GET', + method: "GET", url: `${KRATOS_PUBLIC}/sessions/whoami`, - failOnStatusCode: false + failOnStatusCode: false, }) .then((request) => { expect(request.status).to.eq(401) return request - }) + }), ) -Cypress.Commands.add('getIdentityByEmail', ({ email }) => +Cypress.Commands.add("getIdentityByEmail", ({ email }) => cy .request({ - method: 'GET', + method: "GET", url: `${KRATOS_ADMIN}/identities`, - failOnStatusCode: false + failOnStatusCode: false, }) .then((response) => { expect(response.status).to.eq(200) return response.body.find((identity) => identity.traits.email === email) - }) + }), ) Cypress.Commands.add( - 'performEmailVerification', + "performEmailVerification", ({ - expect: { email, redirectTo } = { email: undefined, redirectTo: undefined } + expect: { email, redirectTo } = { email: undefined, redirectTo: undefined }, } = {}) => cy.getMail().then((message) => { - expect(message.subject).to.equal('Please verify your email address') - expect(message.fromAddress.trim()).to.equal('no-reply@ory.kratos.sh') + expect(message.subject).to.equal("Please verify your email address") + expect(message.fromAddress.trim()).to.equal("no-reply@ory.kratos.sh") expect(message.toAddresses).to.have.length(1) expect(message.toAddresses[0].trim()).to.equal(email) - const link = parseHtml(message.body).querySelector('a') - const flow = new URL(link.href).searchParams.get('flow') + const link = parseHtml(message.body).querySelector("a") + const flow = new URL(link.href).searchParams.get("flow") expect(link).to.not.be.null expect(link.href).to.contain(APP_URL) @@ -895,30 +895,30 @@ Cypress.Commands.add( if (redirectTo) { expect(response.redirectedToUrl).to.eq(`${redirectTo}?flow=${flow}`) } else { - expect(response.redirectedToUrl).to.not.contain('verification') + expect(response.redirectedToUrl).to.not.contain("verification") } - } + }, ) - }) + }), ) Cypress.Commands.add( - 'verifyEmail', + "verifyEmail", ({ expect: { email, password, redirectTo } }) => cy.performEmailVerification({ expect: { email, redirectTo } }).then(() => { cy.getSession().should((session) => - assertVerifiableAddress({ email, isVerified: true })(session) + assertVerifiableAddress({ email, isVerified: true })(session), ) - }) + }), ) // Uses the verification email but waits so that it expires -Cypress.Commands.add('recoverEmailButExpired', ({ expect: { email } }) => { +Cypress.Commands.add("recoverEmailButExpired", ({ expect: { email } }) => { cy.getMail().should((message) => { - expect(message.subject).to.equal('Recover access to your account') + expect(message.subject).to.equal("Recover access to your account") expect(message.toAddresses[0].trim()).to.equal(email) - const link = parseHtml(message.body).querySelector('a') + const link = parseHtml(message.body).querySelector("a") expect(link).to.not.be.null expect(link.href).to.contain(APP_URL) @@ -927,15 +927,15 @@ Cypress.Commands.add('recoverEmailButExpired', ({ expect: { email } }) => { }) Cypress.Commands.add( - 'recoverEmail', + "recoverEmail", ({ expect: { email }, shouldVisit = true }) => cy.getMail().should((message) => { - expect(message.subject).to.equal('Recover access to your account') - expect(message.fromAddress.trim()).to.equal('no-reply@ory.kratos.sh') + expect(message.subject).to.equal("Recover access to your account") + expect(message.fromAddress.trim()).to.equal("no-reply@ory.kratos.sh") expect(message.toAddresses).to.have.length(1) expect(message.toAddresses[0].trim()).to.equal(email) - const link = parseHtml(message.body).querySelector('a') + const link = parseHtml(message.body).querySelector("a") expect(link).to.not.be.null expect(link.href).to.contain(APP_URL) @@ -943,71 +943,71 @@ Cypress.Commands.add( cy.visit(link.href) } return link.href - }) + }), ) // Uses the verification email but waits so that it expires Cypress.Commands.add( - 'verifyEmailButExpired', + "verifyEmailButExpired", ({ expect: { email, password } }) => cy.getMail().then((message) => { - expect(message.subject).to.equal('Please verify your email address') + expect(message.subject).to.equal("Please verify your email address") - expect(message.fromAddress.trim()).to.equal('no-reply@ory.kratos.sh') + expect(message.fromAddress.trim()).to.equal("no-reply@ory.kratos.sh") expect(message.toAddresses).to.have.length(1) expect(message.toAddresses[0].trim()).to.equal(email) - const link = parseHtml(message.body).querySelector('a') + const link = parseHtml(message.body).querySelector("a") cy.getSession().should((session) => { assertVerifiableAddress({ isVerified: false, - email: email + email: email, })(session) }) cy.visit(link.href) - cy.location('pathname').should('include', 'verification') + cy.location("pathname").should("include", "verification") cy.get('[data-testid="ui/message/4070005"]').should( - 'contain.text', - 'verification flow expired' + "contain.text", + "verification flow expired", ) cy.getSession().should((session) => { assertVerifiableAddress({ isVerified: false, - email: email + email: email, })(session) }) - }) + }), ) // Uses the verification email but waits so that it expires -Cypress.Commands.add('waitForPrivilegedSessionToExpire', () => { +Cypress.Commands.add("waitForPrivilegedSessionToExpire", () => { cy.getSession().should((session: Session) => { expect(session.authenticated_at).to.not.be.empty cy.wait( dayjs(session.authenticated_at).add(privilegedLifespan).diff(dayjs()) + - 100 + 100, ) }) }) -Cypress.Commands.add('getLookupSecrets', () => +Cypress.Commands.add("getLookupSecrets", () => cy .get('[data-testid="node/text/lookup_secret_codes/text"] code') - .then(($e) => $e.map((_, e) => e.innerText.trim()).toArray()) + .then(($e) => $e.map((_, e) => e.innerText.trim()).toArray()), ) -Cypress.Commands.add('expectSettingsSaved', () => +Cypress.Commands.add("expectSettingsSaved", () => cy .get('[data-testid="ui/message/1050001"]') - .should('contain.text', 'Your changes have been saved') + .should("contain.text", "Your changes have been saved"), ) -Cypress.Commands.add('getMail', ({ removeMail = true } = {}) => { +Cypress.Commands.add("getMail", ({ removeMail = true } = {}) => { let tries = 0 const req = () => cy.request(`${MAIL_API}/mail`).then((response) => { - expect(response.body).to.have.property('mailItems') + expect(response.body).to.have.property("mailItems") const count = response.body.mailItems.length if (count === 0 && tries < 100) { tries++ @@ -1028,61 +1028,61 @@ Cypress.Commands.add('getMail', ({ removeMail = true } = {}) => { return req() }) -Cypress.Commands.add('clearAllCookies', () => { +Cypress.Commands.add("clearAllCookies", () => { cy.clearCookies({ domain: null }) }) -Cypress.Commands.add('submitPasswordForm', () => { +Cypress.Commands.add("submitPasswordForm", () => { cy.get('[name="method"][value="password"]').click() - cy.get('[name="method"][value="password"]:disabled').should('not.exist') + cy.get('[name="method"][value="password"]:disabled').should("not.exist") }) -Cypress.Commands.add('submitProfileForm', () => { +Cypress.Commands.add("submitProfileForm", () => { cy.get('[name="method"][value="profile"]').click() - cy.get('[name="method"][value="profile"]:disabled').should('not.exist') + cy.get('[name="method"][value="profile"]:disabled').should("not.exist") }) -Cypress.Commands.add('clickWebAuthButton', (type: string) => { - cy.get('*[data-testid="node/script/webauthn_script"]').should('exist') +Cypress.Commands.add("clickWebAuthButton", (type: string) => { + cy.get('*[data-testid="node/script/webauthn_script"]').should("exist") cy.wait(500) // Wait for script to load cy.get('*[name="webauthn_' + type + '_trigger"]').click() cy.wait(500) // Wait webauth to pass }) -Cypress.Commands.add('shouldShow2FAScreen', () => { +Cypress.Commands.add("shouldShow2FAScreen", () => { cy.location().should((loc) => { - expect(loc.pathname).to.include('/login') + expect(loc.pathname).to.include("/login") }) - cy.get('h2').should('contain.text', 'Two-Factor Authentication') + cy.get("h2").should("contain.text", "Two-Factor Authentication") cy.get('[data-testid="ui/message/1010004"]').should( - 'contain.text', - 'Please complete the second authentication challenge.' + "contain.text", + "Please complete the second authentication challenge.", ) }) Cypress.Commands.add( - 'shouldErrorOnDisallowedReturnTo', - (init: string, { app }: { app: 'express' | 'react' }) => { + "shouldErrorOnDisallowedReturnTo", + (init: string, { app }: { app: "express" | "react" }) => { cy.visit(init, { failOnStatusCode: false }) - if (app === 'react') { - cy.location('href').should('include', init.split('?')[0]) - cy.get('.Toastify').should( - 'contain.text', - 'The return_to address is not allowed.' + if (app === "react") { + cy.location("href").should("include", init.split("?")[0]) + cy.get(".Toastify").should( + "contain.text", + "The return_to address is not allowed.", ) } else { - cy.location('pathname').should('contain', 'error') - cy.get('code').should( - 'contain.text', - 'Requested return_to URL \\"https://not-allowed\\" is not allowed.' + cy.location("pathname").should("contain", "error") + cy.get("code").should( + "contain.text", + 'Requested return_to URL \\"https://not-allowed\\" is not allowed.', ) } - } + }, ) Cypress.Commands.add( - 'shouldHaveCsrfError', - ({ app }: { app: 'express' | 'react' }) => { + "shouldHaveCsrfError", + ({ app }: { app: "express" | "react" }) => { let initial let pathname cy.location().should((location) => { @@ -1091,36 +1091,36 @@ Cypress.Commands.add( }) cy.getCookies().should((cookies) => { - const csrf = cookies.find(({ name }) => name.indexOf('csrf') > -1) + const csrf = cookies.find(({ name }) => name.indexOf("csrf") > -1) expect(csrf).to.not.be.undefined cy.clearCookie(csrf.name) }) cy.submitPasswordForm() // We end up at a new flow - if (app === 'express') { + if (app === "express") { cy.location().should((location) => { expect(initial).to.not.be.empty expect(location.search).to.not.eq(initial) }) - cy.location('pathname').should('include', '/error') - cy.get('code').should('contain.text', 'csrf_token') + cy.location("pathname").should("include", "/error") + cy.get("code").should("contain.text", "csrf_token") } else { - cy.location('pathname').should((got) => { + cy.location("pathname").should((got) => { expect(got).to.eql(pathname) }) - cy.get('.Toastify').should( - 'contain.text', - 'A security violation was detected, please fill out the form again.' + cy.get(".Toastify").should( + "contain.text", + "A security violation was detected, please fill out the form again.", ) } - } + }, ) Cypress.Commands.add( - 'triggerOidc', - (app: 'react' | 'express', provider: string = 'hydra') => { + "triggerOidc", + (app: "react" | "express", provider: string = "hydra") => { let initial, didHaveSearch cy.location().then((loc) => { didHaveSearch = loc.search.length > 0 @@ -1128,10 +1128,10 @@ Cypress.Commands.add( }) cy.get('[name="provider"][value="' + provider + '"]').click() cy.location().should((loc) => { - if (app === 'express' || didHaveSearch) { + if (app === "express" || didHaveSearch) { return } expect(loc.pathname + loc.search).not.to.eql(initial) }) - } + }, ) diff --git a/test/e2e/cypress/support/index.d.ts b/test/e2e/cypress/support/index.d.ts index 98a3cc0a4168..4fe1fea58b29 100644 --- a/test/e2e/cypress/support/index.d.ts +++ b/test/e2e/cypress/support/index.d.ts @@ -1,4 +1,4 @@ -import { Session } from '@ory/kratos-client' +import { Session } from "@ory/kratos-client" export interface MailMessage { fromAddress: string @@ -28,9 +28,9 @@ declare global { * @param opts */ getSession(opts?: { - expectAal?: 'aal2' | 'aal1' + expectAal?: "aal2" | "aal1" expectMethods?: Array< - 'password' | 'webauthn' | 'lookup_secret' | 'totp' + "password" | "webauthn" | "lookup_secret" | "totp" > }): Chainable @@ -256,7 +256,7 @@ declare global { expectSettingsSaved(): Chainable clearCookies( - options?: Partial + options?: Partial, ): Chainable /** @@ -289,7 +289,7 @@ declare global { */ shouldErrorOnDisallowedReturnTo( init: string, - opts: { app: string } + opts: { app: string }, ): Chainable /** @@ -301,7 +301,7 @@ declare global { * * @param type */ - clickWebAuthButton(type: 'login' | 'register'): Chainable + clickWebAuthButton(type: "login" | "register"): Chainable /** * Sign up a user using Social Sign In @@ -336,7 +336,7 @@ declare global { * @param app * @param provider */ - triggerOidc(app: 'react' | 'express', provider?: string): Chainable + triggerOidc(app: "react" | "express", provider?: string): Chainable /** * Changes the config so that the recovery privileged lifespan is very long. @@ -500,7 +500,7 @@ declare global { /** * Which app to proxy */ - proxy(app: 'react' | 'express'): Chainable + proxy(app: "react" | "express"): Chainable /** * Log a user in on mobile diff --git a/test/e2e/cypress/support/index.js b/test/e2e/cypress/support/index.js index 9d39bfd290ea..a010c9a5b2ed 100644 --- a/test/e2e/cypress/support/index.js +++ b/test/e2e/cypress/support/index.js @@ -1,3 +1,3 @@ -import './commands' +import "./commands" Cypress.Cookies.debug(true) diff --git a/test/e2e/proxy/proxy.js b/test/e2e/proxy/proxy.js index e7cab7ef7345..31150db4b332 100644 --- a/test/e2e/proxy/proxy.js +++ b/test/e2e/proxy/proxy.js @@ -1,7 +1,7 @@ -const request = require('request') -const urljoin = require('url-join') -const express = require('express') -const fs = require('fs') +const request = require("request") +const urljoin = require("url-join") +const express = require("express") +const fs = require("fs") const app = express() @@ -13,26 +13,26 @@ const proxy = url = urljoin(base, prefix, req.url) } req - .pipe(request(url, { followRedirect: false }).on('error', next)) + .pipe(request(url, { followRedirect: false }).on("error", next)) .pipe(res) } app.use( - '/self-service/', - proxy(process.env.KRATOS_PUBLIC_URL, '/self-service/') + "/self-service/", + proxy(process.env.KRATOS_PUBLIC_URL, "/self-service/"), ) -app.use('/schemas/', proxy(process.env.KRATOS_PUBLIC_URL, '/schemas/')) -app.use('/.well-known/', proxy(process.env.KRATOS_PUBLIC_URL, '/.well-known/')) +app.use("/schemas/", proxy(process.env.KRATOS_PUBLIC_URL, "/schemas/")) +app.use("/.well-known/", proxy(process.env.KRATOS_PUBLIC_URL, "/.well-known/")) -app.use('/', (req, res, next) => { +app.use("/", (req, res, next) => { const pc = JSON.parse( - fs.readFileSync(require.resolve('../proxy.json')).toString() + fs.readFileSync(require.resolve("../proxy.json")).toString(), ) switch (pc) { - case 'react': + case "react": proxy(process.env.KRATOS_UI_REACT_URL)(req, res, next) return - case 'react-native': + case "react-native": proxy(process.env.KRATOS_UI_REACT_NATIVE_URL)(req, res, next) return } @@ -45,4 +45,4 @@ let listener = () => { console.log(`Listening on http://0.0.0.0:${port}`) } -app.listen(port, '0.0.0.0', listener) +app.listen(port, "0.0.0.0", listener)