fix: allow dots in username (#11706)
* fix: allow dots in username * test: added unit tests for slugify * test: add test for username change * tests: add test for username and dynamic booking * fix: type error --------- Co-authored-by: Peer Richelsen <peeroke@gmail.com>pull/12038/head^2
parent
0014ca6865
commit
aa54c013f8
|
@ -43,9 +43,40 @@ test.describe("Change username on settings", () => {
|
||||||
id: user.id,
|
id: user.id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(newUpdatedUser.username).toBe("demousernamex");
|
expect(newUpdatedUser.username).toBe("demousernamex");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("User can change username to include periods(or dots)", async ({ page, users, prisma }) => {
|
||||||
|
const user = await users.create();
|
||||||
|
|
||||||
|
await user.apiLogin();
|
||||||
|
// Try to go homepage
|
||||||
|
await page.goto("/settings/my-account/profile");
|
||||||
|
// Change username from normal to normal
|
||||||
|
const usernameInput = page.locator("[data-testid=username-input]");
|
||||||
|
// User can change username to include dots(or periods)
|
||||||
|
await usernameInput.fill("demo.username");
|
||||||
|
await page.click("[data-testid=update-username-btn]");
|
||||||
|
await Promise.all([
|
||||||
|
page.click("[data-testid=save-username]"),
|
||||||
|
page.getByTestId("toast-success").waitFor(),
|
||||||
|
]);
|
||||||
|
await page.waitForLoadState("networkidle");
|
||||||
|
|
||||||
|
const updatedUser = await prisma.user.findUniqueOrThrow({
|
||||||
|
where: {
|
||||||
|
id: user.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(updatedUser.username).toBe("demo.username");
|
||||||
|
|
||||||
|
// Check if user avatar can be accessed and response headers contain 'image/' in the content type
|
||||||
|
const response = await page.goto("/demo.username/avatar.png");
|
||||||
|
expect(response?.headers()?.["content-type"]).toContain("image/");
|
||||||
|
});
|
||||||
|
|
||||||
test("User can update to PREMIUM username", async ({ page, users }, testInfo) => {
|
test("User can update to PREMIUM username", async ({ page, users }, testInfo) => {
|
||||||
// eslint-disable-next-line playwright/no-skipped-test
|
// eslint-disable-next-line playwright/no-skipped-test
|
||||||
test.skip(!IS_STRIPE_ENABLED, "It should only run if Stripe is installed");
|
test.skip(!IS_STRIPE_ENABLED, "It should only run if Stripe is installed");
|
||||||
|
|
|
@ -13,7 +13,7 @@ test("dynamic booking", async ({ page, users }) => {
|
||||||
const pro = await users.create();
|
const pro = await users.create();
|
||||||
await pro.apiLogin();
|
await pro.apiLogin();
|
||||||
|
|
||||||
const free = await users.create({ username: "free" });
|
const free = await users.create({ username: "free.example" });
|
||||||
await page.goto(`/${pro.username}+${free.username}`);
|
await page.goto(`/${pro.username}+${free.username}`);
|
||||||
|
|
||||||
await test.step("book an event first day in next month", async () => {
|
await test.step("book an event first day in next month", async () => {
|
||||||
|
|
|
@ -635,7 +635,7 @@ export const TestData = {
|
||||||
example: {
|
example: {
|
||||||
name: "Example",
|
name: "Example",
|
||||||
email: "example@example.com",
|
email: "example@example.com",
|
||||||
username: "example",
|
username: "example.username",
|
||||||
defaultScheduleId: 1,
|
defaultScheduleId: 1,
|
||||||
timeZone: Timezones["+5:30"],
|
timeZone: Timezones["+5:30"],
|
||||||
},
|
},
|
||||||
|
|
|
@ -30,6 +30,21 @@ describe("slugify", () => {
|
||||||
expect(slugify("$hello-there_")).toEqual("hello-there");
|
expect(slugify("$hello-there_")).toEqual("hello-there");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should keep periods as is except the start and end", () => {
|
||||||
|
expect(slugify("hello.there")).toEqual("hello.there");
|
||||||
|
expect(slugify("h.e.l.l.o.t.h.e.r.e")).toEqual("h.e.l.l.o.t.h.e.r.e");
|
||||||
|
});
|
||||||
|
it("should remove consecutive periods", () => {
|
||||||
|
expect(slugify("hello...there")).toEqual("hello.there");
|
||||||
|
expect(slugify("hello....there")).toEqual("hello.there");
|
||||||
|
expect(slugify("hello..there")).toEqual("hello.there");
|
||||||
|
});
|
||||||
|
it("should remove periods from start and end", () => {
|
||||||
|
expect(slugify(".hello.there")).toEqual("hello.there");
|
||||||
|
expect(slugify(".hello.there.")).toEqual("hello.there");
|
||||||
|
expect(slugify("hellothere.")).toEqual("hellothere");
|
||||||
|
});
|
||||||
|
|
||||||
// This is failing, if we want to fix it, one approach is as used in getValidRhfFieldName
|
// This is failing, if we want to fix it, one approach is as used in getValidRhfFieldName
|
||||||
it.skip("should remove unicode and emoji characters", () => {
|
it.skip("should remove unicode and emoji characters", () => {
|
||||||
expect(slugify("Hello 📚🕯️®️ There")).toEqual("hello---------there");
|
expect(slugify("Hello 📚🕯️®️ There")).toEqual("hello---------there");
|
||||||
|
|
|
@ -7,11 +7,13 @@ export const slugify = (str: string, forDisplayingInput?: boolean) => {
|
||||||
.trim() // Remove whitespace from both sides
|
.trim() // Remove whitespace from both sides
|
||||||
.normalize("NFD") // Normalize to decomposed form for handling accents
|
.normalize("NFD") // Normalize to decomposed form for handling accents
|
||||||
.replace(/\p{Diacritic}/gu, "") // Remove any diacritics (accents) from characters
|
.replace(/\p{Diacritic}/gu, "") // Remove any diacritics (accents) from characters
|
||||||
.replace(/[^\p{L}\p{N}\p{Zs}\p{Emoji}]+/gu, "-") // Replace any non-alphanumeric characters (including Unicode) with a dash
|
.replace(/[^.\p{L}\p{N}\p{Zs}\p{Emoji}]+/gu, "-") // Replace any non-alphanumeric characters (including Unicode and except "." period) with a dash
|
||||||
.replace(/[\s_#]+/g, "-") // Replace whitespace, # and underscores with a single dash
|
.replace(/[\s_#]+/g, "-") // Replace whitespace, # and underscores with a single dash
|
||||||
.replace(/^-+/, ""); // Remove dashes from start
|
.replace(/^-+/, "") // Remove dashes from start
|
||||||
|
.replace(/\.{2,}/g, ".") // Replace consecutive periods with a single period
|
||||||
|
.replace(/^\.+/, ""); // Remove periods from the start
|
||||||
|
|
||||||
return forDisplayingInput ? s : s.replace(/-+$/, ""); // Remove dashes from end
|
return forDisplayingInput ? s : s.replace(/-+$/, "").replace(/\.*$/, ""); // Remove dashes and period from end
|
||||||
};
|
};
|
||||||
|
|
||||||
export default slugify;
|
export default slugify;
|
||||||
|
|
Loading…
Reference in New Issue