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:
@@ -0,0 +1,382 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { Session } from "@ory/kratos-client"
|
||||
import { gen, MOBILE_URL } from "../../../../helpers"
|
||||
import { routes as express } from "../../../../helpers/express"
|
||||
import { routes as react } from "../../../../helpers/react"
|
||||
|
||||
const Selectors = {
|
||||
mobile: {
|
||||
identifier: "[data-testid='field/identifier']",
|
||||
recoveryEmail: "[data-testid='field/email']",
|
||||
email: "[data-testid='traits.email']",
|
||||
email2: "[data-testid='traits.email2']",
|
||||
website: "[data-testid='traits.website']",
|
||||
username: "[data-testid='traits.username']",
|
||||
code: "[data-testid='field/code'] input",
|
||||
recoveryCode: "[data-testid='code']",
|
||||
submitCode: "[data-testid='field/method/code']",
|
||||
resendCode: "[data-testid='field/resend/code']",
|
||||
credentialSelection: "[data-testid='field/screen/credential-selection']",
|
||||
submitRecovery: "[data-testid='field/method/code']",
|
||||
codeHiddenMethod: "[data-testid='field/method/code']",
|
||||
},
|
||||
express: {
|
||||
identifier: "[data-testid='login-flow-code'] input[name='identifier']",
|
||||
recoveryEmail: "input[name=email]",
|
||||
email: "[data-testid='node/input/traits.email'] input[name='traits.email']",
|
||||
email2:
|
||||
"[data-testid='node/input/traits.email2'] input[name='traits.email2']",
|
||||
website:
|
||||
"[data-testid='node/input/traits.website'] [name='traits.website']",
|
||||
username:
|
||||
"[data-testid='node/input/traits.username'] input[name='traits.username']",
|
||||
code: "input[name='code']",
|
||||
recoveryCode: "input[name=code]",
|
||||
submitRecovery: "button[name=method][value=code]",
|
||||
submitCode: "button[name='method'][value='code']",
|
||||
resendCode: "button[name='resend'][value='code']",
|
||||
codeHiddenMethod: "input[name='method'][value='code'][type='hidden']",
|
||||
credentialSelection: "[name='screen'][value='credential-selection']",
|
||||
},
|
||||
react: {
|
||||
identifier: "input[name='identifier']",
|
||||
recoveryEmail: "input[name=email]",
|
||||
email: "input[name='traits.email']",
|
||||
email2: "input[name='traits.email2']",
|
||||
website: "[name='traits.website']",
|
||||
username: "input[name='traits.username']",
|
||||
code: "input[name='code']",
|
||||
recoveryCode: "input[name=code]",
|
||||
submitRecovery: "button[name=method][value=code]",
|
||||
submitCode: "button[name='method'][value='code']",
|
||||
resendCode: "button[name='resend'][value='code']",
|
||||
codeHiddenMethod: "input[name='method'][value='code'][type='hidden']",
|
||||
credentialSelection: "[name='screen'][value='credential-selection']",
|
||||
},
|
||||
}
|
||||
|
||||
context("Registration success with code method", () => {
|
||||
;[
|
||||
{
|
||||
route: express.registration,
|
||||
login: express.login,
|
||||
recovery: express.recovery,
|
||||
app: "express" as "express",
|
||||
profile: "two-steps",
|
||||
},
|
||||
{
|
||||
route: react.registration,
|
||||
login: react.login,
|
||||
recovery: react.recovery,
|
||||
app: "react" as "react",
|
||||
profile: "two-steps",
|
||||
},
|
||||
{
|
||||
route: MOBILE_URL + "/Registration",
|
||||
login: MOBILE_URL + "/Login",
|
||||
recovery: MOBILE_URL + "/Recovery",
|
||||
app: "mobile" as "mobile",
|
||||
profile: "two-steps",
|
||||
},
|
||||
].forEach(({ route, login, recovery, profile, app }) => {
|
||||
describe(`for app ${app}`, () => {
|
||||
before(() => {
|
||||
cy.useConfigProfile(profile)
|
||||
if (app !== "mobile") {
|
||||
cy.proxy(app)
|
||||
}
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
cy.deleteMail({ atLeast: 0 })
|
||||
cy.clearAllCookies()
|
||||
cy.visit(route)
|
||||
})
|
||||
|
||||
it("should be able to resend the registration code", () => {
|
||||
const email = gen.email()
|
||||
const website = "https://www.example.org/"
|
||||
|
||||
cy.get(Selectors[app]["email"]).type(email)
|
||||
cy.get(Selectors[app]["website"]).type(website)
|
||||
|
||||
cy.submitProfileForm(app)
|
||||
cy.submitCodeForm(app)
|
||||
cy.get('[data-testid="ui/message/1040005"]').should("be.visible")
|
||||
|
||||
cy.getRegistrationCodeFromEmail(email).then((code) =>
|
||||
cy.wrap(code).as("code1"),
|
||||
)
|
||||
|
||||
// cy.get(Selectors[app]["email"]).should("have.value", email)
|
||||
cy.get(Selectors[app]["codeHiddenMethod"]).should("exist")
|
||||
cy.get(Selectors[app]["resendCode"]).click()
|
||||
|
||||
cy.getRegistrationCodeFromEmail(email).then((code) => {
|
||||
cy.wrap(code).as("code2")
|
||||
})
|
||||
|
||||
cy.get("@code1").then((code1) => {
|
||||
// previous code should not work
|
||||
cy.get(Selectors[app]["code"]).clear()
|
||||
cy.get(Selectors[app]["code"]).type(code1.toString())
|
||||
|
||||
cy.submitCodeForm(app)
|
||||
cy.get('[data-testid="ui/message/4040003"]').should(
|
||||
"contain.text",
|
||||
"The registration code is invalid or has already been used. Please try again.",
|
||||
)
|
||||
})
|
||||
|
||||
// Navigate back and forth again
|
||||
cy.get(Selectors[app]["credentialSelection"]).click()
|
||||
cy.submitCodeForm(app)
|
||||
|
||||
cy.getRegistrationCodeFromEmail(email).then((code) => {
|
||||
cy.wrap(code).as("code2")
|
||||
})
|
||||
|
||||
cy.get("@code2").then((code2) => {
|
||||
cy.get(Selectors[app]["code"]).clear()
|
||||
cy.get(Selectors[app]["code"]).type(code2.toString())
|
||||
cy.submitCodeForm(app)
|
||||
})
|
||||
|
||||
if (app === "express") {
|
||||
cy.url().should("match", /\/welcome/)
|
||||
} else {
|
||||
cy.get('[data-testid="session-content"]').should("contain", email)
|
||||
}
|
||||
|
||||
if (app === "mobile") {
|
||||
cy.get('[data-testid="session-token"]').should("not.be.empty")
|
||||
cy.get('[data-testid="session-token"]').then((token) => {
|
||||
cy.getSession({
|
||||
expectAal: "aal1",
|
||||
expectMethods: ["code"],
|
||||
token: token.text(),
|
||||
}).then((session) => {
|
||||
cy.wrap(session).as("session")
|
||||
})
|
||||
})
|
||||
} else {
|
||||
cy.getSession({ expectAal: "aal1", expectMethods: ["code"] }).then(
|
||||
(session) => {
|
||||
cy.wrap(session).as("session")
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
cy.get<Session>("@session").then(({ identity }) => {
|
||||
expect(identity.id).to.not.be.empty
|
||||
expect(identity.traits.email).to.equal(email)
|
||||
})
|
||||
})
|
||||
|
||||
// playwright:migrated
|
||||
it("should sign up and be logged in with session hook", () => {
|
||||
if (app === "react") {
|
||||
// This test is flaky on React, so we skip it for now.
|
||||
return
|
||||
}
|
||||
|
||||
const email = gen.email()
|
||||
const website = "https://www.example.org/"
|
||||
|
||||
cy.get(Selectors[app]["email"]).type(email)
|
||||
cy.get(Selectors[app]["website"]).type(website)
|
||||
cy.submitProfileForm(app)
|
||||
|
||||
cy.submitCodeForm(app)
|
||||
cy.get('[data-testid="ui/message/1040005"]').should("be.visible")
|
||||
|
||||
cy.getRegistrationCodeFromEmail(email).then((code) => {
|
||||
cy.get(Selectors[app]["code"]).type(code)
|
||||
cy.get(Selectors[app]["submitCode"]).click()
|
||||
})
|
||||
|
||||
if (app === "mobile") {
|
||||
cy.get('[data-testid="session-token"]').then((token) => {
|
||||
cy.getSession({
|
||||
expectAal: "aal1",
|
||||
expectMethods: ["code"],
|
||||
token: token.text(),
|
||||
}).then((session) => {
|
||||
cy.wrap(session).as("session")
|
||||
})
|
||||
})
|
||||
|
||||
cy.get('[data-testid="session-content"]').should("contain", email)
|
||||
cy.get('[data-testid="session-token"]').should("not.be.empty")
|
||||
} else {
|
||||
cy.getSession({ expectAal: "aal1", expectMethods: ["code"] }).then(
|
||||
(session) => {
|
||||
cy.wrap(session).as("session")
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
cy.get<Session>("@session").then(({ identity }) => {
|
||||
expect(identity.id).to.not.be.empty
|
||||
expect(identity.traits.email).to.equal(email)
|
||||
})
|
||||
})
|
||||
|
||||
// playwright:migrated
|
||||
it("should be able to sign up without session hook", () => {
|
||||
if (app === "react") {
|
||||
// This test is flaky on React, so we skip it for now.
|
||||
return
|
||||
}
|
||||
|
||||
cy.setPostCodeRegistrationHooks([])
|
||||
const email = gen.email()
|
||||
const website = "https://www.example.org/"
|
||||
|
||||
cy.get(Selectors[app]["email"]).type(email)
|
||||
cy.get(Selectors[app]["website"]).type(website)
|
||||
cy.submitProfileForm(app)
|
||||
|
||||
cy.submitCodeForm(app)
|
||||
cy.get('[data-testid="ui/message/1040005"]').should("be.visible")
|
||||
|
||||
cy.getRegistrationCodeFromEmail(email).then((code) => {
|
||||
cy.get(Selectors[app]["code"]).type(code)
|
||||
cy.get(Selectors[app]["submitCode"]).click()
|
||||
})
|
||||
|
||||
cy.visit(login)
|
||||
cy.get(Selectors[app]["identifier"]).type(email)
|
||||
cy.get(Selectors[app]["submitCode"]).click()
|
||||
|
||||
cy.getLoginCodeFromEmail(email).then((code) => {
|
||||
cy.get(Selectors[app]["code"]).type(code)
|
||||
cy.get(Selectors[app]["submitCode"]).click()
|
||||
})
|
||||
|
||||
if (app === "mobile") {
|
||||
cy.get('[data-testid="session-token"]').then((token) => {
|
||||
cy.getSession({
|
||||
expectAal: "aal1",
|
||||
expectMethods: ["code"],
|
||||
token: token.text(),
|
||||
}).then((session) => {
|
||||
cy.wrap(session).as("session")
|
||||
})
|
||||
})
|
||||
|
||||
cy.get('[data-testid="session-content"]').should("contain", email)
|
||||
cy.get('[data-testid="session-token"]').should("not.be.empty")
|
||||
} else {
|
||||
cy.getSession({ expectAal: "aal1", expectMethods: ["code"] }).then(
|
||||
(session) => {
|
||||
cy.wrap(session).as("session")
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
cy.get<Session>("@session").then(({ identity }) => {
|
||||
expect(identity.id).to.not.be.empty
|
||||
expect(identity.traits.email).to.equal(email)
|
||||
})
|
||||
})
|
||||
|
||||
// Try keep this test as the last one, as it updates the identity schema.
|
||||
it("should be able to use multiple identifiers to signup with and sign in to", () => {
|
||||
cy.setPostCodeRegistrationHooks([
|
||||
{
|
||||
hook: "session",
|
||||
},
|
||||
])
|
||||
|
||||
// Setup complex schema
|
||||
cy.setIdentitySchema(
|
||||
"file://test/e2e/profiles/code/identity.complex.traits.schema.json",
|
||||
)
|
||||
|
||||
cy.visit(route)
|
||||
|
||||
cy.get(Selectors[app]["username"]).type(Math.random().toString(36))
|
||||
|
||||
const email = gen.email()
|
||||
cy.get(Selectors[app]["email"]).type(email)
|
||||
|
||||
const email2 = gen.email()
|
||||
cy.get(Selectors[app]["email2"]).type(email2)
|
||||
|
||||
cy.submitProfileForm(app)
|
||||
cy.submitCodeForm(app)
|
||||
cy.get('[data-testid="ui/message/1040005"]').should("be.visible")
|
||||
|
||||
// intentionally use email 1 to sign up for the account
|
||||
cy.getRegistrationCodeFromEmail(email, { expectedCount: 1 }).then(
|
||||
(code) => {
|
||||
cy.get(Selectors[app]["code"]).type(code)
|
||||
cy.get(Selectors[app]["submitCode"]).click()
|
||||
},
|
||||
)
|
||||
|
||||
if (app === "mobile") {
|
||||
cy.visit(MOBILE_URL + "/Home")
|
||||
cy.get('*[data-testid="logout"]').click()
|
||||
} else {
|
||||
cy.logout()
|
||||
}
|
||||
|
||||
// There are verification emails from the registration process in the inbox that we need to deleted
|
||||
// for the assertions below to pass.
|
||||
cy.deleteMail({ atLeast: 1 })
|
||||
|
||||
// Attempt to sign in with email 2 (should fail)
|
||||
cy.visit(login)
|
||||
cy.get(Selectors[app]["identifier"]).type(email2)
|
||||
|
||||
cy.get(Selectors[app]["submitCode"]).click()
|
||||
|
||||
cy.getLoginCodeFromEmail(email2, {
|
||||
expectedCount: 1,
|
||||
}).then((code) => {
|
||||
cy.get(Selectors[app]["code"]).type(code)
|
||||
cy.get(Selectors[app]["submitCode"]).click()
|
||||
})
|
||||
|
||||
if (app === "mobile") {
|
||||
cy.get('[data-testid="session-token"]').then((token) => {
|
||||
cy.getSession({
|
||||
expectAal: "aal1",
|
||||
expectMethods: ["code"],
|
||||
token: token.text(),
|
||||
}).then((session) => {
|
||||
cy.wrap(session).as("session")
|
||||
})
|
||||
})
|
||||
|
||||
cy.get('[data-testid="session-content"]').should("contain", email)
|
||||
cy.get('[data-testid="session-token"]').should("not.be.empty")
|
||||
} else {
|
||||
cy.getSession({ expectAal: "aal1", expectMethods: ["code"] }).then(
|
||||
(session) => {
|
||||
cy.wrap(session).as("session")
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
cy.get<Session>("@session").then(({ identity }) => {
|
||||
expect(identity.id).to.not.be.empty
|
||||
expect(identity.verifiable_addresses).to.have.length(2)
|
||||
expect(
|
||||
identity.verifiable_addresses.filter((v) => v.value === email)[0]
|
||||
.status,
|
||||
).to.equal("completed")
|
||||
expect(
|
||||
identity.verifiable_addresses.filter((v) => v.value === email2)[0]
|
||||
.status,
|
||||
).to.equal("completed")
|
||||
expect(identity.traits.email).to.equal(email)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,225 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { appPrefix, gen, website } from "../../../../helpers"
|
||||
import { routes as express } from "../../../../helpers/express"
|
||||
import { routes as react } from "../../../../helpers/react"
|
||||
import { testFlowWebhook } from "../../../../helpers/webhook"
|
||||
|
||||
context("Social Sign Up Successes", () => {
|
||||
;[
|
||||
{
|
||||
login: react.login,
|
||||
registration: react.registration,
|
||||
app: "react" as "react",
|
||||
profile: "two-steps",
|
||||
},
|
||||
{
|
||||
login: express.login,
|
||||
registration: express.registration,
|
||||
app: "express" as "express",
|
||||
profile: "two-steps",
|
||||
},
|
||||
].forEach(({ registration, login, profile, app }) => {
|
||||
describe(`for app ${app}`, () => {
|
||||
before(() => {
|
||||
cy.useConfigProfile(profile)
|
||||
cy.proxy(app)
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
cy.clearAllCookies()
|
||||
cy.visit(registration)
|
||||
cy.setIdentitySchema(
|
||||
"file://test/e2e/profiles/oidc/identity.traits.schema.json",
|
||||
)
|
||||
})
|
||||
|
||||
const shouldSession = (email) => (session) => {
|
||||
const { identity } = session
|
||||
expect(identity.id).to.not.be.empty
|
||||
expect(identity.traits.website).to.equal(website)
|
||||
expect(identity.traits.email).to.equal(email)
|
||||
}
|
||||
|
||||
it("should be able to sign up with incomplete data and finally be signed in", () => {
|
||||
const email = gen.email()
|
||||
|
||||
cy.registerOidc({
|
||||
app,
|
||||
email,
|
||||
expectSession: false,
|
||||
route: registration,
|
||||
})
|
||||
|
||||
cy.get("#registration-password").should("not.exist")
|
||||
cy.get(appPrefix(app) + '[name="traits.email"]').should(
|
||||
"have.value",
|
||||
email,
|
||||
)
|
||||
cy.get('[data-testid="ui/message/4000002"]').should(
|
||||
"contain.text",
|
||||
"Property website is missing",
|
||||
)
|
||||
|
||||
cy.get('[name="traits.consent"][type="checkbox"]')
|
||||
.siblings("label")
|
||||
.click()
|
||||
cy.get('[name="traits.newsletter"][type="checkbox"]')
|
||||
.siblings("label")
|
||||
.click()
|
||||
cy.get('[name="traits.website"]').type("http://s")
|
||||
|
||||
cy.get('[name="provider"]')
|
||||
.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('[data-testid="ui/message/4000003"]').should(
|
||||
"contain.text",
|
||||
"length must be >= 10",
|
||||
)
|
||||
cy.get('[name="traits.website"]')
|
||||
.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.triggerOidc(app)
|
||||
|
||||
cy.location("pathname").should((loc) => {
|
||||
expect(loc).to.be.oneOf(["/welcome", "/", "/sessions"])
|
||||
})
|
||||
|
||||
cy.getSession().should((session) => {
|
||||
shouldSession(email)(session)
|
||||
expect(session.identity.traits.consent).to.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
it("should pass transient_payload to webhook", () => {
|
||||
testFlowWebhook(
|
||||
(hooks) =>
|
||||
cy.setupHooks("registration", "after", "oidc", [
|
||||
...hooks,
|
||||
{ hook: "session" },
|
||||
]),
|
||||
() => {
|
||||
const email = gen.email()
|
||||
cy.registerOidc({
|
||||
app,
|
||||
email,
|
||||
website,
|
||||
route: registration,
|
||||
})
|
||||
cy.getSession().should(shouldSession(email))
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
it("should be able to sign up with complete data", () => {
|
||||
const email = gen.email()
|
||||
|
||||
cy.registerOidc({ app, email, website, route: registration })
|
||||
cy.getSession().should(shouldSession(email))
|
||||
})
|
||||
|
||||
it("should be able to convert a sign up flow to a sign in flow", () => {
|
||||
const email = gen.email()
|
||||
|
||||
cy.registerOidc({ app, email, website, route: registration })
|
||||
cy.logout()
|
||||
cy.noSession()
|
||||
cy.visit(registration)
|
||||
cy.triggerOidc(app)
|
||||
|
||||
cy.location("pathname").should((path) => {
|
||||
expect(path).to.oneOf(["/", "/welcome", "/sessions"])
|
||||
})
|
||||
|
||||
cy.getSession().should(shouldSession(email))
|
||||
})
|
||||
|
||||
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",
|
||||
)
|
||||
|
||||
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('[name="scope"]').each(($el) => cy.wrap($el).click())
|
||||
cy.get("#remember").click()
|
||||
cy.get("#accept").click()
|
||||
|
||||
cy.get('[data-testid="ui/message/4000002"]').should(
|
||||
"contain.text",
|
||||
"Property website is missing",
|
||||
)
|
||||
cy.get('[name="traits.website"]').type("http://s")
|
||||
|
||||
cy.triggerOidc(app)
|
||||
|
||||
cy.get('[data-testid="ui/message/4000003"]').should(
|
||||
"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.website"]')
|
||||
.should("have.value", "http://s")
|
||||
.clear()
|
||||
.type(website)
|
||||
cy.triggerOidc(app)
|
||||
|
||||
cy.location("pathname").should("not.contain", "/registration")
|
||||
|
||||
cy.getSession().should(shouldSession(email))
|
||||
})
|
||||
|
||||
it("should be able to sign up with redirects", () => {
|
||||
const email = gen.email()
|
||||
cy.registerOidc({
|
||||
app,
|
||||
email,
|
||||
website,
|
||||
route: registration + "?return_to=https://www.example.org/",
|
||||
})
|
||||
cy.location("href").should("eq", "https://www.example.org/")
|
||||
cy.logout()
|
||||
})
|
||||
|
||||
it("should be able to register with upstream parameters", () => {
|
||||
const email = gen.email()
|
||||
cy.intercept("GET", "**/oauth2/auth*").as("getHydraRegistration")
|
||||
|
||||
cy.visit(registration + "?return_to=https://www.example.org/")
|
||||
|
||||
// hd is forwarded; login_hint is never forwarded because a
|
||||
// caller-supplied value cannot be trusted (HackerOne #3239672,
|
||||
// ory-corp/cloud#8955).
|
||||
cy.addInputElement("form", "upstream_parameters.hd", "ory.sh")
|
||||
cy.addInputElement("form", "upstream_parameters.login_hint", email)
|
||||
|
||||
cy.triggerOidc(app)
|
||||
|
||||
// once a request to getHydraRegistration responds, 'cy.wait' will resolve
|
||||
cy.wait("@getHydraRegistration")
|
||||
.its("request.url")
|
||||
.should("include", "hd=ory.sh")
|
||||
.and("not.include", "login_hint")
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,117 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { appPrefix, APP_URL, gen } from "../../../../helpers"
|
||||
import { routes as express } from "../../../../helpers/express"
|
||||
import { routes as react } from "../../../../helpers/react"
|
||||
|
||||
context("Registration success with two-step signup", () => {
|
||||
;[
|
||||
{
|
||||
route: express.registration,
|
||||
app: "express" as "express",
|
||||
profile: "two-steps",
|
||||
},
|
||||
{
|
||||
route: react.registration,
|
||||
app: "react" as "react",
|
||||
profile: "two-steps",
|
||||
},
|
||||
].forEach(({ route, profile, app }) => {
|
||||
describe(`for app ${app}`, () => {
|
||||
before(() => {
|
||||
cy.useConfigProfile(profile)
|
||||
cy.proxy(app)
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
cy.deleteMail()
|
||||
cy.clearAllCookies()
|
||||
cy.visit(route)
|
||||
cy.enableVerification()
|
||||
if (app === "express") {
|
||||
cy.enableVerificationUIAfterRegistration("password")
|
||||
}
|
||||
})
|
||||
|
||||
// playwright:migrated
|
||||
it("should sign up and be logged in", () => {
|
||||
const email = gen.email()
|
||||
const password = gen.password()
|
||||
const website = "https://www.example.org/"
|
||||
|
||||
// Fill out step one forms
|
||||
cy.get(appPrefix(app) + 'input[name="traits"]').should("not.exist")
|
||||
cy.get('input[name="traits.email"]').type("someone@foo")
|
||||
cy.get('input[name="traits.website"]').type(website)
|
||||
cy.get('[name="method"][value="profile"]').click()
|
||||
|
||||
// navigate back, fill traits again
|
||||
cy.get('[name="screen"][value="previous"]').click()
|
||||
cy.get('input[name="traits.email"]').type(
|
||||
"{selectall}{backspace}" + email,
|
||||
)
|
||||
cy.get('[name="method"][value="profile"]').click()
|
||||
|
||||
// Fill out step two forms
|
||||
cy.get('input[name="password"]').type(password)
|
||||
cy.get('[name="method"][value="password"]').click()
|
||||
|
||||
if (app === "express") {
|
||||
cy.get('a[href*="sessions"]').click()
|
||||
}
|
||||
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_url).to.equal(`${APP_URL}/schemas/ZGVmYXVsdA`)
|
||||
expect(identity.traits.website).to.equal(website)
|
||||
expect(identity.traits.email).to.equal(email)
|
||||
})
|
||||
})
|
||||
|
||||
// playwright:migrated
|
||||
it("should handle form errors", () => {
|
||||
const email = gen.email()
|
||||
const password = gen.password()
|
||||
const websiteTooShort = "a://b"
|
||||
const website = "https://www.example.com"
|
||||
|
||||
// Fill out step one forms
|
||||
cy.get(appPrefix(app) + 'input[name="traits"]').should("not.exist")
|
||||
cy.get('input[name="traits.email"]').type(email)
|
||||
cy.get('input[name="traits.website"]').type(websiteTooShort)
|
||||
cy.get('[name="method"][value="profile"]').click()
|
||||
|
||||
// Assert form errors
|
||||
cy.get('[data-testid="ui/message/4000003"]').should("to.exist")
|
||||
|
||||
// Enter correct value
|
||||
cy.get('input[name="traits.website"]').type(
|
||||
"{selectall}{backspace}" + website,
|
||||
)
|
||||
cy.get('[name="method"][value="profile"]').click()
|
||||
|
||||
// Fill out step two forms
|
||||
cy.get('input[name="password"]').type(password)
|
||||
cy.get('[name="method"][value="password"]').click()
|
||||
|
||||
if (app === "express") {
|
||||
cy.get('a[href*="sessions"]').click()
|
||||
}
|
||||
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_url).to.equal(`${APP_URL}/schemas/ZGVmYXVsdA`)
|
||||
expect(identity.traits.website).to.equal(website)
|
||||
expect(identity.traits.email).to.equal(email)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user