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
Udit Takkar 2023-10-23 18:07:30 +05:30 committed by GitHub
parent 0014ca6865
commit aa54c013f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 53 additions and 5 deletions

View File

@ -43,9 +43,40 @@ test.describe("Change username on settings", () => {
id: user.id,
},
});
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) => {
// eslint-disable-next-line playwright/no-skipped-test
test.skip(!IS_STRIPE_ENABLED, "It should only run if Stripe is installed");

View File

@ -13,7 +13,7 @@ test("dynamic booking", async ({ page, users }) => {
const pro = await users.create();
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 test.step("book an event first day in next month", async () => {

View File

@ -635,7 +635,7 @@ export const TestData = {
example: {
name: "Example",
email: "example@example.com",
username: "example",
username: "example.username",
defaultScheduleId: 1,
timeZone: Timezones["+5:30"],
},

View File

@ -30,6 +30,21 @@ describe("slugify", () => {
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
it.skip("should remove unicode and emoji characters", () => {
expect(slugify("Hello 📚🕯️®️ There")).toEqual("hello---------there");

View File

@ -7,11 +7,13 @@ export const slugify = (str: string, forDisplayingInput?: boolean) => {
.trim() // Remove whitespace from both sides
.normalize("NFD") // Normalize to decomposed form for handling accents
.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(/^-+/, ""); // 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;