From 0b01baf309bbf9b730c826f394f08272c6806f2f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 16 Dec 2021 15:26:39 +0100 Subject: [PATCH] test-utils: update MockStorageApi Signed-off-by: Patrik Oldsberg --- .../apis/StorageApi/MockStorageApi.test.ts | 66 ++++++++++++++++++- .../apis/StorageApi/MockStorageApi.ts | 60 ++++++++++++----- 2 files changed, 109 insertions(+), 17 deletions(-) diff --git a/packages/test-utils/src/testUtils/apis/StorageApi/MockStorageApi.test.ts b/packages/test-utils/src/testUtils/apis/StorageApi/MockStorageApi.test.ts index a3028f8b57..a8187cd849 100644 --- a/packages/test-utils/src/testUtils/apis/StorageApi/MockStorageApi.test.ts +++ b/packages/test-utils/src/testUtils/apis/StorageApi/MockStorageApi.test.ts @@ -25,6 +25,12 @@ describe('WebStorage Storage API', () => { const storage = createMockStorage(); expect(storage.get('myfakekey')).toBeUndefined(); + expect(storage.snapshot('myfakekey')).toEqual({ + key: 'myfakekey', + presence: 'absent', + value: undefined, + newValue: undefined, + }); }); it('should allow the setting and getting of the simple data structures', async () => { @@ -36,6 +42,24 @@ describe('WebStorage Storage API', () => { expect(storage.get('myfakekey')).toBe('helloimastring'); expect(storage.get('mysecondfakekey')).toBe(1234); expect(storage.get('mythirdfakekey')).toBe(true); + expect(storage.snapshot('myfakekey')).toEqual({ + key: 'myfakekey', + presence: 'present', + value: 'helloimastring', + newValue: 'helloimastring', + }); + expect(storage.snapshot('mysecondfakekey')).toEqual({ + key: 'mysecondfakekey', + presence: 'present', + value: 1234, + newValue: 1234, + }); + expect(storage.snapshot('mythirdfakekey')).toEqual({ + key: 'mythirdfakekey', + presence: 'present', + value: true, + newValue: true, + }); }); it('should allow setting of complex datastructures', async () => { @@ -49,6 +73,12 @@ describe('WebStorage Storage API', () => { await storage.set('myfakekey', mockData); expect(storage.get('myfakekey')).toEqual(mockData); + expect(storage.snapshot('myfakekey')).toEqual({ + key: 'myfakekey', + presence: 'present', + value: mockData, + newValue: mockData, + }); }); it('should subscribe to key changes when setting a new value', async () => { @@ -59,7 +89,7 @@ describe('WebStorage Storage API', () => { const mockData = { hello: 'im a great new value' }; await new Promise(resolve => { - storage.observe$('correctKey').subscribe({ + storage.observe$('correctKey').subscribe({ next: (...args) => { selectedKeyNextHandler(...args); resolve(); @@ -75,6 +105,8 @@ describe('WebStorage Storage API', () => { expect(selectedKeyNextHandler).toHaveBeenCalledTimes(1); expect(selectedKeyNextHandler).toHaveBeenCalledWith({ key: 'correctKey', + presence: 'present', + value: mockData, newValue: mockData, }); }); @@ -105,6 +137,8 @@ describe('WebStorage Storage API', () => { expect(selectedKeyNextHandler).toHaveBeenCalledTimes(1); expect(selectedKeyNextHandler).toHaveBeenCalledWith({ key: 'correctKey', + presence: 'absent', + value: undefined, newValue: undefined, }); }); @@ -122,6 +156,21 @@ describe('WebStorage Storage API', () => { expect(firstStorage.get(keyName)).not.toBe(secondStorage.get(keyName)); expect(firstStorage.get(keyName)).toBe('boop'); expect(secondStorage.get(keyName)).toBe('deerp'); + expect(firstStorage.snapshot(keyName)).not.toEqual( + secondStorage.snapshot(keyName), + ); + expect(firstStorage.snapshot(keyName)).toEqual({ + key: keyName, + presence: 'present', + value: 'boop', + newValue: 'boop', + }); + expect(secondStorage.snapshot(keyName)).toEqual({ + key: keyName, + presence: 'present', + value: 'deerp', + newValue: 'deerp', + }); }); it('should not clash with other namespaces when creating buckets', async () => { @@ -138,6 +187,9 @@ describe('WebStorage Storage API', () => { await firstStorage.set('test2', { error: true }); expect(secondStorage.get('deep/test2')).toBe(undefined); + expect(secondStorage.snapshot('deep/test2')).toMatchObject({ + presence: 'absent', + }); }); it('should not reuse storage instances between different rootStorages', async () => { @@ -151,5 +203,17 @@ describe('WebStorage Storage API', () => { expect(firstStorage.get('test2')).toBe(true); expect(secondStorage.get('test2')).toBe(undefined); + expect(firstStorage.snapshot('test2')).toEqual({ + key: 'test2', + presence: 'present', + value: true, + newValue: true, + }); + expect(secondStorage.snapshot('test2')).toEqual({ + key: 'test2', + presence: 'absent', + value: undefined, + newValue: undefined, + }); }); }); diff --git a/packages/test-utils/src/testUtils/apis/StorageApi/MockStorageApi.ts b/packages/test-utils/src/testUtils/apis/StorageApi/MockStorageApi.ts index 6378a77474..f71d2602b5 100644 --- a/packages/test-utils/src/testUtils/apis/StorageApi/MockStorageApi.ts +++ b/packages/test-utils/src/testUtils/apis/StorageApi/MockStorageApi.ts @@ -14,8 +14,8 @@ * limitations under the License. */ -import { StorageApi, StorageValueChange } from '@backstage/core-plugin-api'; -import { Observable } from '@backstage/types'; +import { StorageApi, StorageValueSnapshot } from '@backstage/core-plugin-api'; +import { JsonValue, Observable } from '@backstage/types'; import ObservableImpl from 'zen-observable'; /** @@ -62,20 +62,48 @@ export class MockStorageApi implements StorageApi { } get(key: string): T | undefined { - return this.data[this.getKeyName(key)]; + return this.snapshot(key).value as T | undefined; + } + + snapshot(key: string): StorageValueSnapshot { + if (this.data.hasOwnProperty(this.getKeyName(key))) { + const data = this.data[this.getKeyName(key)]; + return { + key, + presence: 'present', + value: data, + newValue: data, + }; + } + return { + key, + presence: 'absent', + value: undefined, + newValue: undefined, + }; } async set(key: string, data: T): Promise { this.data[this.getKeyName(key)] = data; - this.notifyChanges({ key, newValue: data }); + this.notifyChanges({ + key, + presence: 'present', + value: data, + newValue: data, + }); } async remove(key: string): Promise { delete this.data[this.getKeyName(key)]; - this.notifyChanges({ key, newValue: undefined }); + this.notifyChanges({ + key, + presence: 'absent', + value: undefined, + newValue: undefined, + }); } - observe$(key: string): Observable> { + observe$(key: string): Observable> { return this.observable.filter(({ key: messageKey }) => messageKey === key); } @@ -83,22 +111,22 @@ export class MockStorageApi implements StorageApi { return `${this.namespace}/${encodeURIComponent(key)}`; } - private notifyChanges(message: StorageValueChange) { + private notifyChanges(message: StorageValueSnapshot) { for (const subscription of this.subscribers) { subscription.next(message); } } private subscribers = new Set< - ZenObservable.SubscriptionObserver + ZenObservable.SubscriptionObserver> >(); - private readonly observable = new ObservableImpl( - subscriber => { - this.subscribers.add(subscriber); - return () => { - this.subscribers.delete(subscriber); - }; - }, - ); + private readonly observable = new ObservableImpl< + StorageValueSnapshot + >(subscriber => { + this.subscribers.add(subscriber); + return () => { + this.subscribers.delete(subscriber); + }; + }); }