From 03faeb7c833e651a93b2aba2c91e734d05d4c83e Mon Sep 17 00:00:00 2001 From: t8y2 Date: Mon, 28 Sep 2026 19:07:08 +0800 Subject: [PATCH] fix(data-grid): bound generated phones to column length Closes #10488 --- .../__tests__/dataGeneratePhone.spec.ts | 50 +++++++++++++++++++ apps/desktop/src/lib/dataGrid/dataGenerate.ts | 36 ++++++++++++- 2 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 apps/desktop/src/lib/dataGrid/__tests__/dataGeneratePhone.spec.ts diff --git a/apps/desktop/src/lib/dataGrid/__tests__/dataGeneratePhone.spec.ts b/apps/desktop/src/lib/dataGrid/__tests__/dataGeneratePhone.spec.ts new file mode 100644 index 0000000000..ed5d957617 --- /dev/null +++ b/apps/desktop/src/lib/dataGrid/__tests__/dataGeneratePhone.spec.ts @@ -0,0 +1,50 @@ +import { describe, expect, it } from "vitest"; +import { defaultGeneratorParams, generateValue, type ColumnAttrs } from "@/lib/dataGrid/dataGenerate"; + +function phoneParams(characterMaximumLength: number) { + const attrs: ColumnAttrs = { + dataType: `varchar(${characterMaximumLength})`, + columnDefault: null, + characterMaximumLength, + }; + return defaultGeneratorParams("mobile", attrs, "phone"); +} + +describe("phone data generation (#10488)", () => { + it("keeps automatically generated mobile values within varchar(11)", () => { + const params = phoneParams(11); + + expect(params.maxLength).toBe(11); + for (let row = 0; row < 50; row += 1) { + const value = generateValue("mobile", "varchar(11)", "phone", row, params); + expect(value).toEqual(expect.any(String)); + expect((value as string).length).toBeLessThanOrEqual(11); + } + }); + + it("bounds phone values for columns shorter than a standard phone number", () => { + const params = phoneParams(6); + const value = generateValue("mobile", "varchar(6)", "phone", 0, params); + + expect(value).toMatch(/^\d{6}$/); + }); + + it("preserves configured region and formatting when the column is large enough", () => { + const value = generateValue("mobile", "varchar(32)", "phone", 0, { + phoneFormat: "international", + phoneSeparator: true, + phoneRegions: ["cn"], + maxLength: 32, + }); + + expect(value).toMatch(/^\+86\d{11}$/); + }); + + it("keeps text generator length defaults unchanged", () => { + const attrs: ColumnAttrs = { dataType: "varchar(11)", columnDefault: null, characterMaximumLength: 11 }; + const params = defaultGeneratorParams("note", attrs, "text"); + + expect(params).toMatchObject({ minLength: 6, maxLength: 11 }); + expect((generateValue("note", "varchar(11)", "text", 0, params) as string).length).toBeLessThanOrEqual(11); + }); +}); diff --git a/apps/desktop/src/lib/dataGrid/dataGenerate.ts b/apps/desktop/src/lib/dataGrid/dataGenerate.ts index bc3d56b1b7..c8ded34001 100644 --- a/apps/desktop/src/lib/dataGrid/dataGenerate.ts +++ b/apps/desktop/src/lib/dataGrid/dataGenerate.ts @@ -944,8 +944,39 @@ function transformText(text: string, mode: string): string { function generateEmail(): string { return `${pick(firstNames).toLowerCase()}.${pick(lastNames).toLowerCase()}@${pick(domains)}`; } -function generatePhone(): string { - return `+1${randInt(200, 999)}${randInt(100, 999)}${randInt(1000, 9999)}`; +function generatePhone(params?: GeneratorParams): string { + const regions = params?.phoneRegions?.length ? params.phoneRegions : ["us"]; + const region = pick(regions); + const separator = params?.phoneSeparator === true; + const format = params?.phoneFormat ?? "domestic"; + let phone: string; + + if (region === "uk") { + const first = randInt(1000, 9999); + const second = randInt(100000, 999999); + phone = separator ? `${first} ${second}` : `+44${first}${second}`; + } else if (region === "jp") { + const first = randInt(10, 99); + const second = randInt(1000, 9999); + const third = randInt(1000, 9999); + phone = separator ? `0${first}-${second}-${third}` : `+810${first}${second}${third}`; + } else if (region === "cn" || region === "other") { + const first = randInt(130, 199); + const second = randInt(1000, 9999); + const third = randInt(1000, 9999); + const domestic = separator ? `${first}-${second}-${third}` : `${first}${second}${third}`; + phone = format === "international" ? `+86${domestic.replace(/[^0-9]/g, "")}` : domestic; + } else { + const first = randInt(200, 999); + const second = randInt(100, 999); + const third = randInt(1000, 9999); + phone = separator ? `(${first}) ${second}-${third}` : `+1${first}${second}${third}`; + } + + const maxLength = params?.maxLength; + if (maxLength === undefined || !Number.isFinite(maxLength) || maxLength < 1 || phone.length <= maxLength) return phone; + const digits = phone.replace(/\D/g, ""); + return digits.length <= maxLength ? digits : digits.slice(-Math.floor(maxLength)); } function generateIP(): string { return `${randInt(1, 255)}.${randInt(0, 255)}.${randInt(0, 255)}.${randInt(1, 255)}`; @@ -1455,6 +1486,7 @@ function buildDefaultGeneratorParams(_columnName: string, attrs: ColumnAttrs, ge params.phoneFormat = "domestic"; params.phoneSeparator = true; params.phoneRegions = ["us"]; + if (charLen !== null && charLen > 0) params.maxLength = Math.min(charLen, 2000); return params; } if (generatorKey === "email") {