core-app-api: tests + fix for WebStorage event notifications
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -15,7 +15,13 @@
|
||||
*/
|
||||
|
||||
import { WebStorage } from './WebStorage';
|
||||
import { ErrorApi, StorageApi } from '@backstage/core-plugin-api';
|
||||
import {
|
||||
ErrorApi,
|
||||
StorageApi,
|
||||
StorageValueSnapshot,
|
||||
} from '@backstage/core-plugin-api';
|
||||
import { buckets } from './WebStorage';
|
||||
import { JsonValue } from '@backstage/types';
|
||||
|
||||
describe('WebStorage Storage API', () => {
|
||||
const mockErrorApi = { post: jest.fn(), error$: jest.fn() };
|
||||
@@ -30,6 +36,11 @@ describe('WebStorage Storage API', () => {
|
||||
...args,
|
||||
});
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
buckets.clear();
|
||||
});
|
||||
|
||||
it('should return undefined for values which are unset', async () => {
|
||||
const storage = createWebStorage();
|
||||
|
||||
@@ -250,4 +261,50 @@ describe('WebStorage Storage API', () => {
|
||||
snapshot.value.baz.push({ foo: 'buzz' });
|
||||
}).toThrow(/Cannot add property 1, object is not extensible/);
|
||||
});
|
||||
|
||||
it('should forward storage events accurately', async () => {
|
||||
const storage = createWebStorage();
|
||||
const bucket = storage.forBucket('foo');
|
||||
|
||||
localStorage.setItem('/foo/bar%2Fbaz', '"x"');
|
||||
localStorage.setItem('/foo/bar/baz', '"y"');
|
||||
|
||||
expect(bucket.snapshot('bar/baz').value).toBe('x');
|
||||
expect(bucket.forBucket('bar').snapshot('baz').value).toBe('y');
|
||||
|
||||
const notifyPromise = new Promise<StorageValueSnapshot<JsonValue>>(
|
||||
resolve => {
|
||||
const subscription = bucket.observe$('bar/baz').subscribe({
|
||||
next: snapshot => {
|
||||
resolve(snapshot);
|
||||
subscription.unsubscribe();
|
||||
},
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
await expect(
|
||||
Promise.race([notifyPromise, 'not-yet-resolved']),
|
||||
).resolves.toBe('not-yet-resolved');
|
||||
|
||||
window.dispatchEvent(new StorageEvent('storage', { key: '/foo/bar/baz' }));
|
||||
|
||||
localStorage.setItem('/foo/bar%2Fbaz', '"z"');
|
||||
|
||||
await expect(
|
||||
Promise.race([notifyPromise, 'not-yet-resolved']),
|
||||
).resolves.toBe('not-yet-resolved');
|
||||
|
||||
window.dispatchEvent(
|
||||
new StorageEvent('storage', { key: '/foo/bar%2Fbaz' }),
|
||||
);
|
||||
|
||||
await expect(notifyPromise).resolves.toEqual({
|
||||
key: 'bar/baz',
|
||||
presence: 'present',
|
||||
value: 'z',
|
||||
});
|
||||
|
||||
expect(bucket.snapshot('bar/baz').value).toEqual('z');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
import { JsonValue, Observable } from '@backstage/types';
|
||||
import ObservableImpl from 'zen-observable';
|
||||
|
||||
const buckets = new Map<string, WebStorage>();
|
||||
export const buckets = new Map<string, WebStorage>();
|
||||
|
||||
/**
|
||||
* An implementation of the storage API, that uses the browser's local storage.
|
||||
@@ -109,9 +109,16 @@ export class WebStorage implements StorageApi {
|
||||
}
|
||||
|
||||
private handleStorageChange(eventKey: StorageEvent['key']) {
|
||||
if (!eventKey?.startsWith(this.namespace)) return;
|
||||
const key = eventKey?.replace(`${this.namespace}/`, '');
|
||||
this.notifyChanges(key);
|
||||
if (!eventKey?.startsWith(this.namespace)) {
|
||||
return;
|
||||
}
|
||||
// Grab the part of this key that is local to this bucket
|
||||
const trimmedKey = eventKey?.slice(`${this.namespace}/`.length);
|
||||
|
||||
// If the key still contains a slash, it means it's a sub-bucket
|
||||
if (!trimmedKey.includes('/')) {
|
||||
this.notifyChanges(decodeURIComponent(trimmedKey));
|
||||
}
|
||||
}
|
||||
|
||||
private getKeyName(key: string) {
|
||||
|
||||
Reference in New Issue
Block a user