test-utils: update MockStorageApi
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -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<void>(resolve => {
|
||||
storage.observe$<String>('correctKey').subscribe({
|
||||
storage.observe$<typeof mockData>('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,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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<T>(key: string): T | undefined {
|
||||
return this.data[this.getKeyName(key)];
|
||||
return this.snapshot(key).value as T | undefined;
|
||||
}
|
||||
|
||||
snapshot<T extends JsonValue>(key: string): StorageValueSnapshot<T> {
|
||||
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<T>(key: string, data: T): Promise<void> {
|
||||
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<void> {
|
||||
delete this.data[this.getKeyName(key)];
|
||||
this.notifyChanges({ key, newValue: undefined });
|
||||
this.notifyChanges({
|
||||
key,
|
||||
presence: 'absent',
|
||||
value: undefined,
|
||||
newValue: undefined,
|
||||
});
|
||||
}
|
||||
|
||||
observe$<T>(key: string): Observable<StorageValueChange<T>> {
|
||||
observe$<T>(key: string): Observable<StorageValueSnapshot<T>> {
|
||||
return this.observable.filter(({ key: messageKey }) => messageKey === key);
|
||||
}
|
||||
|
||||
@@ -83,22 +111,22 @@ export class MockStorageApi implements StorageApi {
|
||||
return `${this.namespace}/${encodeURIComponent(key)}`;
|
||||
}
|
||||
|
||||
private notifyChanges<T>(message: StorageValueChange<T>) {
|
||||
private notifyChanges<T>(message: StorageValueSnapshot<T>) {
|
||||
for (const subscription of this.subscribers) {
|
||||
subscription.next(message);
|
||||
}
|
||||
}
|
||||
|
||||
private subscribers = new Set<
|
||||
ZenObservable.SubscriptionObserver<StorageValueChange>
|
||||
ZenObservable.SubscriptionObserver<StorageValueSnapshot<JsonValue>>
|
||||
>();
|
||||
|
||||
private readonly observable = new ObservableImpl<StorageValueChange>(
|
||||
subscriber => {
|
||||
this.subscribers.add(subscriber);
|
||||
return () => {
|
||||
this.subscribers.delete(subscriber);
|
||||
};
|
||||
},
|
||||
);
|
||||
private readonly observable = new ObservableImpl<
|
||||
StorageValueSnapshot<JsonValue>
|
||||
>(subscriber => {
|
||||
this.subscribers.add(subscriber);
|
||||
return () => {
|
||||
this.subscribers.delete(subscriber);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user