From b6bb0c8855ab9598cdafd2b67e68ad7027789adf Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Wed, 6 Jan 2021 18:18:28 +0000 Subject: [PATCH] chore(NA): move elastic-datemath from mocha into jest (#87351) * chore(NA): move from mocha to jest * chore(NA): init changes on sinon replacement * chore(NA): continue to use sinon for timer mocks * docs(NA): explaining why we keep to use sinon on elastic datemath * chore(NA): remove sinon from elastic-datemath --- .../{__tests__/index.js => index.test.js} | 169 +++++++++--------- packages/elastic-datemath/jest.config.js | 25 +++ 2 files changed, 111 insertions(+), 83 deletions(-) rename packages/elastic-datemath/{__tests__/index.js => index.test.js} (69%) create mode 100644 packages/elastic-datemath/jest.config.js diff --git a/packages/elastic-datemath/__tests__/index.js b/packages/elastic-datemath/index.test.js similarity index 69% rename from packages/elastic-datemath/__tests__/index.js rename to packages/elastic-datemath/index.test.js index 1a61021b48a6e..a6a576dd713a9 100644 --- a/packages/elastic-datemath/__tests__/index.js +++ b/packages/elastic-datemath/index.test.js @@ -17,22 +17,21 @@ * under the License. */ -const dateMath = require('../index'); +const dateMath = require('./index'); const moment = require('moment'); -const sinon = require('sinon'); -const expect = require('@kbn/expect'); /** - * Require a new instance of the moment library, bypassing the require cache. + * Require a new instance of the moment library, bypassing the require cache + * by using jest.resetModules(). * This is needed, since we are trying to test whether or not this library works * when passing in a different configured moment instance. If we would change * the locales on the imported moment, it would automatically apply * to the source code, even without passing it in to the method, since they share * the same global state. This method avoids this, by loading a separate instance - * of moment, by deleting the require cache and require the library again. + * of moment, by resetting the jest require modules cache and require the library again. */ function momentClone() { - delete require.cache[require.resolve('moment')]; + jest.resetModules(); return require('moment'); } @@ -43,44 +42,43 @@ describe('dateMath', function () { const anchoredDate = new Date(Date.parse(anchor)); const unix = moment(anchor).valueOf(); const format = 'YYYY-MM-DDTHH:mm:ss.SSSZ'; - let clock; describe('errors', function () { it('should return undefined if passed something falsy', function () { - expect(dateMath.parse()).to.be(undefined); + expect(dateMath.parse()).toBeUndefined(); }); it('should return undefined if I pass an operator besides [+-/]', function () { - expect(dateMath.parse('now&1d')).to.be(undefined); + expect(dateMath.parse('now&1d')).toBeUndefined(); }); it('should return undefined if I pass a unit besides' + spans.toString(), function () { - expect(dateMath.parse('now+5f')).to.be(undefined); + expect(dateMath.parse('now+5f')).toBeUndefined(); }); it('should return undefined if rounding unit is not 1', function () { - expect(dateMath.parse('now/2y')).to.be(undefined); - expect(dateMath.parse('now/0.5y')).to.be(undefined); + expect(dateMath.parse('now/2y')).toBeUndefined(); + expect(dateMath.parse('now/0.5y')).toBeUndefined(); }); it('should not go into an infinite loop when missing a unit', function () { - expect(dateMath.parse('now-0')).to.be(undefined); - expect(dateMath.parse('now-00')).to.be(undefined); - expect(dateMath.parse('now-000')).to.be(undefined); + expect(dateMath.parse('now-0')).toBeUndefined(); + expect(dateMath.parse('now-00')).toBeUndefined(); + expect(dateMath.parse('now-000')).toBeUndefined(); }); describe('forceNow', function () { it('should throw an Error if passed a string', function () { const fn = () => dateMath.parse('now', { forceNow: '2000-01-01T00:00:00.000Z' }); - expect(fn).to.throwError(); + expect(fn).toThrowError(); }); it('should throw an Error if passed a moment', function () { - expect(() => dateMath.parse('now', { forceNow: moment() })).to.throwError(); + expect(() => dateMath.parse('now', { forceNow: moment() })).toThrowError(); }); it('should throw an Error if passed an invalid date', function () { - expect(() => dateMath.parse('now', { forceNow: new Date('foobar') })).to.throwError(); + expect(() => dateMath.parse('now', { forceNow: new Date('foobar') })).toThrowError(); }); }); }); @@ -92,7 +90,8 @@ describe('dateMath', function () { let now; beforeEach(function () { - clock = sinon.useFakeTimers(unix); + jest.useFakeTimers('modern'); + jest.setSystemTime(unix); now = moment(); mmnt = moment(anchor); date = mmnt.toDate(); @@ -100,27 +99,27 @@ describe('dateMath', function () { }); afterEach(function () { - clock.restore(); + jest.useRealTimers(); }); it('should return the same moment if passed a moment', function () { - expect(dateMath.parse(mmnt)).to.eql(mmnt); + expect(dateMath.parse(mmnt)).toEqual(mmnt); }); it('should return a moment if passed a date', function () { - expect(dateMath.parse(date).format(format)).to.eql(mmnt.format(format)); + expect(dateMath.parse(date).format(format)).toEqual(mmnt.format(format)); }); it('should return a moment if passed an ISO8601 string', function () { - expect(dateMath.parse(string).format(format)).to.eql(mmnt.format(format)); + expect(dateMath.parse(string).format(format)).toEqual(mmnt.format(format)); }); it('should return the current time when parsing now', function () { - expect(dateMath.parse('now').format(format)).to.eql(now.format(format)); + expect(dateMath.parse('now').format(format)).toEqual(now.format(format)); }); it('should use the forceNow parameter when parsing now', function () { - expect(dateMath.parse('now', { forceNow: anchoredDate }).valueOf()).to.eql(unix); + expect(dateMath.parse('now', { forceNow: anchoredDate }).valueOf()).toEqual(unix); }); }); @@ -129,13 +128,14 @@ describe('dateMath', function () { let anchored; beforeEach(function () { - clock = sinon.useFakeTimers(unix); + jest.useFakeTimers('modern'); + jest.setSystemTime(unix); now = moment(); anchored = moment(anchor); }); afterEach(function () { - clock.restore(); + jest.useRealTimers(); }); [5, 12, 247].forEach((len) => { @@ -145,17 +145,17 @@ describe('dateMath', function () { it('should return ' + len + span + ' ago', function () { const parsed = dateMath.parse(nowEx).format(format); - expect(parsed).to.eql(now.subtract(len, span).format(format)); + expect(parsed).toEqual(now.subtract(len, span).format(format)); }); it('should return ' + len + span + ' before ' + anchor, function () { const parsed = dateMath.parse(thenEx).format(format); - expect(parsed).to.eql(anchored.subtract(len, span).format(format)); + expect(parsed).toEqual(anchored.subtract(len, span).format(format)); }); it('should return ' + len + span + ' before forceNow', function () { const parsed = dateMath.parse(nowEx, { forceNow: anchoredDate }).valueOf(); - expect(parsed).to.eql(anchored.subtract(len, span).valueOf()); + expect(parsed).toEqual(anchored.subtract(len, span).valueOf()); }); }); }); @@ -166,13 +166,14 @@ describe('dateMath', function () { let anchored; beforeEach(function () { - clock = sinon.useFakeTimers(unix); + jest.useFakeTimers('modern'); + jest.setSystemTime(unix); now = moment(); anchored = moment(anchor); }); afterEach(function () { - clock.restore(); + jest.useRealTimers(); }); [5, 12, 247].forEach((len) => { @@ -181,17 +182,17 @@ describe('dateMath', function () { const thenEx = `${anchor}||+${len}${span}`; it('should return ' + len + span + ' from now', function () { - expect(dateMath.parse(nowEx).format(format)).to.eql(now.add(len, span).format(format)); + expect(dateMath.parse(nowEx).format(format)).toEqual(now.add(len, span).format(format)); }); it('should return ' + len + span + ' after ' + anchor, function () { - expect(dateMath.parse(thenEx).format(format)).to.eql( + expect(dateMath.parse(thenEx).format(format)).toEqual( anchored.add(len, span).format(format) ); }); it('should return ' + len + span + ' after forceNow', function () { - expect(dateMath.parse(nowEx, { forceNow: anchoredDate }).valueOf()).to.eql( + expect(dateMath.parse(nowEx, { forceNow: anchoredDate }).valueOf()).toEqual( anchored.add(len, span).valueOf() ); }); @@ -204,30 +205,31 @@ describe('dateMath', function () { let anchored; beforeEach(function () { - clock = sinon.useFakeTimers(unix); + jest.useFakeTimers('modern'); + jest.setSystemTime(unix); now = moment(); anchored = moment(anchor); }); afterEach(function () { - clock.restore(); + jest.useRealTimers(); }); spans.forEach((span) => { it(`should round now to the beginning of the ${span}`, function () { - expect(dateMath.parse('now/' + span).format(format)).to.eql( + expect(dateMath.parse('now/' + span).format(format)).toEqual( now.startOf(span).format(format) ); }); it(`should round now to the beginning of forceNow's ${span}`, function () { - expect(dateMath.parse('now/' + span, { forceNow: anchoredDate }).valueOf()).to.eql( + expect(dateMath.parse('now/' + span, { forceNow: anchoredDate }).valueOf()).toEqual( anchored.startOf(span).valueOf() ); }); it(`should round now to the end of the ${span}`, function () { - expect(dateMath.parse('now/' + span, { roundUp: true }).format(format)).to.eql( + expect(dateMath.parse('now/' + span, { roundUp: true }).format(format)).toEqual( now.endOf(span).format(format) ); }); @@ -235,7 +237,7 @@ describe('dateMath', function () { it(`should round now to the end of forceNow's ${span}`, function () { expect( dateMath.parse('now/' + span, { roundUp: true, forceNow: anchoredDate }).valueOf() - ).to.eql(anchored.endOf(span).valueOf()); + ).toEqual(anchored.endOf(span).valueOf()); }); }); }); @@ -245,38 +247,39 @@ describe('dateMath', function () { let anchored; beforeEach(function () { - clock = sinon.useFakeTimers(unix); + jest.useFakeTimers('modern'); + jest.setSystemTime(unix); now = moment(); anchored = moment(anchor); }); afterEach(function () { - clock.restore(); + jest.useRealTimers(); }); it('should round to the nearest second with 0 value', function () { const val = dateMath.parse('now-0s/s').format(format); - expect(val).to.eql(now.startOf('s').format(format)); + expect(val).toEqual(now.startOf('s').format(format)); }); it('should subtract 17s, rounded to the nearest second', function () { const val = dateMath.parse('now-17s/s').format(format); - expect(val).to.eql(now.startOf('s').subtract(17, 's').format(format)); + expect(val).toEqual(now.startOf('s').subtract(17, 's').format(format)); }); it('should add 555ms, rounded to the nearest millisecond', function () { const val = dateMath.parse('now+555ms/ms').format(format); - expect(val).to.eql(now.add(555, 'ms').startOf('ms').format(format)); + expect(val).toEqual(now.add(555, 'ms').startOf('ms').format(format)); }); it('should subtract 555ms, rounded to the nearest second', function () { const val = dateMath.parse('now-555ms/s').format(format); - expect(val).to.eql(now.subtract(555, 'ms').startOf('s').format(format)); + expect(val).toEqual(now.subtract(555, 'ms').startOf('s').format(format)); }); it('should round weeks to Sunday by default', function () { const val = dateMath.parse('now-1w/w'); - expect(val.isoWeekday()).to.eql(7); + expect(val.isoWeekday()).toEqual(7); }); it('should round weeks based on the passed moment locale start of week setting', function () { @@ -286,7 +289,7 @@ describe('dateMath', function () { week: { dow: 2 }, }); const val = dateMath.parse('now-1w/w', { momentInstance: m }); - expect(val.isoWeekday()).to.eql(2); + expect(val.isoWeekday()).toEqual(2); }); it('should round up weeks based on the passed moment locale start of week setting', function () { @@ -301,79 +304,79 @@ describe('dateMath', function () { }); // The end of the range (rounding up) should be the last day of the week (so one day before) // our start of the week, that's why 3 - 1 - expect(val.isoWeekday()).to.eql(3 - 1); + expect(val.isoWeekday()).toEqual(3 - 1); }); it('should round relative to forceNow', function () { const val = dateMath.parse('now-0s/s', { forceNow: anchoredDate }).valueOf(); - expect(val).to.eql(anchored.startOf('s').valueOf()); + expect(val).toEqual(anchored.startOf('s').valueOf()); }); it('should parse long expressions', () => { - expect(dateMath.parse('now-1d/d+8h+50m')).to.be.ok(); + expect(dateMath.parse('now-1d/d+8h+50m')).toBeTruthy(); }); }); describe('used momentjs instance', function () { it('should use the default moment instance if parameter not specified', function () { - const momentSpy = sinon.spy(moment, 'isMoment'); + const momentSpy = jest.spyOn(moment, 'isMoment'); dateMath.parse('now'); - expect(momentSpy.called).to.be(true); - momentSpy.restore(); + expect(momentSpy).toHaveBeenCalled(); + momentSpy.mockRestore(); }); it('should not use default moment instance if parameter is specified', function () { const m = momentClone(); - const momentSpy = sinon.spy(moment, 'isMoment'); - const cloneSpy = sinon.spy(m, 'isMoment'); + const momentSpy = jest.spyOn(moment, 'isMoment'); + const cloneSpy = jest.spyOn(m, 'isMoment'); dateMath.parse('now', { momentInstance: m }); - expect(momentSpy.called).to.be(false); - expect(cloneSpy.called).to.be(true); - momentSpy.restore(); - cloneSpy.restore(); + expect(momentSpy).not.toHaveBeenCalled(); + expect(cloneSpy).toHaveBeenCalled(); + momentSpy.mockRestore(); + cloneSpy.mockRestore(); }); it('should work with multiple different instances', function () { const m1 = momentClone(); const m2 = momentClone(); - const m1Spy = sinon.spy(m1, 'isMoment'); - const m2Spy = sinon.spy(m2, 'isMoment'); + const m1Spy = jest.spyOn(m1, 'isMoment'); + const m2Spy = jest.spyOn(m2, 'isMoment'); dateMath.parse('now', { momentInstance: m1 }); - expect(m1Spy.called).to.be(true); - expect(m2Spy.called).to.be(false); - m1Spy.resetHistory(); - m2Spy.resetHistory(); + expect(m1Spy).toHaveBeenCalled(); + expect(m2Spy).not.toHaveBeenCalled(); + m1Spy.mockClear(); + m2Spy.mockClear(); dateMath.parse('now', { momentInstance: m2 }); - expect(m1Spy.called).to.be(false); - expect(m2Spy.called).to.be(true); - m1Spy.restore(); - m2Spy.restore(); + expect(m1Spy).not.toHaveBeenCalled(); + expect(m2Spy).toHaveBeenCalled(); + m1Spy.mockRestore(); + m2Spy.mockRestore(); }); it('should use global instance after passing an instance', function () { const m = momentClone(); - const momentSpy = sinon.spy(moment, 'isMoment'); - const cloneSpy = sinon.spy(m, 'isMoment'); + const momentSpy = jest.spyOn(moment, 'isMoment'); + const cloneSpy = jest.spyOn(m, 'isMoment'); dateMath.parse('now', { momentInstance: m }); - expect(momentSpy.called).to.be(false); - expect(cloneSpy.called).to.be(true); - momentSpy.resetHistory(); - cloneSpy.resetHistory(); + expect(momentSpy).not.toHaveBeenCalled(); + expect(cloneSpy).toHaveBeenCalled(); + momentSpy.mockClear(); + cloneSpy.mockClear(); dateMath.parse('now'); - expect(momentSpy.called).to.be(true); - expect(cloneSpy.called).to.be(false); - momentSpy.restore(); - cloneSpy.restore(); + expect(momentSpy).toHaveBeenCalled(); + expect(cloneSpy).not.toHaveBeenCalled(); + momentSpy.mockRestore(); + cloneSpy.mockRestore(); }); }); describe('units', function () { it('should have units descending for unitsDesc', function () { - expect(dateMath.unitsDesc).to.eql(['y', 'M', 'w', 'd', 'h', 'm', 's', 'ms']); + expect(dateMath.unitsDesc).toEqual(['y', 'M', 'w', 'd', 'h', 'm', 's', 'ms']); }); it('should have units ascending for unitsAsc', function () { - expect(dateMath.unitsAsc).to.eql(['ms', 's', 'm', 'h', 'd', 'w', 'M', 'y']); + expect(dateMath.unitsAsc).toEqual(['ms', 's', 'm', 'h', 'd', 'w', 'M', 'y']); }); }); }); diff --git a/packages/elastic-datemath/jest.config.js b/packages/elastic-datemath/jest.config.js new file mode 100644 index 0000000000000..6a0bd891f1c58 --- /dev/null +++ b/packages/elastic-datemath/jest.config.js @@ -0,0 +1,25 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../..', + roots: ['/packages/elastic-datemath'], + testEnvironment: 'jsdom', +};