Estoy usando moment.js para hacer la mayor parte de mi lógica de fechas en un archivo de ayuda para mis componentes de React, pero no he podido descifrar cómo simular una fecha en Jest a la sinon.useFakeTimers() .
Los documentos de Jest solo hablan sobre funciones de temporizador como setTimeout , setInterval , etc., pero no ayudan a establecer una fecha y luego verificar que mis funciones de fecha hagan lo que deben hacer.
Aquí hay algo de mi archivo JS:
var moment = require('moment'); var DateHelper = { DATE_FORMAT: 'MMMM D', API_DATE_FORMAT: 'YYYY-MM-DD', formatDate: function(date) { return date.format(this.DATE_FORMAT); }, isDateToday: function(date) { return this.formatDate(date) === this.formatDate(moment()); } }; module.exports = DateHelper;y esto es lo que configuré usando Jest:
jest.dontMock('../../../dashboard/calendar/date-helper') .dontMock('moment'); describe('DateHelper', function() { var DateHelper = require('../../../dashboard/calendar/date-helper'), moment = require('moment'), DATE_FORMAT = 'MMMM D'; describe('formatDate', function() { it('should return the date formatted as DATE_FORMAT', function() { var unformattedDate = moment('2014-05-12T00:00:00.000Z'), formattedDate = DateHelper.formatDate(unformattedDate); expect(formattedDate).toEqual('May 12'); }); }); describe('isDateToday', function() { it('should return true if the passed in date is today', function() { var today = moment(); expect(DateHelper.isDateToday(today)).toEqual(true); }); }); });Ahora estas pruebas pasan porque estoy usando moment y mis funciones usan moment pero parece un poco inestable y me gustaría establecer la fecha a una hora fija para las pruebas.
¿Alguna idea de cómo podría lograrse eso?
A partir de Jest 26, esto se puede lograr utilizando temporizadores falsos "modernos" sin necesidad de instalar módulos de terceros: https://jestjs.io/blog/2020/05/05/jest-26#new-fake-timers
jest .useFakeTimers() .setSystemTime(new Date('2020-01-01')); Si desea que los temporizadores falsos estén activos para todas las pruebas, puede establecer timers: 'modern' en su configuración: https://jestjs.io/docs/configuration#timers-string
EDITAR: a partir de Jest 27, los temporizadores falsos modernos son los predeterminados, por lo que puede eliminar el argumento para useFakeTimers .
Dado que momentjs usa Date internamente, puede sobrescribir la función Date.now para devolver siempre el mismo momento.
Date.now = jest.fn(() => 1487076708000) //14.02.2017o
Date.now = jest.fn(() => new Date(Date.UTC(2017, 1, 14)).valueOf())Para una solución rápida y sucia, use jest.spyOn para el tiempo de bloqueo:
let dateNowSpy; beforeAll(() => { // Lock Time dateNowSpy = jest.spyOn(Date, 'now').mockImplementation(() => 1487076708000); }); afterAll(() => { // Unlock Time dateNowSpy.mockRestore(); });ACTUALIZAR:
Para una solución más robusta, mire timekeeper :
import timekeeper from 'timekeeper'; beforeAll(() => { // Lock Time timekeeper.freeze(new Date('2014-01-01')); }); afterAll(() => { // Unlock Time timekeeper.reset(); });