mirror of
https://github.com/immich-app/immich.git
synced 2025-12-22 09:15:34 +03:00
feat: timeline performance (#16446)
* Squash - feature complete * remove need to init assetstore * More optimizations. No need to init. Fix tests * lint * add missing selector for e2e * e2e selectors again * Update: fully reactive store, some transitions, bugfixes * merge fallout * Test fallout * safari quirk * security * lint * lint * Bug fixes * lint/format * accidental commit * lock * null check, more throttle * revert long duration * Fix intersection bounds * Fix bugs in intersection calculation * lint, tweak scrubber ui a tiny bit * bugfix - deselecting asset doesnt work * fix not loading bucket, scroll off-by-1 error, jsdoc, naming
This commit is contained in:
@@ -12,21 +12,25 @@ describe('AssetStore', () => {
|
||||
describe('init', () => {
|
||||
let assetStore: AssetStore;
|
||||
const bucketAssets: Record<string, AssetResponseDto[]> = {
|
||||
'2024-03-01T00:00:00.000Z': assetFactory.buildList(1),
|
||||
'2024-02-01T00:00:00.000Z': assetFactory.buildList(100),
|
||||
'2024-01-01T00:00:00.000Z': assetFactory.buildList(3),
|
||||
'2024-03-01T00:00:00.000Z': assetFactory
|
||||
.buildList(1)
|
||||
.map((asset) => ({ ...asset, localDateTime: '2024-03-01T00:00:00.000Z' })),
|
||||
'2024-02-01T00:00:00.000Z': assetFactory
|
||||
.buildList(100)
|
||||
.map((asset) => ({ ...asset, localDateTime: '2024-02-01T00:00:00.000Z' })),
|
||||
'2024-01-01T00:00:00.000Z': assetFactory
|
||||
.buildList(3)
|
||||
.map((asset) => ({ ...asset, localDateTime: '2024-01-01T00:00:00.000Z' })),
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
assetStore = new AssetStore({});
|
||||
assetStore = new AssetStore();
|
||||
sdkMock.getTimeBuckets.mockResolvedValue([
|
||||
{ count: 1, timeBucket: '2024-03-01T00:00:00.000Z' },
|
||||
{ count: 100, timeBucket: '2024-02-01T00:00:00.000Z' },
|
||||
{ count: 3, timeBucket: '2024-01-01T00:00:00.000Z' },
|
||||
]);
|
||||
sdkMock.getTimeBucket.mockImplementation(({ timeBucket }) => Promise.resolve(bucketAssets[timeBucket]));
|
||||
|
||||
await assetStore.init();
|
||||
await assetStore.updateViewport({ width: 1588, height: 1000 });
|
||||
});
|
||||
|
||||
@@ -37,51 +41,57 @@ describe('AssetStore', () => {
|
||||
});
|
||||
|
||||
it('calculates bucket height', () => {
|
||||
expect(assetStore.buckets).toEqual(
|
||||
const plainBuckets = assetStore.buckets.map((bucket) => ({
|
||||
bucketDate: bucket.bucketDate,
|
||||
bucketHeight: bucket.bucketHeight,
|
||||
}));
|
||||
|
||||
expect(plainBuckets).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ bucketDate: '2024-03-01T00:00:00.000Z', bucketHeight: 286 }),
|
||||
expect.objectContaining({ bucketDate: '2024-02-01T00:00:00.000Z', bucketHeight: 3811 }),
|
||||
expect.objectContaining({ bucketDate: '2024-03-01T00:00:00.000Z', bucketHeight: 304 }),
|
||||
expect.objectContaining({ bucketDate: '2024-02-01T00:00:00.000Z', bucketHeight: 4515.333_333_333_333 }),
|
||||
expect.objectContaining({ bucketDate: '2024-01-01T00:00:00.000Z', bucketHeight: 286 }),
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
it('calculates timeline height', () => {
|
||||
expect(assetStore.timelineHeight).toBe(4383);
|
||||
expect(assetStore.timelineHeight).toBe(5105.333_333_333_333);
|
||||
});
|
||||
});
|
||||
|
||||
describe('loadBucket', () => {
|
||||
let assetStore: AssetStore;
|
||||
const bucketAssets: Record<string, AssetResponseDto[]> = {
|
||||
'2024-01-03T00:00:00.000Z': assetFactory.buildList(1),
|
||||
'2024-01-01T00:00:00.000Z': assetFactory.buildList(3),
|
||||
'2024-01-03T00:00:00.000Z': assetFactory
|
||||
.buildList(1)
|
||||
.map((asset) => ({ ...asset, localDateTime: '2024-03-01T00:00:00.000Z' })),
|
||||
'2024-01-01T00:00:00.000Z': assetFactory
|
||||
.buildList(3)
|
||||
.map((asset) => ({ ...asset, localDateTime: '2024-01-01T00:00:00.000Z' })),
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
assetStore = new AssetStore({});
|
||||
assetStore = new AssetStore();
|
||||
sdkMock.getTimeBuckets.mockResolvedValue([
|
||||
{ count: 1, timeBucket: '2024-01-03T00:00:00.000Z' },
|
||||
{ count: 1, timeBucket: '2024-03-01T00:00:00.000Z' },
|
||||
{ count: 3, timeBucket: '2024-01-01T00:00:00.000Z' },
|
||||
]);
|
||||
sdkMock.getTimeBucket.mockImplementation(async ({ timeBucket }, { signal } = {}) => {
|
||||
// Allow request to be aborted
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
if (signal?.aborted) {
|
||||
throw new AbortError();
|
||||
}
|
||||
|
||||
return bucketAssets[timeBucket];
|
||||
});
|
||||
await assetStore.init();
|
||||
await assetStore.updateViewport({ width: 0, height: 0 });
|
||||
await assetStore.updateViewport({ width: 1588, height: 0 });
|
||||
});
|
||||
|
||||
it('loads a bucket', async () => {
|
||||
expect(assetStore.getBucketByDate('2024-01-01T00:00:00.000Z')?.assets.length).toEqual(0);
|
||||
expect(assetStore.getBucketByDate(2024, 1)?.getAssets().length).toEqual(0);
|
||||
await assetStore.loadBucket('2024-01-01T00:00:00.000Z');
|
||||
expect(sdkMock.getTimeBucket).toBeCalledTimes(1);
|
||||
expect(assetStore.getBucketByDate('2024-01-01T00:00:00.000Z')?.assets.length).toEqual(3);
|
||||
expect(assetStore.getBucketByDate(2024, 1)?.getAssets().length).toEqual(3);
|
||||
});
|
||||
|
||||
it('ignores invalid buckets', async () => {
|
||||
@@ -90,15 +100,13 @@ describe('AssetStore', () => {
|
||||
});
|
||||
|
||||
it('cancels bucket loading', async () => {
|
||||
const bucket = assetStore.getBucketByDate('2024-01-01T00:00:00.000Z');
|
||||
const loadPromise = assetStore.loadBucket(bucket!.bucketDate);
|
||||
|
||||
const abortSpy = vi.spyOn(bucket!.cancelToken!, 'abort');
|
||||
const bucket = assetStore.getBucketByDate(2024, 1)!;
|
||||
void assetStore.loadBucket(bucket!.bucketDate);
|
||||
const abortSpy = vi.spyOn(bucket!.loader!.cancelToken!, 'abort');
|
||||
bucket?.cancel();
|
||||
expect(abortSpy).toBeCalledTimes(1);
|
||||
|
||||
await loadPromise;
|
||||
expect(assetStore.getBucketByDate('2024-01-01T00:00:00.000Z')?.assets.length).toEqual(0);
|
||||
await assetStore.loadBucket(bucket!.bucketDate);
|
||||
expect(assetStore.getBucketByDate(2024, 1)?.getAssets().length).toEqual(3);
|
||||
});
|
||||
|
||||
it('prevents loading buckets multiple times', async () => {
|
||||
@@ -113,15 +121,15 @@ describe('AssetStore', () => {
|
||||
});
|
||||
|
||||
it('allows loading a canceled bucket', async () => {
|
||||
const bucket = assetStore.getBucketByDate('2024-01-01T00:00:00.000Z');
|
||||
const bucket = assetStore.getBucketByDate(2024, 1)!;
|
||||
const loadPromise = assetStore.loadBucket(bucket!.bucketDate);
|
||||
|
||||
bucket?.cancel();
|
||||
bucket.cancel();
|
||||
await loadPromise;
|
||||
expect(bucket?.assets.length).toEqual(0);
|
||||
expect(bucket?.getAssets().length).toEqual(0);
|
||||
|
||||
await assetStore.loadBucket(bucket!.bucketDate);
|
||||
expect(bucket!.assets.length).toEqual(3);
|
||||
await assetStore.loadBucket(bucket.bucketDate);
|
||||
expect(bucket!.getAssets().length).toEqual(3);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -129,15 +137,15 @@ describe('AssetStore', () => {
|
||||
let assetStore: AssetStore;
|
||||
|
||||
beforeEach(async () => {
|
||||
assetStore = new AssetStore({});
|
||||
assetStore = new AssetStore();
|
||||
sdkMock.getTimeBuckets.mockResolvedValue([]);
|
||||
await assetStore.init();
|
||||
|
||||
await assetStore.updateViewport({ width: 1588, height: 1000 });
|
||||
});
|
||||
|
||||
it('is empty initially', () => {
|
||||
expect(assetStore.buckets.length).toEqual(0);
|
||||
expect(assetStore.assets.length).toEqual(0);
|
||||
expect(assetStore.getAssets().length).toEqual(0);
|
||||
});
|
||||
|
||||
it('adds assets to new bucket', () => {
|
||||
@@ -148,10 +156,10 @@ describe('AssetStore', () => {
|
||||
assetStore.addAssets([asset]);
|
||||
|
||||
expect(assetStore.buckets.length).toEqual(1);
|
||||
expect(assetStore.assets.length).toEqual(1);
|
||||
expect(assetStore.buckets[0].assets.length).toEqual(1);
|
||||
expect(assetStore.getAssets().length).toEqual(1);
|
||||
expect(assetStore.buckets[0].getAssets().length).toEqual(1);
|
||||
expect(assetStore.buckets[0].bucketDate).toEqual('2024-01-01T00:00:00.000Z');
|
||||
expect(assetStore.assets[0].id).toEqual(asset.id);
|
||||
expect(assetStore.getAssets()[0].id).toEqual(asset.id);
|
||||
});
|
||||
|
||||
it('adds assets to existing bucket', () => {
|
||||
@@ -163,8 +171,8 @@ describe('AssetStore', () => {
|
||||
assetStore.addAssets([assetTwo]);
|
||||
|
||||
expect(assetStore.buckets.length).toEqual(1);
|
||||
expect(assetStore.assets.length).toEqual(2);
|
||||
expect(assetStore.buckets[0].assets.length).toEqual(2);
|
||||
expect(assetStore.getAssets().length).toEqual(2);
|
||||
expect(assetStore.buckets[0].getAssets().length).toEqual(2);
|
||||
expect(assetStore.buckets[0].bucketDate).toEqual('2024-01-01T00:00:00.000Z');
|
||||
});
|
||||
|
||||
@@ -183,12 +191,12 @@ describe('AssetStore', () => {
|
||||
});
|
||||
assetStore.addAssets([assetOne, assetTwo, assetThree]);
|
||||
|
||||
const bucket = assetStore.getBucketByDate('2024-01-01T00:00:00.000Z');
|
||||
const bucket = assetStore.getBucketByDate(2024, 1);
|
||||
expect(bucket).not.toBeNull();
|
||||
expect(bucket?.assets.length).toEqual(3);
|
||||
expect(bucket?.assets[0].id).toEqual(assetOne.id);
|
||||
expect(bucket?.assets[1].id).toEqual(assetThree.id);
|
||||
expect(bucket?.assets[2].id).toEqual(assetTwo.id);
|
||||
expect(bucket?.getAssets().length).toEqual(3);
|
||||
expect(bucket?.getAssets()[0].id).toEqual(assetOne.id);
|
||||
expect(bucket?.getAssets()[1].id).toEqual(assetThree.id);
|
||||
expect(bucket?.getAssets()[2].id).toEqual(assetTwo.id);
|
||||
});
|
||||
|
||||
it('orders buckets by descending date', () => {
|
||||
@@ -210,17 +218,18 @@ describe('AssetStore', () => {
|
||||
|
||||
assetStore.addAssets([asset]);
|
||||
expect(updateAssetsSpy).toBeCalledWith([asset]);
|
||||
expect(assetStore.assets.length).toEqual(1);
|
||||
expect(assetStore.getAssets().length).toEqual(1);
|
||||
});
|
||||
|
||||
// disabled due to the wasm Justified Layout import
|
||||
it.skip('ignores trashed assets when isTrashed is true', () => {
|
||||
it('ignores trashed assets when isTrashed is true', async () => {
|
||||
const asset = assetFactory.build({ isTrashed: false });
|
||||
const trashedAsset = assetFactory.build({ isTrashed: true });
|
||||
|
||||
const assetStore = new AssetStore({ isTrashed: true });
|
||||
const assetStore = new AssetStore();
|
||||
await assetStore.updateOptions({ isTrashed: true });
|
||||
assetStore.addAssets([asset, trashedAsset]);
|
||||
expect(assetStore.assets).toEqual([trashedAsset]);
|
||||
expect(assetStore.getAssets()).toEqual([trashedAsset]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -228,9 +237,9 @@ describe('AssetStore', () => {
|
||||
let assetStore: AssetStore;
|
||||
|
||||
beforeEach(async () => {
|
||||
assetStore = new AssetStore({});
|
||||
assetStore = new AssetStore();
|
||||
sdkMock.getTimeBuckets.mockResolvedValue([]);
|
||||
await assetStore.init();
|
||||
|
||||
await assetStore.updateViewport({ width: 1588, height: 1000 });
|
||||
});
|
||||
|
||||
@@ -238,7 +247,7 @@ describe('AssetStore', () => {
|
||||
assetStore.updateAssets([assetFactory.build()]);
|
||||
|
||||
expect(assetStore.buckets.length).toEqual(0);
|
||||
expect(assetStore.assets.length).toEqual(0);
|
||||
expect(assetStore.getAssets().length).toEqual(0);
|
||||
});
|
||||
|
||||
it('updates an asset', () => {
|
||||
@@ -246,26 +255,29 @@ describe('AssetStore', () => {
|
||||
const updatedAsset = { ...asset, isFavorite: true };
|
||||
|
||||
assetStore.addAssets([asset]);
|
||||
expect(assetStore.assets.length).toEqual(1);
|
||||
expect(assetStore.assets[0].isFavorite).toEqual(false);
|
||||
expect(assetStore.getAssets().length).toEqual(1);
|
||||
expect(assetStore.getAssets()[0].isFavorite).toEqual(false);
|
||||
|
||||
assetStore.updateAssets([updatedAsset]);
|
||||
expect(assetStore.assets.length).toEqual(1);
|
||||
expect(assetStore.assets[0].isFavorite).toEqual(true);
|
||||
expect(assetStore.getAssets().length).toEqual(1);
|
||||
expect(assetStore.getAssets()[0].isFavorite).toEqual(true);
|
||||
});
|
||||
|
||||
it('replaces bucket date when asset date changes', () => {
|
||||
it('asset moves buckets when asset date changes', () => {
|
||||
const asset = assetFactory.build({ localDateTime: '2024-01-20T12:00:00.000Z' });
|
||||
const updatedAsset = { ...asset, localDateTime: '2024-03-20T12:00:00.000Z' };
|
||||
|
||||
assetStore.addAssets([asset]);
|
||||
expect(assetStore.buckets.length).toEqual(1);
|
||||
expect(assetStore.getBucketByDate('2024-01-01T00:00:00.000Z')).not.toBeNull();
|
||||
expect(assetStore.getBucketByDate(2024, 1)).not.toBeUndefined();
|
||||
expect(assetStore.getBucketByDate(2024, 1)?.getAssets().length).toEqual(1);
|
||||
|
||||
assetStore.updateAssets([updatedAsset]);
|
||||
expect(assetStore.buckets.length).toEqual(1);
|
||||
expect(assetStore.getBucketByDate('2024-01-01T00:00:00.000Z')).toBeNull();
|
||||
expect(assetStore.getBucketByDate('2024-03-01T00:00:00.000Z')).not.toBeNull();
|
||||
expect(assetStore.buckets.length).toEqual(2);
|
||||
expect(assetStore.getBucketByDate(2024, 1)).not.toBeUndefined();
|
||||
expect(assetStore.getBucketByDate(2024, 1)?.getAssets().length).toEqual(0);
|
||||
expect(assetStore.getBucketByDate(2024, 3)).not.toBeUndefined();
|
||||
expect(assetStore.getBucketByDate(2024, 3)?.getAssets().length).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -273,9 +285,9 @@ describe('AssetStore', () => {
|
||||
let assetStore: AssetStore;
|
||||
|
||||
beforeEach(async () => {
|
||||
assetStore = new AssetStore({});
|
||||
assetStore = new AssetStore();
|
||||
sdkMock.getTimeBuckets.mockResolvedValue([]);
|
||||
await assetStore.init();
|
||||
|
||||
await assetStore.updateViewport({ width: 1588, height: 1000 });
|
||||
});
|
||||
|
||||
@@ -283,9 +295,9 @@ describe('AssetStore', () => {
|
||||
assetStore.addAssets(assetFactory.buildList(2, { localDateTime: '2024-01-20T12:00:00.000Z' }));
|
||||
assetStore.removeAssets(['', 'invalid', '4c7d9acc']);
|
||||
|
||||
expect(assetStore.assets.length).toEqual(2);
|
||||
expect(assetStore.getAssets().length).toEqual(2);
|
||||
expect(assetStore.buckets.length).toEqual(1);
|
||||
expect(assetStore.buckets[0].assets.length).toEqual(2);
|
||||
expect(assetStore.buckets[0].getAssets().length).toEqual(2);
|
||||
});
|
||||
|
||||
it('removes asset from bucket', () => {
|
||||
@@ -293,18 +305,18 @@ describe('AssetStore', () => {
|
||||
assetStore.addAssets([assetOne, assetTwo]);
|
||||
assetStore.removeAssets([assetOne.id]);
|
||||
|
||||
expect(assetStore.assets.length).toEqual(1);
|
||||
expect(assetStore.getAssets().length).toEqual(1);
|
||||
expect(assetStore.buckets.length).toEqual(1);
|
||||
expect(assetStore.buckets[0].assets.length).toEqual(1);
|
||||
expect(assetStore.buckets[0].getAssets().length).toEqual(1);
|
||||
});
|
||||
|
||||
it('removes bucket when empty', () => {
|
||||
it('does not remove bucket when empty', () => {
|
||||
const assets = assetFactory.buildList(2, { localDateTime: '2024-01-20T12:00:00.000Z' });
|
||||
assetStore.addAssets(assets);
|
||||
assetStore.removeAssets(assets.map((asset) => asset.id));
|
||||
|
||||
expect(assetStore.assets.length).toEqual(0);
|
||||
expect(assetStore.buckets.length).toEqual(0);
|
||||
expect(assetStore.getAssets().length).toEqual(0);
|
||||
expect(assetStore.buckets.length).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -312,14 +324,13 @@ describe('AssetStore', () => {
|
||||
let assetStore: AssetStore;
|
||||
|
||||
beforeEach(async () => {
|
||||
assetStore = new AssetStore({});
|
||||
assetStore = new AssetStore();
|
||||
sdkMock.getTimeBuckets.mockResolvedValue([]);
|
||||
await assetStore.init();
|
||||
await assetStore.updateViewport({ width: 0, height: 0 });
|
||||
});
|
||||
|
||||
it('empty store returns null', () => {
|
||||
expect(assetStore.getFirstAsset()).toBeNull();
|
||||
expect(assetStore.getFirstAsset()).toBeUndefined();
|
||||
});
|
||||
|
||||
it('populated store returns first asset', () => {
|
||||
@@ -339,13 +350,19 @@ describe('AssetStore', () => {
|
||||
describe('getPreviousAsset', () => {
|
||||
let assetStore: AssetStore;
|
||||
const bucketAssets: Record<string, AssetResponseDto[]> = {
|
||||
'2024-03-01T00:00:00.000Z': assetFactory.buildList(1),
|
||||
'2024-02-01T00:00:00.000Z': assetFactory.buildList(6),
|
||||
'2024-01-01T00:00:00.000Z': assetFactory.buildList(3),
|
||||
'2024-03-01T00:00:00.000Z': assetFactory
|
||||
.buildList(1)
|
||||
.map((asset) => ({ ...asset, localDateTime: '2024-03-01T00:00:00.000Z' })),
|
||||
'2024-02-01T00:00:00.000Z': assetFactory
|
||||
.buildList(6)
|
||||
.map((asset) => ({ ...asset, localDateTime: '2024-02-01T00:00:00.000Z' })),
|
||||
'2024-01-01T00:00:00.000Z': assetFactory
|
||||
.buildList(3)
|
||||
.map((asset) => ({ ...asset, localDateTime: '2024-01-01T00:00:00.000Z' })),
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
assetStore = new AssetStore({});
|
||||
assetStore = new AssetStore();
|
||||
sdkMock.getTimeBuckets.mockResolvedValue([
|
||||
{ count: 1, timeBucket: '2024-03-01T00:00:00.000Z' },
|
||||
{ count: 6, timeBucket: '2024-02-01T00:00:00.000Z' },
|
||||
@@ -353,38 +370,46 @@ describe('AssetStore', () => {
|
||||
]);
|
||||
sdkMock.getTimeBucket.mockImplementation(({ timeBucket }) => Promise.resolve(bucketAssets[timeBucket]));
|
||||
|
||||
await assetStore.init();
|
||||
await assetStore.updateViewport({ width: 0, height: 0 });
|
||||
await assetStore.updateViewport({ width: 1588, height: 1000 });
|
||||
});
|
||||
|
||||
it('returns null for invalid assetId', async () => {
|
||||
expect(() => assetStore.getPreviousAsset({ id: 'invalid' } as AssetResponseDto)).not.toThrow();
|
||||
expect(await assetStore.getPreviousAsset({ id: 'invalid' } as AssetResponseDto)).toBeNull();
|
||||
expect(await assetStore.getPreviousAsset({ id: 'invalid' } as AssetResponseDto)).toBeUndefined();
|
||||
});
|
||||
|
||||
it('returns previous assetId', async () => {
|
||||
await assetStore.loadBucket('2024-01-01T00:00:00.000Z');
|
||||
const bucket = assetStore.getBucketByDate('2024-01-01T00:00:00.000Z');
|
||||
const bucket = assetStore.getBucketByDate(2024, 1);
|
||||
|
||||
expect(await assetStore.getPreviousAsset(bucket!.assets[1])).toEqual(bucket!.assets[0]);
|
||||
const a = bucket!.getAssets()[0];
|
||||
const b = bucket!.getAssets()[1];
|
||||
const previous = await assetStore.getPreviousAsset(b);
|
||||
expect(previous).toEqual(a);
|
||||
});
|
||||
|
||||
it('returns previous assetId spanning multiple buckets', async () => {
|
||||
await assetStore.loadBucket('2024-02-01T00:00:00.000Z');
|
||||
await assetStore.loadBucket('2024-03-01T00:00:00.000Z');
|
||||
|
||||
const bucket = assetStore.getBucketByDate('2024-02-01T00:00:00.000Z');
|
||||
const previousBucket = assetStore.getBucketByDate('2024-03-01T00:00:00.000Z');
|
||||
expect(await assetStore.getPreviousAsset(bucket!.assets[0])).toEqual(previousBucket!.assets[0]);
|
||||
const bucket = assetStore.getBucketByDate(2024, 2);
|
||||
const previousBucket = assetStore.getBucketByDate(2024, 3);
|
||||
const a = bucket!.getAssets()[0];
|
||||
const b = previousBucket!.getAssets()[0];
|
||||
const previous = await assetStore.getPreviousAsset(a);
|
||||
expect(previous).toEqual(b);
|
||||
});
|
||||
|
||||
it('loads previous bucket', async () => {
|
||||
await assetStore.loadBucket('2024-02-01T00:00:00.000Z');
|
||||
|
||||
const loadBucketSpy = vi.spyOn(assetStore, 'loadBucket');
|
||||
const bucket = assetStore.getBucketByDate('2024-02-01T00:00:00.000Z');
|
||||
const previousBucket = assetStore.getBucketByDate('2024-03-01T00:00:00.000Z');
|
||||
expect(await assetStore.getPreviousAsset(bucket!.assets[0])).toEqual(previousBucket!.assets[0]);
|
||||
const bucket = assetStore.getBucketByDate(2024, 2);
|
||||
const previousBucket = assetStore.getBucketByDate(2024, 3);
|
||||
const a = bucket!.getAssets()[0];
|
||||
const b = previousBucket!.getAssets()[0];
|
||||
const previous = await assetStore.getPreviousAsset(a);
|
||||
expect(previous).toEqual(b);
|
||||
expect(loadBucketSpy).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
@@ -393,14 +418,14 @@ describe('AssetStore', () => {
|
||||
await assetStore.loadBucket('2024-02-01T00:00:00.000Z');
|
||||
await assetStore.loadBucket('2024-03-01T00:00:00.000Z');
|
||||
|
||||
const [assetOne, assetTwo, assetThree] = assetStore.assets;
|
||||
const [assetOne, assetTwo, assetThree] = assetStore.getAssets();
|
||||
assetStore.removeAssets([assetTwo.id]);
|
||||
expect(await assetStore.getPreviousAsset(assetThree)).toEqual(assetOne);
|
||||
});
|
||||
|
||||
it('returns null when no more assets', async () => {
|
||||
await assetStore.loadBucket('2024-03-01T00:00:00.000Z');
|
||||
expect(await assetStore.getPreviousAsset(assetStore.assets[0])).toBeNull();
|
||||
expect(await assetStore.getPreviousAsset(assetStore.getAssets()[0])).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -408,15 +433,15 @@ describe('AssetStore', () => {
|
||||
let assetStore: AssetStore;
|
||||
|
||||
beforeEach(async () => {
|
||||
assetStore = new AssetStore({});
|
||||
assetStore = new AssetStore();
|
||||
sdkMock.getTimeBuckets.mockResolvedValue([]);
|
||||
await assetStore.init();
|
||||
|
||||
await assetStore.updateViewport({ width: 0, height: 0 });
|
||||
});
|
||||
|
||||
it('returns null for invalid buckets', () => {
|
||||
expect(assetStore.getBucketByDate('invalid')).toBeNull();
|
||||
expect(assetStore.getBucketByDate('2024-03-01T00:00:00.000Z')).toBeNull();
|
||||
expect(assetStore.getBucketByDate(-1, -1)).toBeUndefined();
|
||||
expect(assetStore.getBucketByDate(2024, 3)).toBeUndefined();
|
||||
});
|
||||
|
||||
it('returns the bucket index', () => {
|
||||
@@ -424,8 +449,8 @@ describe('AssetStore', () => {
|
||||
const assetTwo = assetFactory.build({ localDateTime: '2024-02-15T12:00:00.000Z' });
|
||||
assetStore.addAssets([assetOne, assetTwo]);
|
||||
|
||||
expect(assetStore.getBucketIndexByAssetId(assetTwo.id)).toEqual(0);
|
||||
expect(assetStore.getBucketIndexByAssetId(assetOne.id)).toEqual(1);
|
||||
expect(assetStore.getBucketIndexByAssetId(assetTwo.id)?.bucketDate).toEqual('2024-02-01T00:00:00.000Z');
|
||||
expect(assetStore.getBucketIndexByAssetId(assetOne.id)?.bucketDate).toEqual('2024-01-01T00:00:00.000Z');
|
||||
});
|
||||
|
||||
it('ignores removed buckets', () => {
|
||||
@@ -434,7 +459,7 @@ describe('AssetStore', () => {
|
||||
assetStore.addAssets([assetOne, assetTwo]);
|
||||
|
||||
assetStore.removeAssets([assetTwo.id]);
|
||||
expect(assetStore.getBucketIndexByAssetId(assetOne.id)).toEqual(0);
|
||||
expect(assetStore.getBucketIndexByAssetId(assetOne.id)?.bucketDate).toEqual('2024-01-01T00:00:00.000Z');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user