zona objeto manejo horaria fechas fecha establecer javascript reactjs jestjs enzyme

objeto - set timezone javascript



Los componentes que usan objetos Date producen diferentes instantáneas en diferentes zonas horarias (3)

Estoy usando Enzyme con enzyme-to-json para hacer una prueba instantánea Jest de mis componentes React. Estoy probando instantáneas superficiales de un componente DateRange que representa un campo de visualización con el rango actual (por ejemplo, 5/20/2016 - 7/18/2016 ) y dos componentes DateInput que permiten seleccionar un valor de Date . Esto significa que mi instantánea contiene la Date que paso al componente tanto en los accesorios de DateInput como en una representación de texto que se resuelve por sí misma. En mi prueba estoy creando algunas fechas fijas usando ambas fechas new Date(1995, 4, 23) .

Cuando ejecuto mi prueba en diferentes zonas horarias, esto produce instantáneas diferentes , porque el constructor Date(year, month, ...) crea la fecha en la zona horaria local. Por ejemplo, el uso de una new Date() produce esta diferencia en la instantánea entre las ejecuciones en mi zona horaria local y en nuestro servidor de CI.

- value={1995-05-22T22:00:00.000Z} + value={1995-05-23T00:00:00.000Z}

Intenté eliminar el desplazamiento de la zona horaria de las fechas, pero luego la instantánea difirió en el valor del campo de visualización, donde se usa la representación dependiente de la zona horaria local.

- value={5/20/2016 - 7/18/2016} + value={5/19/2016 - 7/17/2016}

¿Cómo puedo hacer que mis pruebas produzcan las mismas Date en instantáneas independientemente de la zona horaria en la que se ejecutan?


Terminé toLocaleString esto burlando el toLocaleString (o cualquier método toString que estés usando). Usando sinon hice:

var toLocaleString; beforeAll(() => { toLocaleString = sinon.stub(Date.prototype, ''toLocaleString'', () => ''fake time'') }) afterAll(() => { toLocaleString.restore() })

De esta manera, si está generando cadenas directamente desde un objeto Date , todavía está OK.


Luché con esto durante horas / días y solo esto funcionó para mí:

1) En tu prueba:

Date.now = jest.fn(() => new Date(Date.UTC(2017, 7, 9, 8)).valueOf())

2) Luego cambie la var. Env de TZ antes de ejecutar sus pruebas. Entonces el script en mi paquete.json:

"test": "TZ=America/New_York react-scripts test --env=jsdom",


Terminé con una solución compuesta de dos partes.

  1. Nunca cree objetos Date en las pruebas en forma dependiente de la zona horaria. Si no desea utilizar marcas de tiempo directamente para tener un código de prueba legible, use Date.UTC , por ej.

    new Date(Date.UTC(1995, 4, 23))

  2. Simula el formateador de fecha utilizado para convertir la Date s en valores de visualización, de modo que devuelva una representación independiente de la zona horaria, por ejemplo, use Date::toISOString() . Afortunadamente esto fue fácil en mi caso, ya que solo necesitaba burlarme de la función formatDate en mi módulo de localización. Puede ser más difícil si el componente está de alguna manera convirtiendo Date s en cadenas por sí mismo.

Antes de llegar a la solución anterior, intenté cambiar de alguna manera cómo se crean las instantáneas. Fue feo, porque enzyme-to-json guarda una copia local de toISOString() , así que tuve que usar _.cloneDeepWith y modificar todas las Date . No funcionó para mí de todos modos, porque mis pruebas también contenían casos de creación de Date partir de marcas de tiempo (el componente es bastante más complicado de lo que describí anteriormente) y las interacciones entre esas y las fechas que estaba creando en las pruebas explícitamente. Así que primero tuve que asegurarme de que todas las definiciones de fecha se referían a la misma zona horaria y seguí el resto.

Actualización (11/3/2017): Cuando revisé enzyme-to-json recientemente, no he podido encontrar el ahorro local de toISOString() , así que tal vez ya no sea un problema y podría ser burlado. No he podido encontrarlo en la historia tampoco, así que tal vez noté incorrectamente qué biblioteca lo hizo. Prueba a tu propio riesgo :)