Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(date): Add Intl-Based Tests for Date Definitions to Ensure Completeness of Weekdays and Months #2912

Open
wants to merge 27 commits into
base: next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
3097485
test(date): create Intl based tests for date definitions
sossost May 18, 2024
4d3055f
test: create Intl based test for date definition
sossost May 18, 2024
fe8ce70
test : add condition filtering valid Itnl locales
sossost May 19, 2024
fa73f0a
chore : add generate:date command
sossost May 19, 2024
efb206f
feat: auto generate/update date files
sossost May 19, 2024
49f08f6
fix : Add condition that exception case 'vd'
sossost May 19, 2024
1e67eb6
Merge branch 'next' into test/create-Intl-based-tests-for-date-defini…
ST-DDT May 19, 2024
9a07a19
test : restore existing test and remove month, weekday test about cou…
sossost May 19, 2024
16f9994
Merge branch 'test/create-Intl-based-tests-for-date-definitions' of h…
sossost May 19, 2024
5005fcb
test : Refactoring to locale data instead of using a new Faker instance
sossost May 19, 2024
80ee22a
refactor : integrate function that update month, weekDay locale data …
sossost May 19, 2024
aff49d5
fix : rollback generate scripts
sossost May 19, 2024
7263f0d
docs : add comments to explain why 'dv' locale is excluded
sossost May 19, 2024
3488e11
refactor : refactor generate-locales.ts reflecting code review
ynnsuis May 20, 2024
cb80f8d
chore: review and reduce diff
ST-DDT May 20, 2024
8f92366
chore: generate files
ST-DDT May 20, 2024
2a84b19
fix: Replace underscores with dashes in Intl.DateTimeFormat locale
sossost May 23, 2024
9ccf7dc
feat: Skip generating locale date files if identical to parent
sossost May 23, 2024
c6ffe2a
Merge branch 'faker-js:next' into test/create-Intl-based-tests-for-da…
sossost May 24, 2024
7ab5dd2
refactor : Move invalidLocale function inside generateDateModule and …
sossost May 24, 2024
18d9975
Merge branch 'next' of https://github.com/sossost/faker into test/cre…
sossost May 24, 2024
08f49ef
Merge branch 'test/create-Intl-based-tests-for-date-definitions' of h…
sossost May 24, 2024
93f6dbb
Merge branch 'next' into test/create-Intl-based-tests-for-date-defini…
ST-DDT May 27, 2024
3e9d64e
Merge branch 'next' into pr/sossost/2912
ST-DDT Jun 18, 2024
a09f70d
chore: generate files only when needed
ST-DDT Jun 18, 2024
aeb62d6
chore: generate missing files
ST-DDT Jun 18, 2024
78c7183
fix: parentIntl detection
ST-DDT Jun 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,10 @@
"build:code": "tsup-node",
"build:types": "tsc --project tsconfig.build.json",
"build": "run-s build:clean build:code build:types",
"generate": "run-s generate:locales generate:api-docs",
"generate": "run-s generate:locales generate:api-docs generate:date",
"generate:api-docs": "tsx ./scripts/apidocs.ts",
"generate:locales": "tsx ./scripts/generate-locales.ts",
"generate:date": "tsx ./scripts/generate-date-for-locale.ts",
"docs:build": "run-s generate:api-docs docs:build:run",
"docs:build:run": "vitepress build docs",
"docs:build:ci": "run-s build docs:build",
Expand Down
216 changes: 216 additions & 0 deletions scripts/generate-date-for-locale.ts
ST-DDT marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
/* eslint-disable no-restricted-globals */

import { constants } from 'node:fs';
import {
access,
mkdir,
readFile,
readdir,
stat,
writeFile,
} from 'node:fs/promises';
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { formatTypescript } from './apidocs/utils/format';

// Constants
const pathRoot: string = resolve(dirname(fileURLToPath(import.meta.url)), '..');
const pathLocales: string = resolve(pathRoot, 'src', 'locales');

const scriptCommand = 'pnpm run generate:date';
const autoGeneratedCommentHeader = `/*
* This file is automatically generated.
* Run '${scriptCommand}' to update.
*/`;

// Function to check if a locale is valid
function isValidLocale(locale: string): boolean {
try {
new Intl.DateTimeFormat(locale);
return true;
} catch {
return false;
}
}

