refactor: format v2 API managed user timeZone (#15273)

This commit is contained in:
Lauris Skraucis
2024-05-31 12:06:29 +00:00
committed by GitHub
parent 23bb06cc36
commit b905de435d
3 changed files with 91 additions and 0 deletions
@@ -0,0 +1,61 @@
import { plainToClass } from "class-transformer";
import { IsOptional, IsString } from "class-validator";
import { CapitalizeTimeZone } from "./capitalize-timezone";
class TestDto {
@IsOptional()
@IsString()
@CapitalizeTimeZone()
timeZone?: string;
}
describe("CapitalizeTimeZone", () => {
it("should capitalize single part time zone correctly", () => {
const input = { timeZone: "egypt" };
const output = plainToClass(TestDto, input);
expect(output.timeZone).toBe("Egypt");
});
it("should capitalize one-part time zone correctly", () => {
const input = { timeZone: "europe/rome" };
const output = plainToClass(TestDto, input);
expect(output.timeZone).toBe("Europe/Rome");
});
it("should capitalize multi-part time zone correctly", () => {
const input = { timeZone: "america/new_york" };
const output = plainToClass(TestDto, input);
expect(output.timeZone).toBe("America/New_York");
});
it("should capitalize complex time zone correctly", () => {
const input = { timeZone: "europe/isle_of_man" };
const output = plainToClass(TestDto, input);
expect(output.timeZone).toBe("Europe/Isle_Of_Man");
});
it("should handle already capitalized time zones correctly", () => {
const input = { timeZone: "Asia/Tokyo" };
const output = plainToClass(TestDto, input);
expect(output.timeZone).toBe("Asia/Tokyo");
});
it("should handle missing time zone correctly", () => {
const input = {};
const output = plainToClass(TestDto, input);
expect(output.timeZone).toBeUndefined();
});
it("should capitalize EST at the end of the string", () => {
const input = { email: "test@example.com", timeZone: "utc/est" };
const output = plainToClass(TestDto, input);
expect(output.timeZone).toBe("UTC/EST");
});
it("should capitalize UTC when surrounded by non-alphabetical characters", () => {
const input = { email: "test@example.com", timeZone: "utc/gmt+3_est" };
const output = plainToClass(TestDto, input);
expect(output.timeZone).toBe("UTC/GMT+3_EST");
});
});
@@ -0,0 +1,28 @@
import { Transform } from "class-transformer";
export function CapitalizeTimeZone(): PropertyDecorator {
return Transform(({ value }) => {
if (typeof value === "string") {
const parts = value.split("/");
const normalizedParts = parts.map((part) =>
part
.split("_")
.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
.join("_")
);
let normalizedTimeZone = normalizedParts.join("/");
// note(Lauris): regex matching GMT, EST, UTC at the start, end, or surrounded by non-letters and capitalizing them
const specialCases = ["GMT", "EST", "UTC"];
specialCases.forEach((specialCase) => {
const regex = new RegExp(`(^|[^a-zA-Z])(${specialCase})([^a-zA-Z]|$)`, "gi");
normalizedTimeZone = normalizedTimeZone.replace(regex, (match, p1, p2, p3) => {
return `${p1}${specialCase}${p3}`;
});
});
return normalizedTimeZone;
}
return value;
});
}
@@ -1,3 +1,4 @@
import { CapitalizeTimeZone } from "@/lib/inputs/capitalize-timezone";
import { ApiProperty } from "@nestjs/swagger";
import { IsOptional, IsTimeZone, IsString } from "class-validator";
@@ -26,6 +27,7 @@ export class CreateManagedUserInput {
@IsTimeZone()
@IsOptional()
@CapitalizeTimeZone()
@ApiProperty({ example: "America/New_York" })
timeZone?: string;
}