mirror of
https://github.com/better-auth/better-auth.git
synced 2026-07-28 06:47:20 -05:00
test(organization, username): union regression suites with next features (#9616, #9577, #9792, #9464)
Resolves the team and username test-file conflicts as the union of next's new feature suites and main's regression tests, whose source fixes merged in cleanly: - team.test.ts keeps next's listUserTeams suites and adds main's comma-in-team-id rejection test (#9616), plus the databaseHooks.user.create.before -> emailVerified:true setup needed because the merged invitation gate now defaults on (#9577). - username.test.ts keeps next's immutable-username suite and adds main's verify-email callbackURL encoding test (#9792); the admin createUser username validation (#9464) is orthogonal and merged cleanly. team.test.ts 43 pass, username.test.ts 41 pass. (cherry picked from commit ea3ed7af30c12901252085c5ddf43a7dca57f929)
This commit is contained in:
@@ -23,6 +23,15 @@ describe("team", async () => {
|
||||
logger: {
|
||||
level: "error",
|
||||
},
|
||||
databaseHooks: {
|
||||
user: {
|
||||
create: {
|
||||
before: async (user) => ({
|
||||
data: { ...user, emailVerified: true },
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const { headers } = await signInWithTestUser();
|
||||
@@ -418,6 +427,15 @@ describe("team", async () => {
|
||||
logger: {
|
||||
level: "error",
|
||||
},
|
||||
databaseHooks: {
|
||||
user: {
|
||||
create: {
|
||||
before: async (user) => ({
|
||||
data: { ...user, emailVerified: true },
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const { headers } = await signInWithTestUser();
|
||||
@@ -518,6 +536,15 @@ describe("setActiveTeam org scoping", async () => {
|
||||
logger: {
|
||||
level: "error",
|
||||
},
|
||||
databaseHooks: {
|
||||
user: {
|
||||
create: {
|
||||
before: async (user) => ({
|
||||
data: { ...user, emailVerified: true },
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const { headers } = await signInWithTestUser();
|
||||
@@ -773,6 +800,15 @@ describe("multi team support", async () => {
|
||||
logger: {
|
||||
level: "error",
|
||||
},
|
||||
databaseHooks: {
|
||||
user: {
|
||||
create: {
|
||||
before: async (user) => ({
|
||||
data: { ...user, emailVerified: true },
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
testWith: "sqlite",
|
||||
@@ -1608,3 +1644,75 @@ describe("listUserTeams with organizationId parameter", async () => {
|
||||
expect(res).toBeInstanceOf(Error);
|
||||
});
|
||||
});
|
||||
|
||||
describe("invitation with team id containing comma", async () => {
|
||||
const { auth, signInWithTestUser } = await getTestInstance(
|
||||
{
|
||||
advanced: {
|
||||
database: {
|
||||
generateId: ({ model }) => {
|
||||
if (model === "team") {
|
||||
return `team,id,${crypto.randomUUID()}`;
|
||||
}
|
||||
return crypto.randomUUID();
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
organization({
|
||||
async sendInvitationEmail() {},
|
||||
teams: { enabled: true },
|
||||
}),
|
||||
],
|
||||
logger: { level: "error" },
|
||||
databaseHooks: {
|
||||
user: {
|
||||
create: {
|
||||
before: async (user) => ({
|
||||
data: { ...user, emailVerified: true },
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{ testWith: "sqlite" },
|
||||
);
|
||||
|
||||
const admin = await signInWithTestUser();
|
||||
|
||||
const org = await auth.api.createOrganization({
|
||||
headers: admin.headers,
|
||||
body: { name: "Comma Org", slug: "comma-org" },
|
||||
});
|
||||
if (!org) throw new Error("failed to create organization");
|
||||
const organizationId = org.id;
|
||||
|
||||
const team = await auth.api.createTeam({
|
||||
headers: admin.headers,
|
||||
body: { name: "Comma Team", organizationId },
|
||||
});
|
||||
|
||||
it("seeds a team whose generated id contains the storage separator", () => {
|
||||
expect(team.id).toContain(",");
|
||||
});
|
||||
|
||||
it.each([
|
||||
{ name: "string body", teamId: team.id },
|
||||
{ name: "array body", teamId: [team.id] },
|
||||
])("rejects createInvitation with $name", async ({ teamId }) => {
|
||||
await expect(
|
||||
auth.api.createInvitation({
|
||||
headers: admin.headers,
|
||||
body: {
|
||||
email: "comma-invitee@email.com",
|
||||
role: "member",
|
||||
organizationId,
|
||||
teamId,
|
||||
},
|
||||
}),
|
||||
).rejects.toMatchObject({
|
||||
status: "BAD_REQUEST",
|
||||
body: { code: "INVALID_TEAM_ID" },
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -819,3 +819,52 @@ describe("immutable username", async () => {
|
||||
expect(session?.user.displayUsername).toBe("Updated Display Name");
|
||||
});
|
||||
});
|
||||
|
||||
describe("username sign-in verify-email callbackURL", async () => {
|
||||
/**
|
||||
* The verify-email link sent on username sign-in for an unverified user must
|
||||
* keep the caller's `callbackURL` intact. A raw interpolation truncates any
|
||||
* value containing `&` at the first ampersand.
|
||||
*
|
||||
* @see https://github.com/better-auth/better-auth/issues/6086
|
||||
*/
|
||||
it("encodes callbackURL in the verify-email link on username sign-in", async () => {
|
||||
let capturedUrl = "";
|
||||
const { client } = await getTestInstance(
|
||||
{
|
||||
emailAndPassword: { enabled: true, requireEmailVerification: true },
|
||||
emailVerification: {
|
||||
sendOnSignIn: true,
|
||||
async sendVerificationEmail({ url }) {
|
||||
capturedUrl = url;
|
||||
},
|
||||
},
|
||||
plugins: [username()],
|
||||
},
|
||||
{
|
||||
clientOptions: {
|
||||
plugins: [usernameClient()],
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
await client.signUp.email({
|
||||
email: "encode-username@example.com",
|
||||
username: "encode_username",
|
||||
password: "correct-password",
|
||||
name: "Encode Username",
|
||||
});
|
||||
|
||||
const callbackURL = "/welcome?ref=username&plan=pro";
|
||||
await client.signIn.username({
|
||||
username: "encode_username",
|
||||
password: "correct-password",
|
||||
callbackURL,
|
||||
});
|
||||
|
||||
expect(capturedUrl).not.toBe("");
|
||||
expect(new URL(capturedUrl).searchParams.get("callbackURL")).toBe(
|
||||
callbackURL,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user