catalog-react: added MockStarredEntitiesApi + usage
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -476,6 +476,14 @@ export const MockEntityListContextProvider: ({
|
||||
value?: Partial<EntityListContextProps<DefaultEntityFilters>> | undefined;
|
||||
}>) => JSX.Element;
|
||||
|
||||
// @public
|
||||
export class MockStarredEntitiesApi implements StarredEntitiesApi {
|
||||
// (undocumented)
|
||||
starredEntitie$(): Observable<Set<string>>;
|
||||
// (undocumented)
|
||||
toggleStarred(entityRef: string): Promise<void>;
|
||||
}
|
||||
|
||||
// @public @deprecated (undocumented)
|
||||
export function reduceCatalogFilters(
|
||||
filters: EntityFilter[],
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2021 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 { MockStarredEntitiesApi } from './MockStarredEntitiesApi';
|
||||
|
||||
describe('MockStarredEntitiesApi', () => {
|
||||
it('should toggle starred entities', async () => {
|
||||
const api = new MockStarredEntitiesApi();
|
||||
|
||||
const updates1 = new Array<Set<string>>();
|
||||
const sub1 = api
|
||||
.starredEntitie$()
|
||||
.subscribe(entities => updates1.push(entities));
|
||||
|
||||
api.toggleStarred('k:ns/e1');
|
||||
api.toggleStarred('k:ns/e2');
|
||||
|
||||
await Promise.resolve();
|
||||
expect(updates1).toEqual([
|
||||
new Set(),
|
||||
new Set(['k:ns/e1']),
|
||||
new Set(['k:ns/e1', 'k:ns/e2']),
|
||||
]);
|
||||
|
||||
const updates2 = new Array<Set<string>>();
|
||||
const sub2 = api
|
||||
.starredEntitie$()
|
||||
.subscribe(entities => updates2.push(entities));
|
||||
|
||||
api.toggleStarred('k:ns/e2');
|
||||
sub1.unsubscribe();
|
||||
api.toggleStarred('k:ns/e2');
|
||||
|
||||
await Promise.resolve();
|
||||
expect(updates1).toEqual([
|
||||
new Set(),
|
||||
new Set(['k:ns/e1']),
|
||||
new Set(['k:ns/e1', 'k:ns/e2']),
|
||||
new Set(['k:ns/e1']),
|
||||
]);
|
||||
expect(updates2).toEqual([
|
||||
new Set(['k:ns/e1', 'k:ns/e2']),
|
||||
new Set(['k:ns/e1']),
|
||||
new Set(['k:ns/e1', 'k:ns/e2']),
|
||||
]);
|
||||
sub2.unsubscribe();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2021 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 { Observable } from '@backstage/types';
|
||||
import ObservableImpl from 'zen-observable';
|
||||
import { StarredEntitiesApi } from './StarredEntitiesApi';
|
||||
|
||||
/**
|
||||
* An in-memory mock implementation of the StarredEntitiesApi.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export class MockStarredEntitiesApi implements StarredEntitiesApi {
|
||||
private readonly starredEntities = new Set<string>();
|
||||
private readonly subscribers = new Set<
|
||||
ZenObservable.SubscriptionObserver<Set<string>>
|
||||
>();
|
||||
|
||||
private readonly observable = new ObservableImpl<Set<string>>(subscriber => {
|
||||
subscriber.next(new Set(this.starredEntities));
|
||||
|
||||
this.subscribers.add(subscriber);
|
||||
return () => {
|
||||
this.subscribers.delete(subscriber);
|
||||
};
|
||||
});
|
||||
|
||||
async toggleStarred(entityRef: string): Promise<void> {
|
||||
if (!this.starredEntities.delete(entityRef)) {
|
||||
this.starredEntities.add(entityRef);
|
||||
}
|
||||
|
||||
for (const subscription of this.subscribers) {
|
||||
subscription.next(new Set(this.starredEntities));
|
||||
}
|
||||
}
|
||||
|
||||
starredEntitie$(): Observable<Set<string>> {
|
||||
return this.observable;
|
||||
}
|
||||
}
|
||||
@@ -16,3 +16,4 @@
|
||||
|
||||
export { starredEntitiesApiRef } from './StarredEntitiesApi';
|
||||
export type { StarredEntitiesApi } from './StarredEntitiesApi';
|
||||
export { MockStarredEntitiesApi } from './MockStarredEntitiesApi';
|
||||
|
||||
@@ -23,14 +23,13 @@ import {
|
||||
identityApiRef,
|
||||
storageApiRef,
|
||||
} from '@backstage/core-plugin-api';
|
||||
import { DefaultStarredEntitiesApi } from '@backstage/plugin-catalog';
|
||||
import { MockStorageApi, TestApiProvider } from '@backstage/test-utils';
|
||||
import { act, renderHook } from '@testing-library/react-hooks';
|
||||
import qs from 'qs';
|
||||
import React, { PropsWithChildren } from 'react';
|
||||
import { MemoryRouter } from 'react-router';
|
||||
import { catalogApiRef } from '../api';
|
||||
import { starredEntitiesApiRef } from '../apis';
|
||||
import { starredEntitiesApiRef, MockStarredEntitiesApi } from '../apis';
|
||||
import { EntityKindPicker, UserListPicker } from '../components';
|
||||
import { EntityKindFilter, EntityTypeFilter, UserListFilter } from '../filters';
|
||||
import { UserListFilterKind } from '../types';
|
||||
@@ -96,12 +95,7 @@ const wrapper = ({
|
||||
[catalogApiRef, mockCatalogApi],
|
||||
[identityApiRef, mockIdentityApi],
|
||||
[storageApiRef, MockStorageApi.create()],
|
||||
[
|
||||
starredEntitiesApiRef,
|
||||
new DefaultStarredEntitiesApi({
|
||||
storageApi: MockStorageApi.create(),
|
||||
}),
|
||||
],
|
||||
[starredEntitiesApiRef, new MockStarredEntitiesApi()],
|
||||
]}
|
||||
>
|
||||
<EntityListProvider>
|
||||
|
||||
@@ -15,16 +15,18 @@
|
||||
*/
|
||||
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { StorageApi } from '@backstage/core-plugin-api';
|
||||
import { DefaultStarredEntitiesApi } from '@backstage/plugin-catalog';
|
||||
import { MockStorageApi, TestApiProvider } from '@backstage/test-utils';
|
||||
import { TestApiProvider } from '@backstage/test-utils';
|
||||
import { act, renderHook } from '@testing-library/react-hooks';
|
||||
import React, { PropsWithChildren } from 'react';
|
||||
import { starredEntitiesApiRef } from '../apis';
|
||||
import {
|
||||
starredEntitiesApiRef,
|
||||
StarredEntitiesApi,
|
||||
MockStarredEntitiesApi,
|
||||
} from '../apis';
|
||||
import { useStarredEntities } from './useStarredEntities';
|
||||
|
||||
describe('useStarredEntities', () => {
|
||||
let mockStorage: StorageApi;
|
||||
let mockApi: StarredEntitiesApi;
|
||||
let wrapper: React.ComponentType;
|
||||
|
||||
const mockEntity: Entity = {
|
||||
@@ -45,22 +47,15 @@ describe('useStarredEntities', () => {
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
mockStorage = MockStorageApi.create();
|
||||
mockApi = new MockStarredEntitiesApi();
|
||||
wrapper = ({ children }: PropsWithChildren<{}>) => (
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[
|
||||
starredEntitiesApiRef,
|
||||
new DefaultStarredEntitiesApi({ storageApi: mockStorage }),
|
||||
],
|
||||
]}
|
||||
>
|
||||
<TestApiProvider apis={[[starredEntitiesApiRef, mockApi]]}>
|
||||
{children}
|
||||
</TestApiProvider>
|
||||
);
|
||||
});
|
||||
|
||||
it('should return an empty set for when there is no items in storage', async () => {
|
||||
it('should return an empty set', async () => {
|
||||
const { result, waitForNextUpdate } = renderHook(
|
||||
() => useStarredEntities(),
|
||||
{ wrapper },
|
||||
@@ -71,10 +66,11 @@ describe('useStarredEntities', () => {
|
||||
expect(result.current.starredEntities.size).toBe(0);
|
||||
});
|
||||
|
||||
it('should return a set with the current items when there are items in storage', async () => {
|
||||
it('should return a set with the current items', async () => {
|
||||
const expectedIds = ['i', 'am', 'some', 'test', 'ids'];
|
||||
const store = mockStorage?.forBucket('starredEntities');
|
||||
await store?.set('entityRefs', expectedIds);
|
||||
for (const id of expectedIds) {
|
||||
mockApi.toggleStarred(id);
|
||||
}
|
||||
|
||||
const { result, waitForNextUpdate } = renderHook(
|
||||
() => useStarredEntities(),
|
||||
|
||||
@@ -31,6 +31,7 @@ import {
|
||||
catalogApiRef,
|
||||
entityRouteRef,
|
||||
starredEntitiesApiRef,
|
||||
MockStarredEntitiesApi,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import {
|
||||
mockBreakpoint,
|
||||
@@ -42,7 +43,6 @@ import {
|
||||
import DashboardIcon from '@material-ui/icons/Dashboard';
|
||||
import { fireEvent, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { DefaultStarredEntitiesApi } from '../../apis';
|
||||
import { createComponentRouteRef } from '../../routes';
|
||||
import { CatalogTableRow } from '../CatalogTable';
|
||||
import { DefaultCatalogPage } from './DefaultCatalogPage';
|
||||
@@ -141,10 +141,7 @@ describe('DefaultCatalogPage', () => {
|
||||
[catalogApiRef, catalogApi],
|
||||
[identityApiRef, identityApi],
|
||||
[storageApiRef, storageApi],
|
||||
[
|
||||
starredEntitiesApiRef,
|
||||
new DefaultStarredEntitiesApi({ storageApi }),
|
||||
],
|
||||
[starredEntitiesApiRef, new MockStarredEntitiesApi()],
|
||||
]}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -25,15 +25,11 @@ import {
|
||||
MockEntityListContextProvider,
|
||||
starredEntitiesApiRef,
|
||||
UserListFilter,
|
||||
MockStarredEntitiesApi,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import {
|
||||
MockStorageApi,
|
||||
renderInTestApp,
|
||||
TestApiRegistry,
|
||||
} from '@backstage/test-utils';
|
||||
import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils';
|
||||
import { act, fireEvent } from '@testing-library/react';
|
||||
import * as React from 'react';
|
||||
import { DefaultStarredEntitiesApi } from '../../apis';
|
||||
import { CatalogTable } from './CatalogTable';
|
||||
|
||||
const entities: Entity[] = [
|
||||
@@ -57,7 +53,7 @@ const entities: Entity[] = [
|
||||
describe('CatalogTable component', () => {
|
||||
const mockApis = TestApiRegistry.from([
|
||||
starredEntitiesApiRef,
|
||||
new DefaultStarredEntitiesApi({ storageApi: MockStorageApi.create() }),
|
||||
new MockStarredEntitiesApi(),
|
||||
]);
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -24,18 +24,17 @@ import {
|
||||
EntityProvider,
|
||||
entityRouteRef,
|
||||
starredEntitiesApiRef,
|
||||
MockStarredEntitiesApi,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import { permissionApiRef } from '@backstage/plugin-permission-react';
|
||||
import {
|
||||
MockPermissionApi,
|
||||
MockStorageApi,
|
||||
renderInTestApp,
|
||||
TestApiRegistry,
|
||||
} from '@backstage/test-utils';
|
||||
import { act, fireEvent } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { Route, Routes } from 'react-router';
|
||||
import { DefaultStarredEntitiesApi } from '../../apis';
|
||||
import { EntityLayout } from './EntityLayout';
|
||||
|
||||
const mockEntity = {
|
||||
@@ -48,10 +47,7 @@ const mockEntity = {
|
||||
const mockApis = TestApiRegistry.from(
|
||||
[catalogApiRef, {} as CatalogApi],
|
||||
[alertApiRef, {} as AlertApi],
|
||||
[
|
||||
starredEntitiesApiRef,
|
||||
new DefaultStarredEntitiesApi({ storageApi: MockStorageApi.create() }),
|
||||
],
|
||||
[starredEntitiesApiRef, new MockStarredEntitiesApi()],
|
||||
[permissionApiRef, new MockPermissionApi()],
|
||||
);
|
||||
|
||||
|
||||
@@ -13,40 +13,23 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import {
|
||||
renderInTestApp,
|
||||
TestApiProvider,
|
||||
MockStorageApi,
|
||||
} from '@backstage/test-utils';
|
||||
import { renderInTestApp, TestApiProvider } from '@backstage/test-utils';
|
||||
import {
|
||||
starredEntitiesApiRef,
|
||||
MockStarredEntitiesApi,
|
||||
entityRouteRef,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import { DefaultStarredEntitiesApi } from '@backstage/plugin-catalog';
|
||||
import React from 'react';
|
||||
import { Content } from './Content';
|
||||
|
||||
describe('StarredEntitiesContent', () => {
|
||||
it('should render list of tools', async () => {
|
||||
const mockStorageApi = MockStorageApi.create();
|
||||
await mockStorageApi
|
||||
.forBucket('starredEntities')
|
||||
.set('entityRefs', [
|
||||
'component:default/mock-starred-entity',
|
||||
'component:default/mock-starred-entity-2',
|
||||
]);
|
||||
const mockedApi = new MockStarredEntitiesApi();
|
||||
mockedApi.toggleStarred('component:default/mock-starred-entity');
|
||||
mockedApi.toggleStarred('component:default/mock-starred-entity-2');
|
||||
|
||||
const { getByText } = await renderInTestApp(
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[
|
||||
starredEntitiesApiRef,
|
||||
new DefaultStarredEntitiesApi({
|
||||
storageApi: mockStorageApi,
|
||||
}),
|
||||
],
|
||||
]}
|
||||
>
|
||||
<TestApiProvider apis={[[starredEntitiesApiRef, mockedApi]]}>
|
||||
<Content />
|
||||
</TestApiProvider>,
|
||||
{
|
||||
|
||||
@@ -22,9 +22,9 @@ import {
|
||||
} from '@backstage/test-utils';
|
||||
import {
|
||||
starredEntitiesApiRef,
|
||||
MockStarredEntitiesApi,
|
||||
entityRouteRef,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import { DefaultStarredEntitiesApi } from '@backstage/plugin-catalog';
|
||||
import { Grid } from '@material-ui/core';
|
||||
import React, { ComponentType } from 'react';
|
||||
|
||||
@@ -44,14 +44,7 @@ export default {
|
||||
(Story: ComponentType<{}>) =>
|
||||
wrapInTestApp(
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[
|
||||
starredEntitiesApiRef,
|
||||
new DefaultStarredEntitiesApi({
|
||||
storageApi: mockStorageApi,
|
||||
}),
|
||||
],
|
||||
]}
|
||||
apis={[[starredEntitiesApiRef, new MockStarredEntitiesApi()]]}
|
||||
>
|
||||
<Story />
|
||||
</TestApiProvider>,
|
||||
|
||||
@@ -25,9 +25,9 @@ import { wrapInTestApp, TestApiProvider, MockStorageApi} from '@backstage/test-u
|
||||
import { Content, Page, InfoCard } from '@backstage/core-components';
|
||||
import {
|
||||
starredEntitiesApiRef,
|
||||
MockStarredEntitiesApi,
|
||||
entityRouteRef,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import { DefaultStarredEntitiesApi } from '@backstage/plugin-catalog';
|
||||
import {
|
||||
HomePageSearchBar,
|
||||
SearchContextProvider,
|
||||
@@ -57,9 +57,7 @@ export default {
|
||||
apis={[
|
||||
[
|
||||
starredEntitiesApiRef,
|
||||
new DefaultStarredEntitiesApi({
|
||||
storageApi: mockStorageApi,
|
||||
}),
|
||||
new MockStarredEntitiesApi(),
|
||||
],
|
||||
[searchApiRef, { query: () => Promise.resolve({ results: [] }) }],
|
||||
]}
|
||||
|
||||
@@ -20,19 +20,13 @@ import { scmIntegrationsApiRef } from '@backstage/integration-react';
|
||||
import {
|
||||
catalogApiRef,
|
||||
starredEntitiesApiRef,
|
||||
MockStarredEntitiesApi,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import React from 'react';
|
||||
import { scaffolderApiRef, ScaffolderClient } from '../src';
|
||||
import { ScaffolderPage } from '../src/plugin';
|
||||
import {
|
||||
discoveryApiRef,
|
||||
fetchApiRef,
|
||||
storageApiRef,
|
||||
} from '@backstage/core-plugin-api';
|
||||
import {
|
||||
CatalogEntityPage,
|
||||
DefaultStarredEntitiesApi,
|
||||
} from '@backstage/plugin-catalog';
|
||||
import { discoveryApiRef, fetchApiRef } from '@backstage/core-plugin-api';
|
||||
import { CatalogEntityPage } from '@backstage/plugin-catalog';
|
||||
|
||||
createDevApp()
|
||||
.addPage({
|
||||
@@ -46,8 +40,8 @@ createDevApp()
|
||||
})
|
||||
.registerApi({
|
||||
api: starredEntitiesApiRef,
|
||||
deps: { storageApi: storageApiRef },
|
||||
factory: ({ storageApi }) => new DefaultStarredEntitiesApi({ storageApi }),
|
||||
deps: {},
|
||||
factory: () => new MockStarredEntitiesApi(),
|
||||
})
|
||||
.registerApi({
|
||||
api: scaffolderApiRef,
|
||||
|
||||
@@ -20,11 +20,11 @@ import {
|
||||
configApiRef,
|
||||
storageApiRef,
|
||||
} from '@backstage/core-plugin-api';
|
||||
import { DefaultStarredEntitiesApi } from '@backstage/plugin-catalog';
|
||||
import {
|
||||
CatalogApi,
|
||||
catalogApiRef,
|
||||
starredEntitiesApiRef,
|
||||
MockStarredEntitiesApi,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import {
|
||||
MockStorageApi,
|
||||
@@ -73,7 +73,7 @@ describe('TechDocs Home', () => {
|
||||
[catalogApiRef, mockCatalogApi],
|
||||
[configApiRef, configApi],
|
||||
[storageApiRef, storageApi],
|
||||
[starredEntitiesApiRef, new DefaultStarredEntitiesApi({ storageApi })],
|
||||
[starredEntitiesApiRef, new MockStarredEntitiesApi()],
|
||||
);
|
||||
|
||||
it('should render a TechDocs home page', async () => {
|
||||
|
||||
Reference in New Issue
Block a user