fix: move webUrl construction into the st2 client

Signed-off-by: pamelin <pamelin@expediagroup.com>
This commit is contained in:
pamelin
2023-02-16 11:47:09 +00:00
parent 83e8387391
commit 9c53ca52ec
10 changed files with 89 additions and 61 deletions
+2 -2
View File
@@ -14,12 +14,12 @@
* limitations under the License.
*/
export interface Config {
stackstorm?: {
stackstorm: {
/**
* StackStorm Web UI url
* Used in links to StackStorm web UI
* @visibility frontend
*/
webUrl?: string;
webUrl: string;
};
}
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { UrlPatternDiscovery } from '@backstage/core-app-api';
import { ConfigReader, UrlPatternDiscovery } from '@backstage/core-app-api';
import { MockFetchApi, setupRequestMockHandlers } from '@backstage/test-utils';
import { rest } from 'msw';
import { setupServer } from 'msw/node';
@@ -177,31 +177,50 @@ describe('StackstormClient', () => {
beforeEach(() => {
setupHandlers();
client = new StackstormClient({
discoveryApi: discoveryApi,
fetchApi: new MockFetchApi(),
});
client = StackstormClient.fromConfig(
new ConfigReader({
stackstorm: {
webUrl: 'http://stackstorm.example.com:8080',
},
}),
{
discoveryApi: discoveryApi,
fetchApi: new MockFetchApi(),
},
);
});
it('get executions should return executions with emulated pagination', async () => {
it('getExecutions should return executions with emulated pagination', async () => {
const got = await client.getExecutions(2, 1);
expect(got.length).toEqual(2);
expect(got).toMatchObject(executions.slice(1, 3));
});
it('get execution should return one execution', async () => {
it('getExecution should return one execution', async () => {
const got = await client.getExecution('63dcac3e18ba00e09e7bb3b6');
expect(got).toMatchObject(executionWithDetails);
});
it('get packs should return list of all packs', async () => {
it('getPacks should return list of all packs', async () => {
const got = await client.getPacks();
expect(got.length).toEqual(packs.length);
expect(got).toMatchObject(packs);
});
it('get actions should return list of actions', async () => {
it('getActions should return list of actions', async () => {
const got = await client.getActions('core');
expect(got).toMatchObject(actions);
});
it('getExecutionHistoryUrl should return webUrl for executions', async () => {
const got = client.getExecutionHistoryUrl('123abc');
expect(got).toEqual('http://stackstorm.example.com:8080/?#/history/123abc');
});
it('getActionUrl should return webUrl for action', async () => {
const got = client.getActionUrl('core.shell');
expect(got).toEqual(
'http://stackstorm.example.com:8080/?#/actions/core.shell',
);
});
});
+28 -2
View File
@@ -14,21 +14,39 @@
* limitations under the License.
*/
import { Action, Execution, Pack, StackstormApi } from './types';
import { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api';
import { ConfigApi, DiscoveryApi, FetchApi } from '@backstage/core-plugin-api';
export class StackstormClient implements StackstormApi {
private readonly discoveryApi: DiscoveryApi;
private readonly fetchApi: FetchApi;
private readonly webUrl: string;
constructor({
private constructor({
discoveryApi,
fetchApi,
webUrl,
}: {
discoveryApi: DiscoveryApi;
fetchApi: FetchApi;
webUrl: string;
}) {
this.discoveryApi = discoveryApi;
this.fetchApi = fetchApi;
this.webUrl = webUrl;
}
static fromConfig(
config: ConfigApi,
dependencies: {
discoveryApi: DiscoveryApi;
fetchApi: FetchApi;
},
): StackstormClient {
return new StackstormClient({
discoveryApi: dependencies.discoveryApi,
fetchApi: dependencies.fetchApi,
webUrl: config.getString('stackstorm.webUrl'),
});
}
private async get<T = any>(input: string): Promise<T> {
@@ -87,4 +105,12 @@ export class StackstormClient implements StackstormApi {
const path = `/actions?${new URLSearchParams(params)}`;
return this.get<Action[]>(path);
}
getExecutionHistoryUrl(id: string): string {
return `${this.webUrl}/?#/history/${id}`;
}
getActionUrl(ref: string): string {
return `${this.webUrl}/?#/actions/${ref}`;
}
}
+2
View File
@@ -56,4 +56,6 @@ export interface StackstormApi {
getExecution(id: string): Promise<Execution>;
getPacks(): Promise<Pack[]>;
getActions(pack: string): Promise<Action[]>;
getExecutionHistoryUrl(id: string): string;
getActionUrl(ref: string): string;
}
@@ -16,7 +16,7 @@
import React, { useState } from 'react';
import useAsync from 'react-use/lib/useAsync';
import { Progress } from '@backstage/core-components';
import { useApi, configApiRef } from '@backstage/core-plugin-api';
import { useApi } from '@backstage/core-plugin-api';
import {
List,
ListItemText,
@@ -55,7 +55,6 @@ type ActionItemsProps = {
export const ActionItems = ({ pack }: ActionItemsProps) => {
const classes = useStyles();
const st2 = useApi(stackstormApiRef);
const config = useApi(configApiRef);
const { value, loading, error } = useAsync(async (): Promise<Action[]> => {
const data = await st2.getActions(pack.ref);
@@ -76,12 +75,7 @@ export const ActionItems = ({ pack }: ActionItemsProps) => {
key={a.ref}
button
className={classes.nested}
onClick={() =>
window.open(
`${config.getString('stackstorm.webUrl')}/?#/actions/${a.ref}`,
'_blank',
)
}
onClick={() => window.open(st2.getActionUrl(a.ref), '_blank')}
>
<ListItemText primary={a.name} secondary={a.description} />
<ListItemSecondaryAction>{a.runner_type}</ListItemSecondaryAction>
@@ -13,12 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { configApiRef } from '@backstage/core-plugin-api';
import {
MockConfigApi,
renderInTestApp,
TestApiProvider,
} from '@backstage/test-utils';
import { renderInTestApp, TestApiProvider } from '@backstage/test-utils';
import React from 'react';
import { Execution, StackstormApi, stackstormApiRef } from '../../api';
import { ExecutionPanel } from './ExecutionPanel';
@@ -54,19 +49,16 @@ const execution: Execution = {
describe('ExecutionPanel', () => {
const mockApi: jest.Mocked<StackstormApi> = {
getExecution: jest.fn().mockResolvedValue(execution),
getExecutionHistoryUrl: jest
.fn()
.mockResolvedValue(
'http://stackstorm.example.com:8080/?#/history/63dcac3e18ba00e09e7bb3b6',
),
} as any;
it('should render execution details', async () => {
const { getByText } = await renderInTestApp(
<TestApiProvider
apis={[
[stackstormApiRef, mockApi],
[
configApiRef,
new MockConfigApi({ stackstorm: { webUrl: 'http://localhost' } }),
],
]}
>
<TestApiProvider apis={[[stackstormApiRef, mockApi]]}>
<ExecutionPanel id="63dcac3e18ba00e09e7bb3b6" />
</TestApiProvider>,
);
@@ -15,7 +15,7 @@
*/
import React from 'react';
import { CodeSnippet, Progress } from '@backstage/core-components';
import { configApiRef, useApi } from '@backstage/core-plugin-api';
import { useApi } from '@backstage/core-plugin-api';
import { Execution, stackstormApiRef } from '../../api';
import useAsync from 'react-use/lib/useAsync';
import { Alert } from '@material-ui/lab';
@@ -65,11 +65,9 @@ const TRow = withStyles(theme => ({
}))(TableRow);
const ExecutionCard = ({ e }: { e: Execution }) => {
const config = useApi(configApiRef);
const st2 = useApi(stackstormApiRef);
const classes = useStyles();
const webUrl = `${config.getString('stackstorm.webUrl')}/?#/history/${e.id}`;
return (
<Card className={classes.card}>
<CardContent>
@@ -139,7 +137,11 @@ const ExecutionCard = ({ e }: { e: Execution }) => {
/>
</CardContent>
<CardActions>
<Button size="small" href={webUrl} target="_blank">
<Button
size="small"
href={`${st2.getExecutionHistoryUrl(e.id)}`}
target="_blank"
>
View in ST2
</Button>
</CardActions>
@@ -83,19 +83,16 @@ const executions: Execution[] = [
describe('ExecutionsTable', () => {
const mockApi: jest.Mocked<StackstormApi> = {
getExecutions: jest.fn().mockResolvedValue(executions),
getExecutionHistoryUrl: jest
.fn()
.mockResolvedValue(
'http://stackstorm.example.com:8080/?#/history/123abc',
),
} as any;
it('should render all executions', async () => {
const { getByText } = await renderInTestApp(
<TestApiProvider
apis={[
[stackstormApiRef, mockApi],
[
configApiRef,
new MockConfigApi({ stackstorm: { webUrl: 'http://localhost' } }),
],
]}
>
<TestApiProvider apis={[[stackstormApiRef, mockApi]]}>
<ExecutionsTable />
</TestApiProvider>,
);
@@ -15,7 +15,7 @@
*/
import React, { useEffect, useState } from 'react';
import { Link, Table, TableColumn } from '@backstage/core-components';
import { useApi, configApiRef, errorApiRef } from '@backstage/core-plugin-api';
import { useApi, errorApiRef } from '@backstage/core-plugin-api';
import { Execution, stackstormApiRef } from '../../api';
import { Status } from './Status';
import { ExecutionPanel } from './ExecutionPanel';
@@ -37,7 +37,7 @@ export const DenseTable = ({
onPageChange,
onRowsPerPageChange,
}: DenseTableProps) => {
const config = useApi(configApiRef);
const st2 = useApi(stackstormApiRef);
const columns: TableColumn<Execution>[] = [
{
@@ -54,13 +54,7 @@ export const DenseTable = ({
{
title: 'Execution ID',
field: 'id',
render: e => (
<Link
to={`${config.getString('stackstorm.webUrl')}/?#/history/${e.id}`}
>
{e.id}
</Link>
),
render: e => <Link to={st2.getExecutionHistoryUrl(e.id)}>{e.id}</Link>,
},
];
+4 -2
View File
@@ -15,6 +15,7 @@
*/
import {
configApiRef,
createApiFactory,
createPlugin,
createRoutableExtension,
@@ -35,11 +36,12 @@ export const stackstormPlugin = createPlugin({
createApiFactory({
api: stackstormApiRef,
deps: {
configApi: configApiRef,
discoveryApi: discoveryApiRef,
fetchApi: fetchApiRef,
},
factory: ({ discoveryApi, fetchApi }) =>
new StackstormClient({
factory: ({ configApi, discoveryApi, fetchApi }) =>
StackstormClient.fromConfig(configApi, {
discoveryApi,
fetchApi,
}),