snapshot of https://github.com/ory/kratos.git (master, 2026-09-15; blobs > 131072B omitted)
Some checks failed
CI / Run tests and lints (push) Failing after 29s
CI / Build CLI docs (push) Has been skipped
CI / Run Playwright end-to-end tests (mysql) (push) Failing after 3s
CI / Run Playwright end-to-end tests (postgres) (push) Failing after 2s
CI / Run Playwright end-to-end tests (sqlite) (push) Failing after 3s
CodeQL / Analyze (go) (push) Failing after 4s
CodeQL / Analyze (javascript) (push) Failing after 3s
Docker Image Scanners / scanners (push) Failing after 4s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Run end-to-end tests (postgres) (push) Failing after 19s
CI / Run end-to-end tests (sqlite) (push) Failing after 2s
CI / Run Playwright end-to-end tests (cockroach) (push) Failing after 2s
CI / Draft newsletter (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
Some checks failed
CI / Run tests and lints (push) Failing after 29s
CI / Build CLI docs (push) Has been skipped
CI / Run Playwright end-to-end tests (mysql) (push) Failing after 3s
CI / Run Playwright end-to-end tests (postgres) (push) Failing after 2s
CI / Run Playwright end-to-end tests (sqlite) (push) Failing after 3s
CodeQL / Analyze (go) (push) Failing after 4s
CodeQL / Analyze (javascript) (push) Failing after 3s
Docker Image Scanners / scanners (push) Failing after 4s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Run end-to-end tests (postgres) (push) Failing after 19s
CI / Run end-to-end tests (sqlite) (push) Failing after 2s
CI / Run Playwright end-to-end tests (cockroach) (push) Failing after 2s
CI / Draft newsletter (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
This commit is contained in:
14
test/e2e/cypress/helpers/express.ts
Normal file
14
test/e2e/cypress/helpers/express.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { APP_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",
|
||||
welcome: APP_URL + "/welcome",
|
||||
}
|
||||
45
test/e2e/cypress/helpers/httpbin.ts
Normal file
45
test/e2e/cypress/helpers/httpbin.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import * as oauth2 from "./oauth2"
|
||||
|
||||
export function checkToken(
|
||||
client: oauth2.oAuth2Client,
|
||||
scope: string[],
|
||||
check: (token: any) => void,
|
||||
) {
|
||||
cy.location("href")
|
||||
.should(
|
||||
"match",
|
||||
new RegExp(
|
||||
"https://ory-network-httpbin-ijakee5waq-ez.a.run.app/anything[?]code=.*",
|
||||
),
|
||||
)
|
||||
.then(() => {
|
||||
cy.get("body")
|
||||
.invoke("text")
|
||||
.then((text) => {
|
||||
const result = JSON.parse(text)
|
||||
const tokenParams = {
|
||||
code: result.args.code,
|
||||
redirect_uri:
|
||||
"https://ory-network-httpbin-ijakee5waq-ez.a.run.app/anything",
|
||||
scope: scope.join(" "),
|
||||
}
|
||||
oauth2
|
||||
.getToken(
|
||||
client.token_endpoint,
|
||||
client.id,
|
||||
client.secret,
|
||||
"authorization_code",
|
||||
tokenParams.code,
|
||||
tokenParams.redirect_uri,
|
||||
tokenParams.scope,
|
||||
)
|
||||
.then((res) => {
|
||||
const token = res.body
|
||||
check(token)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
104
test/e2e/cypress/helpers/index.ts
Normal file
104
test/e2e/cypress/helpers/index.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
export const email = () => Math.random().toString(36) + "@ory.sh"
|
||||
export const blockedEmail = () =>
|
||||
Math.random().toString(36) + "_blocked" + "@ory.sh"
|
||||
|
||||
export const password = () => Math.random().toString(36)
|
||||
|
||||
export const assertVerifiableAddress =
|
||||
({ isVerified, email }) =>
|
||||
(session) => {
|
||||
const { identity } = session
|
||||
expect(identity).to.have.property("verifiable_addresses")
|
||||
expect(identity.verifiable_addresses).to.have.length(1)
|
||||
|
||||
const address = identity.verifiable_addresses[0]
|
||||
expect(address.id).to.not.be.empty
|
||||
expect(address.verified).to.equal(isVerified)
|
||||
expect(address.value).to.equal(email)
|
||||
|
||||
if (isVerified) {
|
||||
expect(address.verified_at).to.not.be.null
|
||||
} else {
|
||||
expect(address).to.not.have.property("verified_at")
|
||||
}
|
||||
}
|
||||
|
||||
export const assertRecoveryAddress =
|
||||
({ email }) =>
|
||||
({ identity }) => {
|
||||
expect(identity).to.have.property("recovery_addresses")
|
||||
expect(identity.recovery_addresses).to.have.length(1)
|
||||
|
||||
const address = identity.recovery_addresses[0]
|
||||
expect(address.id).to.not.be.empty
|
||||
expect(address.value).to.equal(email)
|
||||
}
|
||||
|
||||
export const parseHtml = (html: string) =>
|
||||
new DOMParser().parseFromString(html, "text/html")
|
||||
|
||||
export const APP_URL = (
|
||||
Cypress.env("app_url") || "http://localhost:4455"
|
||||
).replace(/\/$/, "")
|
||||
|
||||
export const MOBILE_URL = (
|
||||
Cypress.env("mobile_url") || "http://localhost:19006"
|
||||
).replace(/\/$/, "")
|
||||
export const SPA_URL = (
|
||||
Cypress.env("react_url") || "http://localhost:4455"
|
||||
).replace(/\/$/, "")
|
||||
export const KRATOS_ADMIN = (
|
||||
Cypress.env("kratos_admin") || "http://localhost:4434"
|
||||
)
|
||||
.replace()
|
||||
.replace(/\/$/, "")
|
||||
|
||||
export const KRATOS_PUBLIC = (
|
||||
Cypress.env("kratos_public") || "http://localhost:4433"
|
||||
)
|
||||
.replace()
|
||||
.replace(/\/$/, "")
|
||||
|
||||
export const MAIL_API = (
|
||||
Cypress.env("mail_url") || "http://localhost:4437"
|
||||
).replace(/\/$/, "")
|
||||
|
||||
export const website = "https://www.ory.sh/"
|
||||
|
||||
export const gen = {
|
||||
email,
|
||||
blockedEmail,
|
||||
password,
|
||||
identity: () => ({ email: email(), password: password() }),
|
||||
identityWithWebsite: () => ({
|
||||
email: email(),
|
||||
password: password(),
|
||||
fields: { "traits.website": "https://www.ory.sh" },
|
||||
}),
|
||||
}
|
||||
|
||||
// Format is
|
||||
export const verifyHrefPattern =
|
||||
/^http:.*\/self-service\/verification\?(((&|)code|(&|)token|(&|)flow)=([\-a-zA-Z0-9]+)){2}$/
|
||||
|
||||
// intervals define how long to wait for something,
|
||||
export const pollInterval = 250 // how long to wait before retry
|
||||
|
||||
// Adding 1+ second on top because MySQL doesn't do millisecs.
|
||||
export const verifyLifespan = 5000 + 1000
|
||||
export const privilegedLifespan = 5000 + 1000
|
||||
|
||||
export const appPrefix = (app) => `[data-testid="app-${app}"] `
|
||||
|
||||
export const codeRegex = /(\d{6})/
|
||||
|
||||
export function extractOTPCode(body: string): string | null {
|
||||
const result = codeRegex.exec(body)
|
||||
if (result != null && result.length > 0) {
|
||||
return result[0]
|
||||
}
|
||||
return null
|
||||
}
|
||||
106
test/e2e/cypress/helpers/oauth2.ts
Normal file
106
test/e2e/cypress/helpers/oauth2.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import * as uuid from "uuid"
|
||||
|
||||
export type oAuth2Client = {
|
||||
auth_endpoint: string
|
||||
token_endpoint: string
|
||||
id: string
|
||||
secret: string
|
||||
token_endpoint_auth_method: string
|
||||
grant_types: string[]
|
||||
response_types: string[]
|
||||
scopes: string[]
|
||||
callbacks: string[]
|
||||
}
|
||||
|
||||
export function getDefaultAuthorizeURL(client: oAuth2Client) {
|
||||
const state = uuid.v4()
|
||||
const nonce = uuid.v4()
|
||||
return getAuthorizeURL(
|
||||
client.auth_endpoint,
|
||||
"",
|
||||
client.id,
|
||||
undefined,
|
||||
nonce,
|
||||
"https://ory-network-httpbin-ijakee5waq-ez.a.run.app/anything",
|
||||
"code",
|
||||
["offline", "openid"],
|
||||
state,
|
||||
undefined,
|
||||
)
|
||||
}
|
||||
|
||||
export function getAuthorizeURL(
|
||||
auth_endpoint: string,
|
||||
audience: string,
|
||||
client_id: string,
|
||||
max_age: string | undefined,
|
||||
nonce: string,
|
||||
redirect_uri: string,
|
||||
response_type:
|
||||
| "code"
|
||||
| "id_token"
|
||||
| "id_token token"
|
||||
| "code id_token"
|
||||
| "code token"
|
||||
| "code id_token token",
|
||||
scopes: string[],
|
||||
state: string,
|
||||
code_challenge?: string,
|
||||
): string {
|
||||
const r = new URL(auth_endpoint)
|
||||
r.searchParams.append("audience", audience)
|
||||
r.searchParams.append("client_id", client_id)
|
||||
if (max_age !== undefined) {
|
||||
r.searchParams.append("max_age", max_age)
|
||||
}
|
||||
r.searchParams.append("nonce", nonce)
|
||||
r.searchParams.append("prompt", "")
|
||||
r.searchParams.append("redirect_uri", redirect_uri)
|
||||
r.searchParams.append("response_type", response_type)
|
||||
r.searchParams.append("scope", scopes.join(" "))
|
||||
r.searchParams.append("state", state)
|
||||
|
||||
code_challenge && r.searchParams.append("code_challenge", code_challenge)
|
||||
return r.toString()
|
||||
}
|
||||
|
||||
export function getToken(
|
||||
token_endpoint: string,
|
||||
client_id: string,
|
||||
client_secret: string,
|
||||
grant_type: "authorization_code",
|
||||
code: string,
|
||||
redirect_uri: string,
|
||||
scope: string,
|
||||
) {
|
||||
let urlEncodedData = ""
|
||||
const urlEncodedDataPairs = []
|
||||
urlEncodedDataPairs.push(
|
||||
encodeURIComponent("grant_type") + "=" + encodeURIComponent(grant_type),
|
||||
)
|
||||
urlEncodedDataPairs.push(
|
||||
encodeURIComponent("code") + "=" + encodeURIComponent(code),
|
||||
)
|
||||
urlEncodedDataPairs.push(
|
||||
encodeURIComponent("redirect_uri") + "=" + encodeURIComponent(redirect_uri),
|
||||
)
|
||||
urlEncodedDataPairs.push(
|
||||
encodeURIComponent("scope") + "=" + encodeURIComponent(scope),
|
||||
)
|
||||
|
||||
urlEncodedData = urlEncodedDataPairs.join("&").replace(/%20/g, "+")
|
||||
|
||||
return cy.request({
|
||||
method: "POST",
|
||||
url: token_endpoint,
|
||||
form: true,
|
||||
body: urlEncodedData,
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
Authorization: "Basic " + btoa(client_id + ":" + client_secret),
|
||||
},
|
||||
})
|
||||
}
|
||||
13
test/e2e/cypress/helpers/react.ts
Normal file
13
test/e2e/cypress/helpers/react.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
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",
|
||||
}
|
||||
70
test/e2e/cypress/helpers/webhook.ts
Normal file
70
test/e2e/cypress/helpers/webhook.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { fail } from "assert"
|
||||
import { gen } from "."
|
||||
|
||||
const WEBHOOK_TARGET = "https://webhook-target-gsmwn5ab4a-uc.a.run.app"
|
||||
const documentUrl = (key: string) => `${WEBHOOK_TARGET}/documents/${key}`
|
||||
const jsonnet = Buffer.from("function(ctx) ctx").toString("base64")
|
||||
|
||||
export const testFlowWebhook = (
|
||||
configSetup: (
|
||||
hooks: Array<{ hook: string; config?: any }>,
|
||||
) => Cypress.Chainable<void>,
|
||||
act: () => Cypress.Chainable<void> | void,
|
||||
) => {
|
||||
const documentID = gen.password()
|
||||
configSetup([
|
||||
{
|
||||
hook: "web_hook",
|
||||
config: {
|
||||
body: "base64://" + jsonnet,
|
||||
url: documentUrl(documentID),
|
||||
method: "PUT",
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
const transient_payload = {
|
||||
stuff: {
|
||||
blub: [42, 3.14152],
|
||||
fu: "bar",
|
||||
},
|
||||
consent: true,
|
||||
}
|
||||
cy.intercept(
|
||||
"POST",
|
||||
/.*\/self-service\/(registration|login|recovery|verification|settings).*/,
|
||||
(req) => {
|
||||
switch (typeof req.body) {
|
||||
case "string":
|
||||
req.body =
|
||||
req.body +
|
||||
"&transient_payload=" +
|
||||
encodeURIComponent(JSON.stringify(transient_payload))
|
||||
break
|
||||
case "object":
|
||||
req.body = {
|
||||
...req.body,
|
||||
transient_payload,
|
||||
}
|
||||
break
|
||||
|
||||
default:
|
||||
fail()
|
||||
break
|
||||
}
|
||||
req.continue()
|
||||
},
|
||||
)
|
||||
|
||||
act()
|
||||
|
||||
cy.request(documentUrl(documentID)).then(({ body, status }) => {
|
||||
const b = JSON.parse(body)
|
||||
expect(status).to.equal(200)
|
||||
expect(b.identity).is.not.undefined
|
||||
expect(b.flow.transient_payload).to.deep.equal(transient_payload)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user