diff --git a/package.json b/package.json index 9d6c8c1aeee60..aef906febaeeb 100644 --- a/package.json +++ b/package.json @@ -1762,7 +1762,7 @@ "@types/selenium-webdriver": "^4.1.28", "@types/semver": "^7.7.0", "@types/set-value": "^4.0.3", - "@types/sinon": "^7.0.13", + "@types/sinon": "^17.0.3", "@types/source-map-support": "^0.5.10", "@types/stats-lite": "^2.2.0", "@types/styled-components": "^5.1.0", @@ -1937,7 +1937,7 @@ "selenium-webdriver": "^4.33.0", "sharp": "0.32.6", "simple-git": "^3.27.0", - "sinon": "^7.4.2", + "sinon": "^19.0.2", "sort-package-json": "^3.2.1", "source-map": "^0.7.4", "storybook": "^8.6.3", diff --git a/x-pack/platform/plugins/shared/alerting/server/task_runner/task_runner_alerts_client.test.ts b/x-pack/platform/plugins/shared/alerting/server/task_runner/task_runner_alerts_client.test.ts index 13c974bd89c62..1722627f019e0 100644 --- a/x-pack/platform/plugins/shared/alerting/server/task_runner/task_runner_alerts_client.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/task_runner/task_runner_alerts_client.test.ts @@ -5,7 +5,6 @@ * 2.0. */ -import sinon from 'sinon'; import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; import type { RuleExecutorOptions, @@ -128,7 +127,6 @@ jest.mock('../lib/alerting_event_logger/alerting_event_logger'); jest.mock('../rules_client/lib/get_alert_from_raw'); const mockGetAlertFromRaw = getAlertFromRaw as jest.MockedFunction; -let fakeTimer: sinon.SinonFakeTimers; const logger: ReturnType = loggingSystemMock.createLogger(); const taskRunnerLogger = createTaskRunnerLogger({ logger, tags: ['1', 'test'] }); @@ -165,11 +163,12 @@ describe('Task Runner', () => { let mockedTaskInstance: ConcreteTaskInstance; beforeAll(() => { - fakeTimer = sinon.useFakeTimers(); + jest.useFakeTimers(); + jest.setSystemTime(new Date(DATE_1970)); mockedTaskInstance = mockTaskInstance(); }); - afterAll(() => fakeTimer.restore()); + afterAll(() => jest.useRealTimers()); const encryptedSavedObjectsClient = encryptedSavedObjectsMock.createClient(); const internalSavedObjectsRepository = savedObjectsRepositoryMock.create(); diff --git a/x-pack/platform/plugins/shared/task_manager/server/lib/create_managed_configuration.test.ts b/x-pack/platform/plugins/shared/task_manager/server/lib/create_managed_configuration.test.ts index 71caee2ae24e1..cfe493adf88fe 100644 --- a/x-pack/platform/plugins/shared/task_manager/server/lib/create_managed_configuration.test.ts +++ b/x-pack/platform/plugins/shared/task_manager/server/lib/create_managed_configuration.test.ts @@ -5,7 +5,6 @@ * 2.0. */ -import sinon from 'sinon'; import { Subject, startWith, distinctUntilChanged, BehaviorSubject, withLatestFrom } from 'rxjs'; import { SavedObjectsErrorHelpers } from '@kbn/core/server'; import { @@ -29,15 +28,17 @@ import { BulkUpdateError } from './bulk_update_error'; import { createRunningAveragedStat } from '../monitoring/task_run_calculators'; describe('createManagedConfiguration()', () => { - let clock: sinon.SinonFakeTimers; const logger = mockLogger(); + beforeAll(() => { + jest.useFakeTimers(); + }); + beforeEach(() => { jest.resetAllMocks(); - clock = sinon.useFakeTimers(); }); - afterEach(() => clock.restore()); + afterAll(() => jest.useRealTimers()); test('uses max_workers config as capacity if only max workers is defined', async () => { const capacity = calculateStartingCapacity( @@ -97,7 +98,7 @@ describe('createManagedConfiguration()', () => { errorCheck$.subscribe(errorSubscription); errors$.next(new Error('foo')); - clock.tick(ADJUST_THROUGHPUT_INTERVAL); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL); expect(errorSubscription).toHaveBeenCalledTimes(1); }); @@ -126,21 +127,14 @@ describe('createManagedConfiguration()', () => { return { subscription, errors$ }; } - beforeEach(() => { - jest.resetAllMocks(); - clock = sinon.useFakeTimers(); - }); - - afterEach(() => clock.restore()); - describe('default claim strategy', () => { test('should decrease configuration at the next interval when an error is emitted', async () => { const { subscription, errors$ } = setupScenario(10); errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b')); - clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1); expect(subscription).toHaveBeenCalledTimes(1); expect(subscription).toHaveBeenNthCalledWith(1, 10); - clock.tick(1); + jest.advanceTimersByTime(1); expect(subscription).toHaveBeenCalledTimes(2); expect(subscription).toHaveBeenNthCalledWith(2, 8); }); @@ -148,10 +142,10 @@ describe('createManagedConfiguration()', () => { test('should decrease configuration at the next interval when a 500 error is emitted', async () => { const { subscription, errors$ } = setupScenario(10); errors$.next(SavedObjectsErrorHelpers.decorateGeneralError(new Error('a'), 'b')); - clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1); expect(subscription).toHaveBeenCalledTimes(1); expect(subscription).toHaveBeenNthCalledWith(1, 10); - clock.tick(1); + jest.advanceTimersByTime(1); expect(subscription).toHaveBeenCalledTimes(2); expect(subscription).toHaveBeenNthCalledWith(2, 8); }); @@ -159,10 +153,10 @@ describe('createManagedConfiguration()', () => { test('should decrease configuration at the next interval when a 503 error is emitted', async () => { const { subscription, errors$ } = setupScenario(10); errors$.next(SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError('a', 'b')); - clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1); expect(subscription).toHaveBeenCalledTimes(1); expect(subscription).toHaveBeenNthCalledWith(1, 10); - clock.tick(1); + jest.advanceTimersByTime(1); expect(subscription).toHaveBeenCalledTimes(2); expect(subscription).toHaveBeenNthCalledWith(2, 8); }); @@ -170,7 +164,7 @@ describe('createManagedConfiguration()', () => { test('should log a warning when the configuration changes from the starting value', async () => { const { errors$ } = setupScenario(10); errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b')); - clock.tick(ADJUST_THROUGHPUT_INTERVAL); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL); expect(logger.warn).toHaveBeenCalledWith( 'Capacity configuration is temporarily reduced after Elasticsearch returned 1 "too many request" and/or "execute [inline] script" error(s).' ); @@ -179,7 +173,7 @@ describe('createManagedConfiguration()', () => { test('should increase configuration back to normal incrementally after an error is emitted', async () => { const { subscription, errors$ } = setupScenario(10); errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b')); - clock.tick(ADJUST_THROUGHPUT_INTERVAL * 10); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL * 10); expect(subscription).toHaveBeenNthCalledWith(1, 10); expect(subscription).toHaveBeenNthCalledWith(2, 8); expect(subscription).toHaveBeenNthCalledWith(3, 9); @@ -192,7 +186,7 @@ describe('createManagedConfiguration()', () => { const { subscription, errors$ } = setupScenario(10); for (let i = 0; i < 20; i++) { errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b')); - clock.tick(ADJUST_THROUGHPUT_INTERVAL); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL); } expect(subscription).toHaveBeenNthCalledWith(1, 10); expect(subscription).toHaveBeenNthCalledWith(2, 8); @@ -210,10 +204,10 @@ describe('createManagedConfiguration()', () => { test('should not decrease configuration at the next interval when an error without status code is emitted', async () => { const { subscription, errors$ } = setupScenario(10); errors$.next(new Error()); - clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1); expect(subscription).toHaveBeenCalledTimes(1); expect(subscription).toHaveBeenNthCalledWith(1, 10); - clock.tick(1); + jest.advanceTimersByTime(1); expect(subscription).toHaveBeenCalledTimes(1); expect(subscription).toHaveBeenNthCalledWith(1, 10); }); @@ -221,10 +215,10 @@ describe('createManagedConfiguration()', () => { test('should decrease configuration at the next interval when an msearch 429 error is emitted', async () => { const { subscription, errors$ } = setupScenario(10); errors$.next(new MsearchError(429)); - clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1); expect(subscription).toHaveBeenCalledTimes(1); expect(subscription).toHaveBeenNthCalledWith(1, 10); - clock.tick(1); + jest.advanceTimersByTime(1); expect(subscription).toHaveBeenCalledTimes(2); expect(subscription).toHaveBeenNthCalledWith(2, 8); }); @@ -232,10 +226,10 @@ describe('createManagedConfiguration()', () => { test('should decrease configuration at the next interval when an msearch 500 error is emitted', async () => { const { subscription, errors$ } = setupScenario(10); errors$.next(new MsearchError(500)); - clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1); expect(subscription).toHaveBeenCalledTimes(1); expect(subscription).toHaveBeenNthCalledWith(1, 10); - clock.tick(1); + jest.advanceTimersByTime(1); expect(subscription).toHaveBeenCalledTimes(2); expect(subscription).toHaveBeenNthCalledWith(2, 8); }); @@ -243,10 +237,10 @@ describe('createManagedConfiguration()', () => { test('should decrease configuration at the next interval when an msearch 503 error is emitted', async () => { const { subscription, errors$ } = setupScenario(10); errors$.next(new MsearchError(503)); - clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1); expect(subscription).toHaveBeenCalledTimes(1); expect(subscription).toHaveBeenNthCalledWith(1, 10); - clock.tick(1); + jest.advanceTimersByTime(1); expect(subscription).toHaveBeenCalledTimes(2); expect(subscription).toHaveBeenNthCalledWith(2, 8); }); @@ -256,10 +250,10 @@ describe('createManagedConfiguration()', () => { errors$.next( new BulkUpdateError({ statusCode: 429, message: 'test', type: 'too_many_requests' }) ); - clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1); expect(subscription).toHaveBeenCalledTimes(1); expect(subscription).toHaveBeenNthCalledWith(1, 10); - clock.tick(1); + jest.advanceTimersByTime(1); expect(subscription).toHaveBeenCalledTimes(2); expect(subscription).toHaveBeenNthCalledWith(2, 8); }); @@ -269,10 +263,10 @@ describe('createManagedConfiguration()', () => { errors$.next( new BulkUpdateError({ statusCode: 500, message: 'test', type: 'server_error' }) ); - clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1); expect(subscription).toHaveBeenCalledTimes(1); expect(subscription).toHaveBeenNthCalledWith(1, 10); - clock.tick(1); + jest.advanceTimersByTime(1); expect(subscription).toHaveBeenCalledTimes(2); expect(subscription).toHaveBeenNthCalledWith(2, 8); }); @@ -280,10 +274,10 @@ describe('createManagedConfiguration()', () => { test('should decrease configuration at the next interval when an msearch 502 error is emitted', async () => { const { subscription, errors$ } = setupScenario(10); errors$.next(new MsearchError(502)); - clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1); expect(subscription).toHaveBeenCalledTimes(1); expect(subscription).toHaveBeenNthCalledWith(1, 10); - clock.tick(1); + jest.advanceTimersByTime(1); expect(subscription).toHaveBeenCalledTimes(2); expect(subscription).toHaveBeenNthCalledWith(2, 8); }); @@ -293,10 +287,10 @@ describe('createManagedConfiguration()', () => { errors$.next( new BulkUpdateError({ statusCode: 503, message: 'test', type: 'unavailable' }) ); - clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1); expect(subscription).toHaveBeenCalledTimes(1); expect(subscription).toHaveBeenNthCalledWith(1, 10); - clock.tick(1); + jest.advanceTimersByTime(1); expect(subscription).toHaveBeenCalledTimes(2); expect(subscription).toHaveBeenNthCalledWith(2, 8); }); @@ -304,10 +298,10 @@ describe('createManagedConfiguration()', () => { test('should decrease configuration at the next interval when an msearch 504 error is emitted', async () => { const { subscription, errors$ } = setupScenario(10); errors$.next(new MsearchError(504)); - clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1); expect(subscription).toHaveBeenCalledTimes(1); expect(subscription).toHaveBeenNthCalledWith(1, 10); - clock.tick(1); + jest.advanceTimersByTime(1); expect(subscription).toHaveBeenCalledTimes(2); expect(subscription).toHaveBeenNthCalledWith(2, 8); }); @@ -315,17 +309,17 @@ describe('createManagedConfiguration()', () => { test('should not change configuration at the next interval when other msearch error is emitted', async () => { const { subscription, errors$ } = setupScenario(10); errors$.next(new MsearchError(404)); - clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1); expect(subscription).toHaveBeenCalledTimes(1); expect(subscription).toHaveBeenNthCalledWith(1, 10); - clock.tick(1); + jest.advanceTimersByTime(1); expect(subscription).toHaveBeenCalledTimes(1); }); test('should log a warning when the configuration changes from the starting value', async () => { const { errors$ } = setupScenario(10, CLAIM_STRATEGY_MGET); errors$.next(new MsearchError(429)); - clock.tick(ADJUST_THROUGHPUT_INTERVAL); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL); expect(logger.warn).toHaveBeenCalledWith( 'Capacity configuration is temporarily reduced after Elasticsearch returned 1 "too many request" and/or "execute [inline] script" error(s).' ); @@ -334,7 +328,7 @@ describe('createManagedConfiguration()', () => { test('should increase configuration back to normal incrementally after an error is emitted', async () => { const { subscription, errors$ } = setupScenario(10, CLAIM_STRATEGY_MGET); errors$.next(new MsearchError(429)); - clock.tick(ADJUST_THROUGHPUT_INTERVAL * 10); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL * 10); expect(subscription).toHaveBeenNthCalledWith(1, 10); expect(subscription).toHaveBeenNthCalledWith(2, 8); expect(subscription).toHaveBeenNthCalledWith(3, 9); @@ -347,7 +341,7 @@ describe('createManagedConfiguration()', () => { const { subscription, errors$ } = setupScenario(10, CLAIM_STRATEGY_MGET); for (let i = 0; i < 20; i++) { errors$.next(new MsearchError(429)); - clock.tick(ADJUST_THROUGHPUT_INTERVAL); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL); } expect(subscription).toHaveBeenNthCalledWith(1, 10); expect(subscription).toHaveBeenNthCalledWith(2, 8); @@ -379,20 +373,13 @@ describe('createManagedConfiguration()', () => { return { subscription, errors$, utilization$ }; } - beforeEach(() => { - jest.resetAllMocks(); - clock = sinon.useFakeTimers(); - }); - - afterEach(() => clock.restore()); - describe('default claim strategy', () => { test('should increase configuration at the next interval when an error is emitted', async () => { const { subscription, errors$ } = setupScenario(100); errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b')); - clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1); expect(subscription).toHaveBeenCalledTimes(1); - clock.tick(1); + jest.advanceTimersByTime(1); expect(subscription).toHaveBeenCalledTimes(2); expect(subscription).toHaveBeenNthCalledWith(2, 120); }); @@ -400,9 +387,9 @@ describe('createManagedConfiguration()', () => { test('should increase configuration at the next interval when a 500 error is emitted', async () => { const { subscription, errors$ } = setupScenario(100); errors$.next(SavedObjectsErrorHelpers.decorateGeneralError(new Error('a'), 'b')); - clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1); expect(subscription).toHaveBeenCalledTimes(1); - clock.tick(1); + jest.advanceTimersByTime(1); expect(subscription).toHaveBeenCalledTimes(2); expect(subscription).toHaveBeenNthCalledWith(2, 120); }); @@ -410,9 +397,9 @@ describe('createManagedConfiguration()', () => { test('should increase configuration at the next interval when a 503 error is emitted', async () => { const { subscription, errors$ } = setupScenario(100); errors$.next(SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError('a', 'b')); - clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1); expect(subscription).toHaveBeenCalledTimes(1); - clock.tick(1); + jest.advanceTimersByTime(1); expect(subscription).toHaveBeenCalledTimes(2); expect(subscription).toHaveBeenNthCalledWith(2, 120); }); @@ -429,7 +416,7 @@ describe('createManagedConfiguration()', () => { expect(subscription).toHaveBeenNthCalledWith(1, 100); // It emits the error with cluster_block_exception type immediately expect(subscription).toHaveBeenNthCalledWith(2, INTERVAL_AFTER_BLOCK_EXCEPTION); - clock.tick(INTERVAL_AFTER_BLOCK_EXCEPTION); + jest.advanceTimersByTime(INTERVAL_AFTER_BLOCK_EXCEPTION); expect(subscription).toHaveBeenCalledTimes(3); expect(subscription).toHaveBeenNthCalledWith(3, 100); }); @@ -437,7 +424,7 @@ describe('createManagedConfiguration()', () => { test('should log a warning when the configuration changes from the starting value', async () => { const { errors$ } = setupScenario(100); errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b')); - clock.tick(ADJUST_THROUGHPUT_INTERVAL); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL); expect(logger.warn).toHaveBeenCalledWith( 'Poll interval configuration changing from 100 to 120 after seeing 1 "too many request" and/or "execute [inline] script" error(s) and/or "cluster_block_exception" error(s).' ); @@ -446,7 +433,7 @@ describe('createManagedConfiguration()', () => { test('should log a warning when an issue occurred in the calculating of the increased poll interval', async () => { const { errors$ } = setupScenario(NaN); errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b')); - clock.tick(ADJUST_THROUGHPUT_INTERVAL); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL); expect(logger.error).toHaveBeenCalledWith( 'Poll interval configuration had an issue calculating the new poll interval: Math.min(Math.ceil(NaN * 1.2), Math.max(60000, NaN)) = NaN, will keep the poll interval unchanged (NaN)' ); @@ -454,7 +441,7 @@ describe('createManagedConfiguration()', () => { test('should log a warning when an issue occurred in the calculating of the decreased poll interval', async () => { setupScenario(NaN); - clock.tick(ADJUST_THROUGHPUT_INTERVAL); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL); expect(logger.error).toHaveBeenCalledWith( 'Poll interval configuration had an issue calculating the new poll interval: Math.max(NaN, Math.floor(NaN * 0.95)) = NaN, will keep the poll interval unchanged (NaN)' ); @@ -463,7 +450,7 @@ describe('createManagedConfiguration()', () => { test('should decrease configuration back to normal incrementally after an error is emitted', async () => { const { subscription, errors$ } = setupScenario(100); errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b')); - clock.tick(ADJUST_THROUGHPUT_INTERVAL * 10); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL * 10); expect(subscription).toHaveBeenNthCalledWith(2, 120); expect(subscription).toHaveBeenNthCalledWith(3, 114); // 108.3 -> 108 from Math.floor @@ -479,7 +466,7 @@ describe('createManagedConfiguration()', () => { const { subscription, errors$ } = setupScenario(100); for (let i = 0; i < 3; i++) { errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b')); - clock.tick(ADJUST_THROUGHPUT_INTERVAL); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL); } expect(subscription).toHaveBeenNthCalledWith(2, 120); expect(subscription).toHaveBeenNthCalledWith(3, 144); @@ -491,7 +478,7 @@ describe('createManagedConfiguration()', () => { const { subscription, errors$ } = setupScenario(3000); for (let i = 0; i < 18; i++) { errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b')); - clock.tick(ADJUST_THROUGHPUT_INTERVAL); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL); } expect(subscription).toHaveBeenNthCalledWith(2, 3600); expect(subscription).toHaveBeenNthCalledWith(3, 4320); @@ -516,7 +503,7 @@ describe('createManagedConfiguration()', () => { const { subscription, errors$ } = setupScenario(65000); for (let i = 0; i < 5; i++) { errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b')); - clock.tick(ADJUST_THROUGHPUT_INTERVAL); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL); } expect(subscription).toHaveBeenCalledTimes(1); expect(subscription).toHaveBeenNthCalledWith(1, 65000); @@ -527,9 +514,9 @@ describe('createManagedConfiguration()', () => { test('should increase configuration at the next interval when an error is emitted', async () => { const { subscription, errors$ } = setupScenario(100, CLAIM_STRATEGY_MGET); errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b')); - clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1); expect(subscription).toHaveBeenCalledTimes(1); - clock.tick(1); + jest.advanceTimersByTime(1); expect(subscription).toHaveBeenCalledTimes(2); expect(subscription).toHaveBeenNthCalledWith(2, 120); }); @@ -537,7 +524,7 @@ describe('createManagedConfiguration()', () => { test('should log a warning when the configuration changes from the starting value', async () => { const { errors$ } = setupScenario(100, CLAIM_STRATEGY_MGET); errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b')); - clock.tick(ADJUST_THROUGHPUT_INTERVAL); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL); expect(logger.warn).toHaveBeenCalledWith( 'Poll interval configuration changing from 100 to 120 after seeing 1 "too many request" and/or "execute [inline] script" error(s) and/or "cluster_block_exception" error(s).' ); @@ -546,7 +533,7 @@ describe('createManagedConfiguration()', () => { test('should decrease configuration back to normal incrementally after an error is emitted', async () => { const { subscription, errors$ } = setupScenario(DEFAULT_POLL_INTERVAL, CLAIM_STRATEGY_MGET); errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b')); - clock.tick(ADJUST_THROUGHPUT_INTERVAL * 10); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL * 10); expect(subscription).toHaveBeenNthCalledWith(2, 3600); expect(subscription).toHaveBeenNthCalledWith(3, 3420); expect(subscription).toHaveBeenNthCalledWith(4, 3249); @@ -559,7 +546,7 @@ describe('createManagedConfiguration()', () => { test('should decrease configuration after error and reset to initial poll interval when poll interval < default and TM utilization > 25%', async () => { const { subscription, errors$ } = setupScenario(2800, CLAIM_STRATEGY_MGET); errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b')); - clock.tick(ADJUST_THROUGHPUT_INTERVAL * 10); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL * 10); expect(subscription).toHaveBeenNthCalledWith(2, 3360); expect(subscription).toHaveBeenNthCalledWith(3, 3192); expect(subscription).toHaveBeenNthCalledWith(4, 3032); @@ -573,7 +560,7 @@ describe('createManagedConfiguration()', () => { errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b')); for (let i = 0; i < 10; i++) { utilization$.next(20); - clock.tick(ADJUST_THROUGHPUT_INTERVAL); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL); } expect(subscription).toHaveBeenNthCalledWith(2, 3360); expect(subscription).toHaveBeenNthCalledWith(3, 3192); @@ -588,7 +575,7 @@ describe('createManagedConfiguration()', () => { const u = [15, 35, 5, 48, 0]; for (let i = 0; i < u.length; i++) { utilization$.next(u[i]); - clock.tick(ADJUST_THROUGHPUT_INTERVAL); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL); } expect(subscription).toHaveBeenNthCalledWith(2, 3000); expect(subscription).toHaveBeenNthCalledWith(3, 500); @@ -601,7 +588,7 @@ describe('createManagedConfiguration()', () => { test('should log a warning when the configuration changes from the starting value based on TM utilization', async () => { const { utilization$ } = setupScenario(100, CLAIM_STRATEGY_MGET); utilization$.next(20); - clock.tick(ADJUST_THROUGHPUT_INTERVAL); + jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL); expect(logger.debug).toHaveBeenCalledWith( 'Poll interval configuration changing from 100 to 3000 after a change in the average task load: 20.' ); diff --git a/x-pack/platform/plugins/shared/task_manager/server/task_claimers/strategy_mget.test.ts b/x-pack/platform/plugins/shared/task_manager/server/task_claimers/strategy_mget.test.ts index 288789e2d7f67..8f732c29bb433 100644 --- a/x-pack/platform/plugins/shared/task_manager/server/task_claimers/strategy_mget.test.ts +++ b/x-pack/platform/plugins/shared/task_manager/server/task_claimers/strategy_mget.test.ts @@ -6,7 +6,6 @@ */ import _ from 'lodash'; -import sinon from 'sinon'; import { v4 as uuidv4 } from 'uuid'; import { filter, take } from 'rxjs'; @@ -53,7 +52,6 @@ jest.mock('../constants', () => ({ ], })); -let fakeTimer: sinon.SinonFakeTimers; const taskManagerLogger = mockLogger(); beforeEach(() => jest.clearAllMocks()); @@ -121,10 +119,11 @@ const taskPartitioner = new TaskPartitioner({ // needs more tests in the similar to the `strategy_default.test.ts` test suite describe('TaskClaiming', () => { beforeAll(() => { - fakeTimer = sinon.useFakeTimers(); + jest.useFakeTimers(); + jest.setSystemTime(new Date('1970-01-01T00:00:00.000Z')); }); - afterAll(() => fakeTimer.restore()); + afterAll(() => jest.useRealTimers()); beforeEach(() => { jest.clearAllMocks(); @@ -2228,7 +2227,7 @@ describe('TaskClaiming', () => { test(`it should log warning on interval when the node has no assigned partitions`, async () => { // Reset the warning timer by advancing more - fakeTimer.tick(NO_ASSIGNED_PARTITIONS_WARNING_INTERVAL); + jest.advanceTimersByTime(NO_ASSIGNED_PARTITIONS_WARNING_INTERVAL); jest.spyOn(taskPartitioner, 'getPartitions').mockResolvedValue([]); const taskManagerId = uuidv4(); @@ -2260,7 +2259,7 @@ describe('TaskClaiming', () => { ); taskManagerLogger.warn.mockReset(); - fakeTimer.tick(NO_ASSIGNED_PARTITIONS_WARNING_INTERVAL - 500); + jest.advanceTimersByTime(NO_ASSIGNED_PARTITIONS_WARNING_INTERVAL - 500); await testClaimAvailableTasks({ storeOpts: { @@ -2275,7 +2274,7 @@ describe('TaskClaiming', () => { expect(taskManagerLogger.warn).not.toHaveBeenCalled(); - fakeTimer.tick(500); + jest.advanceTimersByTime(500); await testClaimAvailableTasks({ storeOpts: { @@ -2296,7 +2295,7 @@ describe('TaskClaiming', () => { test(`it should log a message after the node no longer has no assigned partitions`, async () => { // Reset the warning timer by advancing more - fakeTimer.tick(NO_ASSIGNED_PARTITIONS_WARNING_INTERVAL); + jest.advanceTimersByTime(NO_ASSIGNED_PARTITIONS_WARNING_INTERVAL); jest.spyOn(taskPartitioner, 'getPartitions').mockResolvedValue([]); const taskManagerId = uuidv4(); @@ -2329,7 +2328,7 @@ describe('TaskClaiming', () => { taskManagerLogger.warn.mockReset(); jest.spyOn(taskPartitioner, 'getPartitions').mockResolvedValue([1, 2, 3]); - fakeTimer.tick(500); + jest.advanceTimersByTime(500); await testClaimAvailableTasks({ storeOpts: { diff --git a/x-pack/platform/plugins/shared/task_manager/server/task_running/task_runner.test.ts b/x-pack/platform/plugins/shared/task_manager/server/task_running/task_runner.test.ts index 8344835a674ba..f7fb0c5419dde 100644 --- a/x-pack/platform/plugins/shared/task_manager/server/task_running/task_runner.test.ts +++ b/x-pack/platform/plugins/shared/task_manager/server/task_running/task_runner.test.ts @@ -6,7 +6,6 @@ */ import _ from 'lodash'; -import sinon from 'sinon'; import { secondsFromNow } from '../lib/intervals'; import { asOk, asErr } from '../lib/result_type'; import { @@ -50,17 +49,19 @@ const executionContext = executionContextServiceMock.createSetupContract(); const minutesFromNow = (mins: number): Date => secondsFromNow(mins * 60); const getNextRunAtSpy = jest.spyOn(nextRunAtUtils, 'getNextRunAt'); -let fakeTimer: sinon.SinonFakeTimers; - jest.mock('uuid', () => ({ v4: () => 'NEW_UUID', })); beforeAll(() => { - fakeTimer = sinon.useFakeTimers(); + jest.useFakeTimers(); +}); + +beforeEach(() => { + jest.setSystemTime(new Date('1970-01-01T00:00:00.000Z')); }); -afterAll(() => fakeTimer.restore()); +afterAll(() => jest.useRealTimers()); describe('TaskManagerRunner', () => { const pendingStageSetup = (opts: TestOpts) => testOpts(TaskRunningStage.PENDING, opts); @@ -93,6 +94,7 @@ describe('TaskManagerRunner', () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any .mockImplementation(() => mockApmTrans as any); }); + test('makes calls to APM as expected when task markedAsRunning is success', async () => { const { runner } = await pendingStageSetup({ instance: { @@ -116,6 +118,7 @@ describe('TaskManagerRunner', () => { ); expect(mockApmTrans.end).toHaveBeenCalledWith('success'); }); + test('makes calls to APM as expected when task markedAsRunning fails', async () => { const { runner, store } = await pendingStageSetup({ instance: { @@ -145,6 +148,7 @@ describe('TaskManagerRunner', () => { ); expect(mockApmTrans.end).toHaveBeenCalledWith('failure'); }); + test('provides execution context on run', async () => { const { runner } = await readyToRunStageSetup({ definitions: { @@ -170,6 +174,7 @@ describe('TaskManagerRunner', () => { expect.any(Function) ); }); + test('provides details about the task that is running', async () => { const { runner } = await pendingStageSetup({ instance: { @@ -366,7 +371,7 @@ describe('TaskManagerRunner', () => { expect(instance.enabled).not.toBeDefined(); }); - test('test sets retryAt to task instance timeout override when defined when claiming an ad hoc task', async () => { + test('sets retryAt to task instance timeout override when defined when claiming an ad hoc task', async () => { const timeoutSeconds = 60; const timeoutOverrideSeconds = 90; const id = _.random(1, 20).toString(); @@ -759,7 +764,6 @@ describe('TaskManagerRunner', () => { const id = _.random(1, 20).toString(); const initialAttempts = _.random(1, 3); const timeoutMinutes = 1; - const getRetryStub = sinon.stub().returns(false); const { runner, store } = await pendingStageSetup({ instance: { id, @@ -782,7 +786,6 @@ describe('TaskManagerRunner', () => { await runner.markTaskAsRunning(); expect(store.update).toHaveBeenCalledTimes(1); - sinon.assert.notCalled(getRetryStub); const instance = store.update.mock.calls[0][0]; const timeoutDelay = timeoutMinutes * 60 * 1000; @@ -1367,7 +1370,7 @@ describe('TaskManagerRunner', () => { createTaskRunner: () => ({ async run() { const promise = new Promise((r) => setTimeout(r, 1000)); - fakeTimer.tick(1000); + jest.advanceTimersByTime(1000); await promise; }, async cancel() { @@ -1521,7 +1524,6 @@ describe('TaskManagerRunner', () => { test('bypasses getRetry function (returning false) on error of a recurring task', async () => { const initialAttempts = _.random(1, 3); const id = Date.now().toString(); - const getRetryStub = sinon.stub().returns(false); const error = new Error('Dangit!'); const { instance: taskInstance, @@ -1555,7 +1557,6 @@ describe('TaskManagerRunner', () => { doc: taskInstance, }); - sinon.assert.notCalled(getRetryStub); const instance = store.partialUpdate.mock.calls[0][0]; const nextIntervalDelay = 60000; // 1m @@ -1811,7 +1812,7 @@ describe('TaskManagerRunner', () => { }); test('emits TaskEvent when a task is run successfully but completes after timeout', async () => { - fakeTimer = sinon.useFakeTimers(new Date(2023, 1, 1, 0, 0, 0, 0).valueOf()); + jest.setSystemTime(new Date(2023, 1, 1, 0, 0, 0, 0)); const id = _.random(1, 20).toString(); const onTaskEvent = jest.fn(); const { runner, instance } = await readyToRunStageSetup({ @@ -1832,7 +1833,7 @@ describe('TaskManagerRunner', () => { }, }); - fakeTimer = sinon.useFakeTimers(new Date(2023, 1, 1, 0, 10, 0, 0).valueOf()); + jest.setSystemTime(new Date(2023, 1, 1, 0, 10, 0, 0)); await runner.run(); expect(onTaskEvent).toHaveBeenCalledWith( @@ -1893,7 +1894,7 @@ describe('TaskManagerRunner', () => { }); test('emits TaskEvent when a recurring task is run successfully but completes after timeout', async () => { - fakeTimer = sinon.useFakeTimers(new Date(2023, 1, 1, 0, 0, 0, 0).valueOf()); + jest.setSystemTime(new Date(2023, 1, 1, 0, 0, 0, 0)); const id = _.random(1, 20).toString(); const runAt = minutesFromNow(_.random(5)); const onTaskEvent = jest.fn(); @@ -1916,7 +1917,7 @@ describe('TaskManagerRunner', () => { }, }); - fakeTimer = sinon.useFakeTimers(new Date(2023, 1, 1, 0, 10, 0, 0).valueOf()); + jest.setSystemTime(new Date(2023, 1, 1, 0, 10, 0, 0)); await runner.run(); expect(onTaskEvent).toHaveBeenCalledWith( @@ -1982,7 +1983,7 @@ describe('TaskManagerRunner', () => { }); test('emits TaskEvent when a recurring task returns a success result with taskRunError but completes after timeout', async () => { - fakeTimer = sinon.useFakeTimers(new Date(2023, 1, 1, 0, 0, 0, 0).valueOf()); + jest.setSystemTime(new Date(2023, 1, 1, 0, 0, 0, 0)); const id = _.random(1, 20).toString(); const runAt = minutesFromNow(_.random(5)); const onTaskEvent = jest.fn(); @@ -2009,7 +2010,7 @@ describe('TaskManagerRunner', () => { }, }); - fakeTimer = sinon.useFakeTimers(new Date(2023, 1, 1, 0, 10, 0, 0).valueOf()); + jest.setSystemTime(new Date(2023, 1, 1, 0, 10, 0, 0)); await runner.run(); expect(onTaskEvent).toHaveBeenCalledWith( @@ -2068,7 +2069,7 @@ describe('TaskManagerRunner', () => { }); test('emits TaskEvent when a task run throws an error and has timed out', async () => { - fakeTimer = sinon.useFakeTimers(new Date(2023, 1, 1, 0, 0, 0, 0).valueOf()); + jest.setSystemTime(new Date(2023, 1, 1, 0, 0, 0, 0)); const id = _.random(1, 20).toString(); const error = new Error('Dangit!'); const onTaskEvent = jest.fn(); @@ -2089,7 +2090,7 @@ describe('TaskManagerRunner', () => { }, }, }); - fakeTimer = sinon.useFakeTimers(new Date(2023, 1, 1, 0, 10, 0, 0).valueOf()); + jest.setSystemTime(new Date(2023, 1, 1, 0, 10, 0, 0)); await runner.run(); expect(onTaskEvent).toHaveBeenCalledWith( @@ -2567,8 +2568,6 @@ describe('TaskManagerRunner', () => { } async function testOpts(stage: TaskRunningStage, opts: TestOpts) { - const callCluster = sinon.stub(); - const createTaskRunner = sinon.stub(); const logger = mockLogger(); const instance = mockInstance(opts.instance); @@ -2583,7 +2582,7 @@ describe('TaskManagerRunner', () => { definitions.registerTaskDefinitions({ testbar: { title: 'Bar!', - createTaskRunner, + createTaskRunner: jest.fn(), }, }); if (opts.definitions) { @@ -2623,8 +2622,6 @@ describe('TaskManagerRunner', () => { } return { - callCluster, - createTaskRunner, runner, logger, store, diff --git a/yarn.lock b/yarn.lock index 1d5a0154da56d..20ce44d149fe6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10119,17 +10119,10 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.0.0.tgz#2ff674e9611b45b528896d820d3d7a812de2f0e4" integrity sha512-FyD2meJpDPjyNQejSjvnhpgI/azsQkA4lGbuu5BQZfjvJ9cbRZXzeWL2HceCekW4lixO9JPesIIQkSoLjeJHNQ== -"@sinonjs/commons@^1", "@sinonjs/commons@^1.3.0", "@sinonjs/commons@^1.4.0", "@sinonjs/commons@^1.7.0": - version "1.7.2" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.7.2.tgz#505f55c74e0272b43f6c52d81946bed7058fc0e2" - integrity sha512-+DUO6pnp3udV/v2VfUWgaY5BIE1IfT7lLfeDzPVeMT1XKkaAp9LgSI9x5RtrFQoZ9Oi0PgXQQHPaoKu7dCjVxw== - dependencies: - type-detect "4.0.8" - -"@sinonjs/commons@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.0.tgz#beb434fe875d965265e04722ccfc21df7f755d72" - integrity sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA== +"@sinonjs/commons@^3.0.0", "@sinonjs/commons@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" + integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== dependencies: type-detect "4.0.8" @@ -10140,27 +10133,26 @@ dependencies: "@sinonjs/commons" "^3.0.0" -"@sinonjs/formatio@^3.2.1": - version "3.2.2" - resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-3.2.2.tgz#771c60dfa75ea7f2d68e3b94c7e888a78781372c" - integrity sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ== +"@sinonjs/fake-timers@^13.0.1", "@sinonjs/fake-timers@^13.0.2": + version "13.0.5" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz#36b9dbc21ad5546486ea9173d6bea063eb1717d5" + integrity sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw== dependencies: - "@sinonjs/commons" "^1" - "@sinonjs/samsam" "^3.1.0" + "@sinonjs/commons" "^3.0.1" -"@sinonjs/samsam@^3.1.0", "@sinonjs/samsam@^3.3.3": - version "3.3.3" - resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-3.3.3.tgz#46682efd9967b259b81136b9f120fd54585feb4a" - integrity sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ== +"@sinonjs/samsam@^8.0.1": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-8.0.2.tgz#e4386bf668ff36c95949e55a38dc5f5892fc2689" + integrity sha512-v46t/fwnhejRSFTGqbpn9u+LQ9xJDse10gNnPgAcxgdoCDMXj/G2asWAC/8Qs+BAZDicX+MNZouXT1A7c83kVw== dependencies: - "@sinonjs/commons" "^1.3.0" - array-from "^2.1.1" - lodash "^4.17.15" + "@sinonjs/commons" "^3.0.1" + lodash.get "^4.4.2" + type-detect "^4.1.0" -"@sinonjs/text-encoding@^0.7.1": - version "0.7.1" - resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5" - integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ== +"@sinonjs/text-encoding@^0.7.3": + version "0.7.3" + resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz#282046f03e886e352b2d5f5da5eb755e01457f3f" + integrity sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA== "@slack/types@^2.9.0": version "2.11.0" @@ -12685,12 +12677,14 @@ resolved "https://registry.yarnpkg.com/@types/shimmer/-/shimmer-1.2.0.tgz#9b706af96fa06416828842397a70dfbbf1c14ded" integrity sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg== -"@types/sinon@^7.0.13": - version "7.0.13" - resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-7.0.13.tgz#ca039c23a9e27ebea53e0901ef928ea2a1a6d313" - integrity sha512-d7c/C/+H/knZ3L8/cxhicHUiTDxdgap0b/aNJfsmLwFu/iOP17mdgbQsbHA3SJmrzsjD0l3UEE5SN4xxuz5ung== +"@types/sinon@^17.0.3": + version "17.0.3" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-17.0.3.tgz#9aa7e62f0a323b9ead177ed23a36ea757141a5fa" + integrity sha512-j3uovdn8ewky9kRBG19bOwaZbexJu/XjtkHyjvUgt4xfPFz18dcORIMqnYh66Fx3Powhcr85NT5+er3+oViapw== + dependencies: + "@types/sinonjs__fake-timers" "*" -"@types/sinonjs__fake-timers@8.1.1": +"@types/sinonjs__fake-timers@*", "@types/sinonjs__fake-timers@8.1.1": version "8.1.1" resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz#b49c2c70150141a15e0fa7e79cf1f92a72934ce3" integrity sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g== @@ -13905,11 +13899,6 @@ array-flatten@1.1.1: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= -array-from@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/array-from/-/array-from-2.1.1.tgz#cfe9d8c26628b9dc5aecc62a9f5d8f1f352c1195" - integrity sha1-z+nYwmYoudxa7MYqn12PHzUsEZU= - array-includes@^3.1.6: version "3.1.6" resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f" @@ -17539,11 +17528,6 @@ diff-sequences@^29.6.3: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== -diff@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== - diff@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" @@ -17554,6 +17538,11 @@ diff@^5.0.0, diff@^5.1.0, diff@^5.2.0: resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== +diff@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-7.0.0.tgz#3fb34d387cd76d803f6eebea67b921dab0182a9a" + integrity sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw== + diff@^8.0.2: version "8.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-8.0.2.tgz#712156a6dd288e66ebb986864e190c2fc9eddfae" @@ -22921,10 +22910,10 @@ just-curry-it@^3.1.0: resolved "https://registry.yarnpkg.com/just-curry-it/-/just-curry-it-3.1.0.tgz#ab59daed308a58b847ada166edd0a2d40766fbc5" integrity sha512-mjzgSOFzlrurlURaHVjnQodyPNvrHrf1TbQP2XU9NSqBtHQPuHZ+Eb6TAJP7ASeJN9h9K0KXoRTs8u6ouHBKvg== -just-extend@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-4.0.2.tgz#f3f47f7dfca0f989c55410a7ebc8854b07108afc" - integrity sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw== +just-extend@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-6.2.0.tgz#b816abfb3d67ee860482e7401564672558163947" + integrity sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw== just-reduce-object@^1.0.3: version "1.1.0" @@ -23572,18 +23561,6 @@ loglevel@^1.6.0: resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.9.1.tgz#d63976ac9bcd03c7c873116d41c2a85bafff1be7" integrity sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg== -lolex@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lolex/-/lolex-4.2.0.tgz#ddbd7f6213ca1ea5826901ab1222b65d714b3cd7" - integrity sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg== - -lolex@^5.0.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/lolex/-/lolex-5.1.2.tgz#953694d098ce7c07bc5ed6d0e42bc6c0c6d5a367" - integrity sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A== - dependencies: - "@sinonjs/commons" "^1.7.0" - long@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" @@ -24925,16 +24902,16 @@ nice-napi@^1.0.2: node-addon-api "^3.0.0" node-gyp-build "^4.2.2" -nise@^1.5.2: - version "1.5.3" - resolved "https://registry.yarnpkg.com/nise/-/nise-1.5.3.tgz#9d2cfe37d44f57317766c6e9408a359c5d3ac1f7" - integrity sha512-Ymbac/94xeIrMf59REBPOv0thr+CJVFMhrlAkW/gjCIE58BGQdCj0x7KRCb3yz+Ga2Rz3E9XXSvUyyxqqhjQAQ== +nise@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/nise/-/nise-6.1.1.tgz#78ea93cc49be122e44cb7c8fdf597b0e8778b64a" + integrity sha512-aMSAzLVY7LyeM60gvBS423nBmIPP+Wy7St7hsb+8/fc1HmeoHJfLO8CKse4u3BtOZvQLJghYPI2i/1WZrEj5/g== dependencies: - "@sinonjs/formatio" "^3.2.1" - "@sinonjs/text-encoding" "^0.7.1" - just-extend "^4.0.2" - lolex "^5.0.1" - path-to-regexp "^1.7.0" + "@sinonjs/commons" "^3.0.1" + "@sinonjs/fake-timers" "^13.0.1" + "@sinonjs/text-encoding" "^0.7.3" + just-extend "^6.2.0" + path-to-regexp "^8.1.0" no-case@^3.0.4: version "3.0.4" @@ -29326,18 +29303,17 @@ simple-websocket@^9.0.0: readable-stream "^3.6.0" ws "^7.4.2" -sinon@^7.4.2: - version "7.5.0" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-7.5.0.tgz#e9488ea466070ea908fd44a3d6478fd4923c67ec" - integrity sha512-AoD0oJWerp0/rY9czP/D6hDTTUYGpObhZjMpd7Cl/A6+j0xBE+ayL/ldfggkBXUs0IkvIiM1ljM8+WkOc5k78Q== - dependencies: - "@sinonjs/commons" "^1.4.0" - "@sinonjs/formatio" "^3.2.1" - "@sinonjs/samsam" "^3.3.3" - diff "^3.5.0" - lolex "^4.2.0" - nise "^1.5.2" - supports-color "^5.5.0" +sinon@^19.0.2: + version "19.0.2" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-19.0.2.tgz#944cf771d22236aa84fc1ab70ce5bffc3a215dad" + integrity sha512-euuToqM+PjO4UgXeLETsfQiuoyPXlqFezr6YZDFwHR3t4qaX0fZUe1MfPMznTL5f8BWrVS89KduLdMUsxFCO6g== + dependencies: + "@sinonjs/commons" "^3.0.1" + "@sinonjs/fake-timers" "^13.0.2" + "@sinonjs/samsam" "^8.0.1" + diff "^7.0.0" + nise "^6.1.1" + supports-color "^7.2.0" sirv@^2.0.3: version "2.0.4" @@ -30357,7 +30333,7 @@ supports-color@^5.3.0, supports-color@^5.5.0: dependencies: has-flag "^3.0.0" -supports-color@^7.0.0, supports-color@^7.1.0: +supports-color@^7.0.0, supports-color@^7.1.0, supports-color@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== @@ -31225,11 +31201,16 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" -type-detect@4.0.8, type-detect@^4.0.8: +type-detect@4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== +type-detect@^4.0.8, type-detect@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.1.0.tgz#deb2453e8f08dcae7ae98c626b13dddb0155906c" + integrity sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw== + type-fest@^0.18.0: version "0.18.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f"