fix api reports + create StaticExploreToolProvider

Signed-off-by: Andrew Thauer <athauer@wealthsimple.com>
This commit is contained in:
Andrew Thauer
2022-11-11 07:14:43 -05:00
parent 3eaa4bdfbc
commit ce34320d91
16 changed files with 200 additions and 24 deletions
+8
View File
@@ -32,6 +32,14 @@ export interface RouterOptions {
toolProvider: ExploreToolProvider;
}
// @public
export class StaticExploreToolProvider implements ExploreToolProvider {
// (undocumented)
static fromData(tools: ExploreTool[]): StaticExploreToolProvider;
// (undocumented)
getTools(request: GetExploreToolsRequest): Promise<GetExploreToolsResponse>;
}
// @public
export interface ToolDocument extends IndexableDocument, ExploreTool {}
+2 -1
View File
@@ -22,8 +22,9 @@
export * from './search';
export * from './service';
export * from './tools';
/**
* @internal Example only - do not use in production
*/
export { getExampleTools } from './example/getExampleTools';
export { exampleTools } from './example/exampleTools';
@@ -16,4 +16,3 @@
export { createRouter } from './router';
export type { RouterOptions } from './router';
export * from './types';
@@ -21,9 +21,8 @@ import {
} from '@backstage/plugin-explore-common';
import express from 'express';
import request from 'supertest';
import { ExploreToolProvider } from '../tools';
import { createRouter } from './router';
import { ExploreToolProvider } from './types';
const mockTools: ExploreTool[] = [
{ title: 'Tool 1', url: 'https://example.com/tool1', image: '' },
@@ -19,7 +19,7 @@ import { GetExploreToolsRequest } from '@backstage/plugin-explore-common';
import express from 'express';
import Router from 'express-promise-router';
import { Logger } from 'winston';
import { ExploreToolProvider } from './types';
import { ExploreToolProvider } from '../tools';
/**
* @public
@@ -0,0 +1,18 @@
/*
* Copyright 2022 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.
*/
export { StaticExploreToolProvider } from './providers';
export type { ExploreToolProvider } from './types';
@@ -0,0 +1,85 @@
/*
* Copyright 2022 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 { ExploreTool } from '@backstage/plugin-explore-common';
import { StaticExploreToolProvider } from './providers';
describe('StaticExploreToolProvider', () => {
const tool1: ExploreTool = {
title: 'Tool 1',
image: 'https://example/image.png',
url: 'https://example.com',
lifecycle: 'production',
tags: ['tag1', 'tag2'],
};
const tool2: ExploreTool = {
...tool1,
title: 'Tool 2',
lifecycle: 'production',
tags: ['tag1'],
};
const tool3: ExploreTool = {
...tool1,
title: 'Tool 3',
lifecycle: 'experimental',
tags: ['tag2'],
};
const allTools: ExploreTool[] = [tool1, tool2, tool3];
describe('getTools', () => {
it('returns a list of all tools', async () => {
const provider = StaticExploreToolProvider.fromData(allTools);
await expect(provider.getTools({})).resolves.toEqual({
tools: allTools,
});
});
it.each([
[['tag1'], [tool1, tool2]],
[['tag2'], [tool1, tool3]],
[[], allTools],
])(
'returns % when filtered by tags %',
async (tagFilter, expectedTools) => {
const provider = StaticExploreToolProvider.fromData(allTools);
await expect(
provider.getTools({ filter: { tags: tagFilter } }),
).resolves.toEqual({
tools: expectedTools,
});
},
);
it.each([
[['production'], [tool1, tool2]],
[['experimental'], [tool3]],
[[], allTools],
])(
'returns % when filtered by lifecycle %',
async (lifecycleFilter, expectedTools) => {
const provider = StaticExploreToolProvider.fromData(allTools);
await expect(
provider.getTools({ filter: { lifecycle: lifecycleFilter } }),
).resolves.toEqual({
tools: expectedTools,
});
},
);
});
});
@@ -1,5 +1,5 @@
/*
* Copyright 2020 The Backstage Authors
* Copyright 2022 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.
@@ -15,11 +15,12 @@
*/
import {
ExploreTool,
GetExploreToolsRequest,
GetExploreToolsResponse,
} from '@backstage/plugin-explore-common';
import { intersection, isEmpty } from 'lodash';
import { exampleTools } from './tools';
import { ExploreToolProvider } from './types';
const anyOf = <T>(prop: T | T[], matches: T[]) =>
isEmpty(matches)
@@ -27,18 +28,32 @@ const anyOf = <T>(prop: T | T[], matches: T[]) =>
: intersection([...[prop]].flat(), matches)?.length > 0;
/**
* @private Example only - do not use in production
* A basic ExploreToolProvider implementation using static data.
*
* @public
*/
export async function getExampleTools(
request: GetExploreToolsRequest,
): Promise<GetExploreToolsResponse> {
const { filter } = request ?? {};
const tags = filter?.tags ?? [];
const lifecycles = filter?.lifecycle ?? [];
export class StaticExploreToolProvider implements ExploreToolProvider {
private readonly tools: ExploreTool[];
return {
tools: exampleTools.filter(
static fromData(tools: ExploreTool[]) {
return new StaticExploreToolProvider(tools);
}
private constructor(tools: ExploreTool[]) {
this.tools = tools;
}
async getTools(
request: GetExploreToolsRequest,
): Promise<GetExploreToolsResponse> {
const { filter } = request ?? {};
const tags = filter?.tags ?? [];
const lifecycles = filter?.lifecycle ?? [];
const tools = this.tools.filter(
t => anyOf(t.tags ?? [], tags) && anyOf(t.lifecycle ?? [], lifecycles),
),
};
);
return { tools };
}
}