UNPKG

cumulocity-cypress

Version:
317 lines (316 loc) 14.2 kB
// default locales to be registered automatically import localeDe from "@angular/common/locales/de"; import localeEn from "@angular/common/locales/en-GB"; import { normalizeLocaleId } from "../../shared/date"; import { getLastDefinedValue, shortestUniquePrefixes } from "../../shared/util"; import * as dateFnsDe from "date-fns/locale/de"; import * as dateFnsEnGB from "date-fns/locale/en-GB"; const { _ } = Cypress; // https://angular.io/api/common/DatePipe#pre-defined-format-options // https://github.com/angular/angular/blob/9847085448feff29ac6d51493e224250990c3ff0/packages/common/src/pipes/date_pipe.ts#L58 // not imported from @angular/common to avoid requiring jit at runtime export var FormatWidth; (function (FormatWidth) { FormatWidth[FormatWidth["Short"] = 0] = "Short"; FormatWidth[FormatWidth["Medium"] = 1] = "Medium"; FormatWidth[FormatWidth["Long"] = 2] = "Long"; FormatWidth[FormatWidth["Full"] = 3] = "Full"; })(FormatWidth || (FormatWidth = {})); export { localeDe, localeEn }; // Some i18n functions from Angular are used directly in here. This is required to not have Angular in a particular // version as a dependency of this package. locales must be imported in the tests with the version used in the project. // See as sources: // https://github.com/angular/angular/tree/6f5dabe0d25a5660b7c3001041449b4622dd8924/packages/core/src/i18n // https://github.com/angular/angular/tree/6f5dabe0d25a5660b7c3001041449b4622dd8924/packages/common/src/i18n // https://github.com/angular/angular/blob/6f5dabe0d25a5660b7c3001041449b4622dd8924/packages/common/src/i18n/locale_data_api.ts // https://github.com/angular/angular/blob/6f5dabe0d25a5660b7c3001041449b4622dd8924/packages/core/src/i18n/locale_data_api.ts export var NgLocaleDataIndex; (function (NgLocaleDataIndex) { NgLocaleDataIndex[NgLocaleDataIndex["LocaleId"] = 0] = "LocaleId"; NgLocaleDataIndex[NgLocaleDataIndex["DayPeriodsFormat"] = 1] = "DayPeriodsFormat"; NgLocaleDataIndex[NgLocaleDataIndex["DayPeriodsStandalone"] = 2] = "DayPeriodsStandalone"; NgLocaleDataIndex[NgLocaleDataIndex["DaysFormat"] = 3] = "DaysFormat"; NgLocaleDataIndex[NgLocaleDataIndex["DaysStandalone"] = 4] = "DaysStandalone"; NgLocaleDataIndex[NgLocaleDataIndex["MonthsFormat"] = 5] = "MonthsFormat"; NgLocaleDataIndex[NgLocaleDataIndex["MonthsStandalone"] = 6] = "MonthsStandalone"; NgLocaleDataIndex[NgLocaleDataIndex["Eras"] = 7] = "Eras"; NgLocaleDataIndex[NgLocaleDataIndex["FirstDayOfWeek"] = 8] = "FirstDayOfWeek"; NgLocaleDataIndex[NgLocaleDataIndex["WeekendRange"] = 9] = "WeekendRange"; NgLocaleDataIndex[NgLocaleDataIndex["DateFormat"] = 10] = "DateFormat"; NgLocaleDataIndex[NgLocaleDataIndex["TimeFormat"] = 11] = "TimeFormat"; NgLocaleDataIndex[NgLocaleDataIndex["DateTimeFormat"] = 12] = "DateTimeFormat"; NgLocaleDataIndex[NgLocaleDataIndex["NumberSymbols"] = 13] = "NumberSymbols"; NgLocaleDataIndex[NgLocaleDataIndex["NumberFormats"] = 14] = "NumberFormats"; NgLocaleDataIndex[NgLocaleDataIndex["CurrencyCode"] = 15] = "CurrencyCode"; NgLocaleDataIndex[NgLocaleDataIndex["CurrencySymbol"] = 16] = "CurrencySymbol"; NgLocaleDataIndex[NgLocaleDataIndex["CurrencyName"] = 17] = "CurrencyName"; NgLocaleDataIndex[NgLocaleDataIndex["Currencies"] = 18] = "Currencies"; NgLocaleDataIndex[NgLocaleDataIndex["Directionality"] = 19] = "Directionality"; NgLocaleDataIndex[NgLocaleDataIndex["PluralCase"] = 20] = "PluralCase"; NgLocaleDataIndex[NgLocaleDataIndex["ExtraData"] = 21] = "ExtraData"; NgLocaleDataIndex[NgLocaleDataIndex["DfnsLocale"] = 22] = "DfnsLocale"; })(NgLocaleDataIndex || (NgLocaleDataIndex = {})); const LOCALE_DATA = {}; export function getNgLocaleId(locale) { const data = getNgLocale(locale); return data[NgLocaleDataIndex.LocaleId]; } /** * Registers a locale with the given ID and data. Registered locale can be used * with `cy.setLanguage` to set the locale for date formatting and other * locale-specific operations in `cy.toDate`, `cy.toISODate`, etc. * @param c8yLocaleId The Cumulocity locale ID (e.g., "en", "de"). * @param angularLocale The Angular locale data. * @param dfnsLocale The date-fns locale data (optional). * @param extraData Additional data to be stored in the locale (optional). */ export function registerLocale(c8yLocaleId, angularLocale, dfnsLocale = null, extraData = undefined) { const angularId = normalizeLocaleId(c8yLocaleId); LOCALE_DATA[angularId] = angularLocale; if (extraData) { LOCALE_DATA[angularId][NgLocaleDataIndex.ExtraData] = extraData; } LOCALE_DATA[angularId][NgLocaleDataIndex.DfnsLocale] = { ...(typeof dfnsLocale === 'object' && dfnsLocale !== null ? dfnsLocale : {}), localize: { ...dfnsLocale?.localize, month: buildLocalizeFn({ values: monthValuesForLocale(angularId), defaultWidth: "wide", }), day: buildLocalizeFn({ values: dayValuesForLocale(angularId), defaultWidth: "wide", }), }, // node_modules/date-fns/locale/en-US/_lib/match/index.js match: { ...dfnsLocale?.match, month: buildMatchFn({ matchPatterns: matchMonthPatterns(angularId), defaultMatchWidth: "wide", parsePatterns: parseMonthPatterns(angularId), defaultParseWidth: "any", }), day: buildMatchFn({ matchPatterns: matchDayPatterns(angularId), defaultMatchWidth: "wide", parsePatterns: parseDayPatterns(angularId), defaultParseWidth: "any", }), }, }; } /** * Registers default locales `de` and `en` with their respective * Angular and date-fns locales for use in tests. */ export function registerDefaultLocales() { registerLocale("de", // @ts-expect-error !isModule(localeDe) ? localeDe : localeDe.default, dateFnsDe.default || dateFnsDe); registerLocale("en", // @ts-expect-error !isModule(localeEn) ? localeEn : localeEn.default, dateFnsEnGB.default || dateFnsEnGB); } export function getNgLocale(localeId) { const getNgLocaleData = (localeId) => { const normalizedLocale = normalizeLocaleId(localeId); if (!(normalizedLocale in LOCALE_DATA)) { LOCALE_DATA[normalizedLocale] = // @ts-expect-error globalThis.ng?.common?.locales?.[normalizedLocale]; } return LOCALE_DATA[normalizedLocale]; }; const normalizedLocale = normalizeLocaleId(localeId); let match = getNgLocaleData(normalizedLocale); if (match) { return match; } // let's try to find a parent locale const parentLocale = normalizedLocale.split("-")[0]; match = getNgLocaleData(parentLocale); if (match) { return match; } throw new Error(`Missing locale data for the locale "${localeId}".`); } export function localizedTimeFormat(localeId = "en", formatWidth = FormatWidth.Short) { return getLocaleValue(localeId, NgLocaleDataIndex.TimeFormat, formatWidth); } export function localizedDateFormat(localeId = "en", formatWidth = FormatWidth.Short) { return getLocaleValue(localeId, NgLocaleDataIndex.DateFormat, formatWidth); } export function localizedDateTimeFormat(localeId = "en", formatWidth = FormatWidth.Short) { const fullTime = getLocaleValue(localeId, NgLocaleDataIndex.TimeFormat, formatWidth); const fullDate = getLocaleValue(localeId, NgLocaleDataIndex.DateFormat, formatWidth); return formatDateTime(getLocaleValue(localeId, NgLocaleDataIndex.DateTimeFormat, formatWidth), [fullTime, fullDate]); } // https://github.com/angular/angular/blob/fe691935091aaf7090864c8111a15f7cc7e53b6c/packages/common/src/i18n/format_date.ts#L201 function formatDateTime(str, opt_values) { if (opt_values) { str = str.replace(/\{([^}]+)}/g, function (match, key) { return opt_values != null && key in opt_values ? opt_values[key] : match; }); } return str; } function isModule(module) { return ( // @ts-expect-error module && _.isObject(module) && module.default && !_.isEmpty(module.default)); } function getLocaleValue(locale, index, width) { const data = getNgLocale(locale); const result = getLastDefinedValue(data[index], width); if (!result) { throw new Error(`Missing value for locale "${locale}" and width "${width}".`); } return result; } // var parseDayPatterns = { // narrow: [/^s/i, /^m/i, /^t/i, /^w/i, /^t/i, /^f/i, /^s/i], // any: [/^su/i, /^m/i, /^tu/i, /^w/i, /^th/i, /^f/i, /^sa/i] // }; function parseDayPatterns(locale) { const l = getNgLocale(locale); if (!l) return null; const dayData = l[NgLocaleDataIndex.DaysStandalone] ?? l[NgLocaleDataIndex.DaysFormat]; const result = { narrow: dayData[0].map((m) => new RegExp("^" + _.lowerCase(m).substring(0, 1), "i")), any: shortestUniquePrefixes(dayData[2]).map((m) => new RegExp("^" + _.lowerCase(m), "i")), }; return result; } // var matchDayPatterns = { // narrow: /^[smdmf]/i, // short: /^(so|mo|di|mi|do|fr|sa)/i, // abbreviated: /^(son?|mon?|die?|mit?|don?|fre?|sam?)\.?/i, // wide: /^(sonntag|montag|dienstag|mittwoch|donnerstag|freitag|samstag)/i // }; function matchDayPatterns(locale) { const l = getNgLocale(locale); if (!l) return null; const dayData = l[NgLocaleDataIndex.DaysStandalone] ?? l[NgLocaleDataIndex.DaysFormat]; const result = { narrow: new RegExp("^[" + _.uniq(dayData[0]).join("|") + "]", "i"), short: new RegExp("^(" + _.uniq(dayData[3]).join("|") + ")", "i"), abbreviated: new RegExp("^(" + dayData[1].join("|") + ")", "i"), wide: new RegExp("^(" + dayData[2].join("|") + ")", "i"), }; return result; } function parseMonthPatterns(locale) { const l = getNgLocale(locale); if (!l) return null; const monthData = l[NgLocaleDataIndex.MonthsStandalone] ?? l[NgLocaleDataIndex.MonthsFormat]; const result = { narrow: monthData[0].map((m) => new RegExp("^" + _.lowerCase(m).substring(0, 1), "i")), any: shortestUniquePrefixes(monthData[2]).map((m) => new RegExp("^" + _.lowerCase(m), "i")), }; return result; } function matchMonthPatterns(locale) { const l = getNgLocale(locale); if (!l) return null; const monthData = l[NgLocaleDataIndex.MonthsStandalone] ?? l[NgLocaleDataIndex.MonthsFormat]; const result = { narrow: new RegExp("^[" + _.uniq(monthData[0]).join("|") + "]", "i"), abbreviated: new RegExp("^(" + monthData[1].join("|") + ")", "i"), wide: new RegExp("^(" + monthData[2].join("|") + ")", "i"), }; return result; } function monthValuesForLocale(locale) { const l = getNgLocale(locale); if (!l) return null; const monthData = l[NgLocaleDataIndex.MonthsStandalone] ?? l[NgLocaleDataIndex.MonthsFormat]; const result = { narrow: monthData[0], abbreviated: monthData[1], wide: monthData[2], }; return result; } function dayValuesForLocale(locale) { const l = getNgLocale(locale); if (!l) return null; const monthData = l[NgLocaleDataIndex.DaysStandalone] ?? l[NgLocaleDataIndex.DaysFormat]; const result = { narrow: monthData[0], abbreviated: monthData[1], wide: monthData[2], }; return result; } // Copied from date-fns as data-fns does not allow importing from locale files // See https://github.com/date-fns/date-fns/issues/3686 function buildLocalizeFn(args) { return (value, options) => { const context = options?.context ? String(options.context) : "standalone"; let valuesArray; if (context === "formatting" && args.formattingValues) { const defaultWidth = args.defaultFormattingWidth || args.defaultWidth; const width = options?.width ? String(options.width) : defaultWidth; valuesArray = args.formattingValues[width] || args.formattingValues[defaultWidth]; } else { const defaultWidth = args.defaultWidth; const width = options?.width ? String(options.width) : args.defaultWidth; valuesArray = args.values[width] || args.values[defaultWidth]; } const index = args.argumentCallback ? args.argumentCallback(value) : value; return valuesArray[index]; }; } export function buildMatchFn(args) { return (string, options = {}) => { const width = options.width; const matchPattern = (width && args.matchPatterns[width]) || args.matchPatterns[args.defaultMatchWidth]; const matchResult = string.match(matchPattern); if (!matchResult) { return null; } const matchedString = matchResult[0]; const parsePatterns = (width && args.parsePatterns[width]) || args.parsePatterns[args.defaultParseWidth]; const key = Array.isArray(parsePatterns) ? findIndex(parsePatterns, (pattern) => pattern.test(matchedString)) : // [TODO] -- I challenge you to fix the type findKey(parsePatterns, (pattern) => pattern.test(matchedString)); let value; value = args.valueCallback ? args.valueCallback(key) : key; value = options.valueCallback ? // [TODO] -- I challenge you to fix the type options.valueCallback(value) : value; const rest = string.slice(matchedString.length); return { value, rest }; }; } function findKey(object, predicate) { for (const key in object) { if (Object.prototype.hasOwnProperty.call(object, key) && predicate(object[key])) { return key; } } return undefined; } function findIndex(array, predicate) { for (let key = 0; key < array.length; key++) { if (predicate(array[key])) { return key; } } return undefined; }