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.
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, useDate.UTC
, por ej.new Date(Date.UTC(1995, 4, 23))
- 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, useDate::toISOString()
. Afortunadamente esto fue fácil en mi caso, ya que solo necesitaba burlarme de la funciónformatDate
en mi módulo de localización. Puede ser más difícil si el componente está de alguna manera convirtiendoDate
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 :)