Fix mockLocale for vitest 4.x spyOn breaking change (#5303)

This commit is contained in:
Quentin Gliech
2025-12-03 11:08:50 +01:00
committed by GitHub

View File

@@ -12,11 +12,31 @@ import { vi } from "vitest";
* Defaults to `en-GB`
*/
export const mockLocale = (defaultLocale = "en-GB"): void => {
const { DateTimeFormat } = Intl;
const OriginalDateTimeFormat = Intl.DateTimeFormat;
// Vitest 4.x requires function/class implementations for spyOn mocks when
// mocking constructors. For built-in constructors like Intl.DateTimeFormat
// that have internal slots, we use a function that returns a new instance.
// This is valid JavaScript - when a constructor returns an object, that
// object becomes the instance (instead of `this`).
function MockDateTimeFormat(
this: unknown,
locales?: Intl.LocalesArgument,
options?: Intl.DateTimeFormatOptions,
): Intl.DateTimeFormat {
// Apply default locale when no locale is specified
return new OriginalDateTimeFormat(locales || defaultLocale, options);
}
// Inherit static methods from the original DateTimeFormat
Object.setPrototypeOf(MockDateTimeFormat, OriginalDateTimeFormat);
// Set up prototype chain so instanceof checks work correctly
Object.setPrototypeOf(
MockDateTimeFormat.prototype,
OriginalDateTimeFormat.prototype,
);
vi.spyOn(Intl, "DateTimeFormat").mockImplementation(
(
locales?: Intl.LocalesArgument,
options?: Intl.DateTimeFormatOptions | undefined,
) => new DateTimeFormat(locales || defaultLocale, options),
MockDateTimeFormat as typeof Intl.DateTimeFormat,
);
};