From efaf191183e6d0224f2e6aa126888fe85df03d5f Mon Sep 17 00:00:00 2001 From: Piotr Szlachciak Date: Thu, 21 Mar 2024 19:56:32 +0100 Subject: [PATCH] Add more tests for MultiIndexer --- .../src/indexers/multi/MultiIndexer.test.ts | 119 ++++++++++++++++++ .../uif/src/indexers/multi/MultiIndexer.ts | 4 +- 2 files changed, 121 insertions(+), 2 deletions(-) diff --git a/packages/uif/src/indexers/multi/MultiIndexer.test.ts b/packages/uif/src/indexers/multi/MultiIndexer.test.ts index e4ca7e7f..48540b4b 100644 --- a/packages/uif/src/indexers/multi/MultiIndexer.test.ts +++ b/packages/uif/src/indexers/multi/MultiIndexer.test.ts @@ -5,6 +5,39 @@ import { IMultiIndexer, MultiIndexer } from './MultiIndexer' import { Configuration, SavedConfiguration } from './types' describe(MultiIndexer.name, () => { + describe(MultiIndexer.prototype.initialize.name, () => { + it('calls multiInitialize and saves configurations', async () => { + const testIndexer = new TestMultiIndexer( + [actual('a', 100, 400), actual('b', 200, 500)], + [saved('a', 100, 300), saved('b', 200, 300), saved('c', 100, 300)], + ) + + const newHeight = await testIndexer.initialize() + expect(newHeight).toEqual(300) + + expect(testIndexer.removeData).toHaveBeenOnlyCalledWith([ + removal('c', 100, 300), + ]) + expect(testIndexer.saveConfigurations).toHaveBeenOnlyCalledWith([ + saved('a', 100, 300), + saved('b', 200, 300), + ]) + }) + + it('skips calling removeData if there is nothing to remove', async () => { + const testIndexer = new TestMultiIndexer( + [actual('a', 100, 400), actual('b', 200, 500)], + [saved('a', 100, 400), saved('b', 200, 500)], + ) + + const newHeight = await testIndexer.initialize() + expect(newHeight).toEqual(Infinity) + + expect(testIndexer.removeData).not.toHaveBeenCalled() + expect(testIndexer.saveConfigurations).not.toHaveBeenCalled() + }) + }) + describe(MultiIndexer.prototype.update.name, () => { it('calls multiUpdate with an early matching configuration', async () => { const testIndexer = new TestMultiIndexer( @@ -125,6 +158,84 @@ describe(MultiIndexer.name, () => { expect(testIndexer.saveConfigurations).not.toHaveBeenCalled() }) }) + + describe('multiUpdate', () => { + it('returns the currentHeight', async () => { + const testIndexer = new TestMultiIndexer( + [actual('a', 100, 300), actual('b', 100, 400)], + [saved('a', 100, 200), saved('b', 100, 200)], + ) + await testIndexer.initialize() + + testIndexer.multiUpdate.resolvesTo(200) + + const newHeight = await testIndexer.update(200, 500) + expect(newHeight).toEqual(200) + expect(testIndexer.saveConfigurations).not.toHaveBeenCalled() + }) + + it('returns the targetHeight', async () => { + const testIndexer = new TestMultiIndexer( + [actual('a', 100, 300), actual('b', 100, 400)], + [saved('a', 100, 200), saved('b', 100, 200)], + ) + await testIndexer.initialize() + + testIndexer.multiUpdate.resolvesTo(300) + + const newHeight = await testIndexer.update(200, 300) + expect(newHeight).toEqual(300) + expect(testIndexer.saveConfigurations).toHaveBeenOnlyCalledWith([ + saved('a', 100, 300), + saved('b', 100, 300), + ]) + }) + + it('returns something in between', async () => { + const testIndexer = new TestMultiIndexer( + [actual('a', 100, 300), actual('b', 100, 400)], + [saved('a', 100, 200), saved('b', 100, 200)], + ) + await testIndexer.initialize() + + testIndexer.multiUpdate.resolvesTo(250) + + const newHeight = await testIndexer.update(200, 300) + expect(newHeight).toEqual(250) + expect(testIndexer.saveConfigurations).toHaveBeenOnlyCalledWith([ + saved('a', 100, 250), + saved('b', 100, 250), + ]) + }) + + it('cannot return less than currentHeight', async () => { + const testIndexer = new TestMultiIndexer( + [actual('a', 100, 300), actual('b', 100, 400)], + [saved('a', 100, 200), saved('b', 100, 200)], + ) + await testIndexer.initialize() + + testIndexer.multiUpdate.resolvesTo(150) + + await expect(testIndexer.update(200, 300)).toBeRejectedWith( + /returned height must be between currentHeight and targetHeight/, + ) + }) + + it('cannot return more than targetHeight', async () => { + const testIndexer = new TestMultiIndexer( + [actual('a', 100, 300), actual('b', 100, 400)], + [saved('a', 100, 200), saved('b', 100, 200)], + ) + await testIndexer.initialize() + + testIndexer.multiUpdate.resolvesTo(350) + + await expect(testIndexer.update(200, 300)).toBeRejectedWith( + /returned height must be between currentHeight and targetHeight/, + ) + }) + }) }) class TestMultiIndexer @@ -159,3 +270,11 @@ function actual(id: string, minHeight: number, maxHeight: number | null) { function saved(id: string, minHeight: number, currentHeight: number) { return { id, minHeight, currentHeight } } + +function removal( + id: string, + fromHeightInclusive: number, + toHeightInclusive: number, +) { + return { id, fromHeightInclusive, toHeightInclusive } +} diff --git a/packages/uif/src/indexers/multi/MultiIndexer.ts b/packages/uif/src/indexers/multi/MultiIndexer.ts index ce0cece9..5ba4cc72 100644 --- a/packages/uif/src/indexers/multi/MultiIndexer.ts +++ b/packages/uif/src/indexers/multi/MultiIndexer.ts @@ -31,8 +31,8 @@ export interface IMultiIndexer { * in each configuration. It is possible for multiple ranges to share a * configuration id! * - * This method is only called during the initialization of the indexer, after - * `multiInitialize` returns. + * This method can only be called during the initialization of the indexer, + * after `multiInitialize` returns. */ removeData: (configurations: RemovalConfiguration[]) => Promise