feature(home-plugin): VisitApi implementation backed by StorageApi
Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com>
This commit is contained in:
committed by
Camila Belo
parent
5d671e6220
commit
c485469098
@@ -20,6 +20,7 @@ import { ReactElement } from 'react';
|
||||
import { ReactNode } from 'react';
|
||||
import { RendererProps as RendererProps_2 } from '@backstage/plugin-home-react';
|
||||
import { RouteRef } from '@backstage/core-plugin-api';
|
||||
import { StorageApi } from '@backstage/core-plugin-api';
|
||||
|
||||
// @public
|
||||
export type Breakpoint = 'xxs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
||||
@@ -74,6 +75,19 @@ export const ComponentTabs: (props: {
|
||||
}[];
|
||||
}) => JSX_2.Element;
|
||||
|
||||
// @public
|
||||
export class CoreStorageVisitsApi extends VisitsApiFactory {
|
||||
constructor({
|
||||
storageApi,
|
||||
randomUUID,
|
||||
limit,
|
||||
}: {
|
||||
storageApi: StorageApi;
|
||||
randomUUID?: Window['crypto']['randomUUID'];
|
||||
limit?: number;
|
||||
});
|
||||
}
|
||||
|
||||
// @public @deprecated (undocumented)
|
||||
export const createCardExtension: typeof createCardExtension_2;
|
||||
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2023 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { CoreStorageVisitsApi } from './CoreStorageVisitsApi';
|
||||
import { MockStorageApi } from '@backstage/test-utils';
|
||||
|
||||
describe('new CoreStorageVisitsApi({ storageApi: MockStorageApi.create() })', () => {
|
||||
const mockRandomUUID = () =>
|
||||
'068f3129-7440-4e0e-8fd4-xxxxxxxxxxxx'.replace(
|
||||
/x/g,
|
||||
() => Math.floor(Math.random() * 16).toString(16), // 0x0 to 0xf
|
||||
) as `${string}-${string}-${string}-${string}-${string}`;
|
||||
|
||||
beforeEach(() => {
|
||||
window.crypto.randomUUID = mockRandomUUID;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
window.localStorage.clear();
|
||||
});
|
||||
|
||||
it('instantiates with no configuration', () => {
|
||||
const api = new CoreStorageVisitsApi({
|
||||
storageApi: MockStorageApi.create(),
|
||||
});
|
||||
expect(api).toBeTruthy();
|
||||
});
|
||||
|
||||
it('saves a visit', async () => {
|
||||
const api = new CoreStorageVisitsApi({
|
||||
storageApi: MockStorageApi.create(),
|
||||
});
|
||||
const visit = {
|
||||
pathname: '/catalog/default/component/playback-order',
|
||||
entityRef: 'component:default/playback-order',
|
||||
name: 'Playback Order',
|
||||
};
|
||||
const returnedVisit = await api.saveVisit({ visit });
|
||||
expect(returnedVisit).toEqual(expect.objectContaining(visit));
|
||||
expect(returnedVisit.id).toBeTruthy();
|
||||
expect(returnedVisit.timestamp).toBeTruthy();
|
||||
expect(returnedVisit.hits).toBeTruthy();
|
||||
});
|
||||
|
||||
it('retrieves visits', async () => {
|
||||
const api = new CoreStorageVisitsApi({
|
||||
storageApi: MockStorageApi.create(),
|
||||
});
|
||||
const visit = {
|
||||
pathname: '/catalog/default/component/playback-order',
|
||||
entityRef: 'component:default/playback-order',
|
||||
name: 'Playback Order',
|
||||
};
|
||||
const returnedVisit = await api.saveVisit({ visit });
|
||||
const visits = await api.listVisits();
|
||||
expect(visits).toHaveLength(1);
|
||||
expect(visits).toEqual([expect.objectContaining(visit)]);
|
||||
expect(visits).toEqual([returnedVisit]);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2023 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { StorageApi } from '@backstage/core-plugin-api';
|
||||
import { Visit } from './VisitsApi';
|
||||
import { VisitsApiFactory } from './VisitsApiFactory';
|
||||
|
||||
/**
|
||||
* @public
|
||||
* This is an implementation of VisitsApi that relies on a StorageApi
|
||||
*/
|
||||
export class CoreStorageVisitsApi extends VisitsApiFactory {
|
||||
private readonly storageApi: StorageApi;
|
||||
private readonly storageKey = '@backstage/plugin-home:visits';
|
||||
|
||||
constructor({
|
||||
storageApi,
|
||||
randomUUID = window?.crypto?.randomUUID,
|
||||
limit = 100,
|
||||
}: {
|
||||
storageApi: StorageApi;
|
||||
randomUUID?: Window['crypto']['randomUUID'];
|
||||
limit?: number;
|
||||
}) {
|
||||
super({ randomUUID, limit });
|
||||
this.storageApi = storageApi;
|
||||
this.retrieveAll = async (): Promise<Array<Visit>> => {
|
||||
let visits: Array<Visit>;
|
||||
try {
|
||||
visits =
|
||||
this.storageApi.snapshot<Array<Visit>>(this.storageKey).value ?? [];
|
||||
} catch {
|
||||
visits = [];
|
||||
}
|
||||
return visits;
|
||||
};
|
||||
this.persistAll = async (visits: Array<Visit>) =>
|
||||
this.storageApi.set<Array<Visit>>(this.storageKey, visits);
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export * from './VisitsApi';
|
||||
export * from './CoreStorageVisitsApi';
|
||||
export * from './LocalStorageVisitsApi';
|
||||
export * from './VisitsApi';
|
||||
export * from './VisitsApiFactory';
|
||||
|
||||
@@ -33,7 +33,7 @@ const visits = [
|
||||
|
||||
const mockVisitsApi = {
|
||||
saveVisit: async () => visits[0],
|
||||
listUserVisits: async () => visits,
|
||||
listVisits: async () => visits,
|
||||
};
|
||||
|
||||
describe('<Content kind="recent"/>', () => {
|
||||
|
||||
Reference in New Issue
Block a user