// Function to update weekday values for a given locale
async function updateWeekdaysForLocale(locale: string): Promise<void> {
if (locale === 'dv') return;
sossost marked this conversation as resolved.
Show resolved Hide resolved

const dateFolderPath: string = resolve(pathLocales, locale, 'date');
const weekdayPath: string = resolve(dateFolderPath, 'weekday.ts');

// Check if the weekday.ts file exists, if not create it
try {
await access(weekdayPath, constants.R_OK);
} catch {
console.log(`Creating weekday.ts file for locale ${locale}.`);
const defaultWeekdayContent = `export default { "wide": [], "abbr": [] };`;
await writeFile(weekdayPath, await formatTypescript(defaultWeekdayContent));
}

// Read the current weekday values
const fileContent: string = await readFile(weekdayPath, 'utf8');
ST-DDT marked this conversation as resolved.
Show resolved Hide resolved

// Remove 'export default ' and convert to object
const objectString: string = fileContent
.replace(/export\s+default\s+/, '')
.trim()
.replace(/;$/, '');
let storedWeekdays: { wide: string[]; abbr: string[] };
try {
storedWeekdays = eval(`(${objectString})`);
} catch (error) {
console.error(`Failed to parse JSON for locale ${locale}:`, error);
return;
}

// Generate correct weekday values
const validLocale: string = isValidLocale(locale) ? locale : 'en';
ST-DDT marked this conversation as resolved.
Show resolved Hide resolved
const wide: string[] = [];
const abbr: string[] = [];
for (let i = 0; i < 7; i++) {
const date: Date = new Date(1970, 0, i + 4); // 1970-01-04 is a Sunday
wide.push(
new Intl.DateTimeFormat(validLocale, { weekday: 'long' }).format(date)
ST-DDT marked this conversation as resolved.
Show resolved Hide resolved
);
abbr.push(
new Intl.DateTimeFormat(validLocale, { weekday: 'short' }).format(date)
);
}

// Update stored weekdays
storedWeekdays.wide = wide;
storedWeekdays.abbr = abbr;

// Write updated values back to the file
const updatedContent = `${autoGeneratedCommentHeader}
export default ${JSON.stringify(storedWeekdays, null, 2)};`;
ST-DDT marked this conversation as resolved.
Show resolved Hide resolved
await writeFile(weekdayPath, await formatTypescript(updatedContent));
}

// Function to update month values for a given locale
async function updateMonthForLocale(locale: string): Promise<void> {
if (locale === 'dv') return;
ST-DDT marked this conversation as resolved.
Show resolved Hide resolved

const dateFolderPath: string = resolve(pathLocales, locale, 'date');
const monthPath: string = resolve(dateFolderPath, 'month.ts');

// Check if the month.ts file exists, if not create it
try {
await access(monthPath, constants.R_OK);
} catch {
console.log(`Creating month.ts file for locale ${locale}.`);
const defaultMonthContent = `export default { "wide": [], "abbr": [] };`;
await writeFile(monthPath, await formatTypescript(defaultMonthContent));
}

// Read the current month values
const fileContent: string = await readFile(monthPath, 'utf8');

// Remove 'export default ' and convert to object
const objectString: string = fileContent
.replace(/export\s+default\s+/, '')
.trim()
.replace(/;$/, '');
let storedMonths: { wide: string[]; abbr: string[] };
try {
storedMonths = eval(`(${objectString})`);
} catch (error) {
console.error(`Failed to parse JSON for locale ${locale}:`, error);
return;
}

// Generate correct month values
const validLocale: string = isValidLocale(locale) ? locale : 'en';
const wide: string[] = [];
const abbr: string[] = [];
for (let i = 0; i < 12; i++) {
const date: Date = new Date(1970, i, 1);
wide.push(
new Intl.DateTimeFormat(validLocale, { month: 'long' }).format(date)
);
abbr.push(
new Intl.DateTimeFormat(validLocale, { month: 'short' }).format(date)
);
}

// Update stored months
storedMonths.wide = wide;
storedMonths.abbr = abbr;

// Write updated values back to the file
const updatedContent = `${autoGeneratedCommentHeader}
export default ${JSON.stringify(storedMonths, null, 2)};`;
await writeFile(monthPath, await formatTypescript(updatedContent));
}

// Function to create date folder and index.ts file if not exists
async function createDateFolderAndIndex(locale: string): Promise<void> {
ST-DDT marked this conversation as resolved.
Show resolved Hide resolved
const dateFolderPath: string = resolve(pathLocales, locale, 'date');
const dateIndexPath: string = resolve(dateFolderPath, 'index.ts');
const localeIndexPath: string = resolve(pathLocales, locale, 'index.ts');

// Check if the date folder exists, if not create it
try {
await access(dateFolderPath, constants.R_OK);
} catch {
console.log(`Creating date folder for locale ${locale}.`);
} finally {
await mkdir(dateFolderPath, { recursive: true });

// Create a new index.ts file for the date module
const dateIndexContent = `
${autoGeneratedCommentHeader}
import type { DateDefinition } from '../../..';
import month from './month';
import weekday from './weekday';

const date: DateDefinition = {
month,
weekday,
};

export default date;
`;
await writeFile(dateIndexPath, await formatTypescript(dateIndexContent));
}

// Update the locale index file to include date
let localeIndexContent: string = await readFile(localeIndexPath, 'utf8');
if (!localeIndexContent.includes("import date from './date';")) {
localeIndexContent = localeIndexContent.replace(
"import type { LocaleDefinition } from '../..';",
"import type { LocaleDefinition } from '../..';\nimport date from './date';"
);
localeIndexContent = localeIndexContent.replace(
/(const \w+: LocaleDefinition = {)/,
`$1\n date,`
);
await writeFile(
localeIndexPath,
await formatTypescript(localeIndexContent)
);
}
}

// Main function to update all locales
async function updateAllLocales(): Promise<void> {
const locales: string[] = await readdir(pathLocales);

for (const locale of locales) {
const localePath: string = resolve(pathLocales, locale);
const localeStat = await stat(localePath);

if (localeStat.isDirectory()) {
ST-DDT marked this conversation as resolved.
Show resolved Hide resolved
await createDateFolderAndIndex(locale);
await updateMonthForLocale(locale);
await updateWeekdaysForLocale(locale);
} else {
console.log(`Skipping ${locale} as it is not a directory.`);
}
}
}

// Run the script to update weekdays for all locales
await updateAllLocales();
Loading
Loading