diff --git a/plugins/puppetdb/src/api/PupeptDbClient.test.ts b/plugins/puppetdb/src/api/PupeptDbClient.test.ts new file mode 100644 index 0000000000..8b858e21ca --- /dev/null +++ b/plugins/puppetdb/src/api/PupeptDbClient.test.ts @@ -0,0 +1,206 @@ +/* + * 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 { UrlPatternDiscovery } from '@backstage/core-app-api'; +import { MockFetchApi, setupRequestMockHandlers } from '@backstage/test-utils'; +import { rest } from 'msw'; +import { setupServer } from 'msw/node'; +import { PuppetDbClient } from './PuppetDbClient'; +import { + PuppetDbReport, + PuppetDbReportEvent, + PuppetDbReportLog, +} from './types'; + +const server = setupServer(); + +const reports: PuppetDbReport[] = [ + { + hash: 'hash1', + puppet_version: 'version1', + report_format: 1, + certname: 'node1', + start_time: '2021-01-01T00:00:00Z', + end_time: '2021-01-01T00:00:00Z', + producer_timestamp: '2021-01-01T00:00:00Z', + receive_time: '2021-01-01T00:00:00Z', + producer: 'producer1', + transaction_uuid: 'uuid1', + catalog_uuid: 'uuid1', + code_id: 'id1', + cached_catalog_status: 'status1', + type: 'type1', + corrective_change: false, + configuration_version: 'version1', + environment: 'production', + noop: false, + status: 'changed', + }, + { + hash: 'hash2', + puppet_version: 'version2', + report_format: 2, + certname: 'node1', + start_time: '2021-01-01T00:00:00Z', + end_time: '2021-01-01T00:00:00Z', + producer_timestamp: '2021-01-01T00:00:00Z', + receive_time: '2021-01-01T00:00:00Z', + producer: 'producer2', + transaction_uuid: 'uuid2', + catalog_uuid: 'uuid2', + code_id: 'id2', + cached_catalog_status: 'status2', + type: 'type2', + corrective_change: false, + configuration_version: 'version2', + environment: 'production', + noop: false, + status: 'failed', + }, +]; + +const events: PuppetDbReportEvent[] = [ + { + name: 'event1', + message: 'message1', + file: 'file1', + line: 1, + certname: 'node1', + report: 'hash1', + timestamp: '2021-01-01T00:00:00Z', + report_receive_time: '2021-01-01T00:00:00Z', + run_start_time: '2021-01-01T00:00:00Z', + containing_class: 'class1', + environment: 'production', + configuration_version: 'version1', + containment_path: ['path1'], + corrective_change: false, + run_end_time: '2021-01-01T00:00:00Z', + resource_type: 'type1', + resource_title: 'title1', + property: 'property1', + old_value: 'old1', + new_value: 'new1', + status: 'changed', + }, + { + name: 'event2', + message: 'message2', + file: 'file2', + line: 2, + certname: 'node1', + report: 'hash1', + timestamp: '2021-01-01T00:00:00Z', + report_receive_time: '2021-01-01T00:00:00Z', + run_start_time: '2021-01-01T00:00:00Z', + containing_class: 'class2', + environment: 'production', + configuration_version: 'version2', + containment_path: ['path2'], + corrective_change: false, + run_end_time: '2021-01-01T00:00:00Z', + resource_type: 'type2', + resource_title: 'title2', + property: 'property2', + old_value: 'old2', + new_value: 'new2', + status: 'failed', + }, +]; + +const logs: PuppetDbReportLog[] = [ + { + level: 'level1', + file: 'file1', + line: 1, + time: '2021-01-01T00:00:00Z', + message: 'message1', + source: 'source1', + tags: ['tag1'], + }, + { + level: 'level2', + file: 'file2', + line: 2, + time: '2021-01-01T00:00:00Z', + message: 'message2', + source: 'source2', + tags: ['tag2'], + }, +]; + +describe('PuppetDbClient', () => { + setupRequestMockHandlers(server); + + const puppetDbCertName = 'node1'; + const mockBaseUrl = 'http://backstage:9191/api/proxy'; + const discoveryApi = UrlPatternDiscovery.compile(mockBaseUrl); + let client: PuppetDbClient; + + const setupHandlers = () => { + server.use( + rest.get( + `${mockBaseUrl}/puppetdb/pdb/query/v4/reports`, + (req, res, ctx) => { + if ( + req.url.searchParams.get('query') !== + `["=","certname","${puppetDbCertName}"]` + ) { + return res(ctx.status(400)); + } + + return res(ctx.status(200), ctx.json(reports)); + }, + ), + + rest.get( + `${mockBaseUrl}/puppetdb/pdb/query/v4/reports/hash1/events`, + (_, res, ctx) => { + return res(ctx.status(200), ctx.json(events)); + }, + ), + + rest.get( + `${mockBaseUrl}/puppetdb/pdb/query/v4/reports/hash1/logs`, + (_, res, ctx) => { + return res(ctx.status(200), ctx.json(logs)); + }, + ), + ); + }; + + beforeEach(() => { + setupHandlers(); + client = new PuppetDbClient({ + discoveryApi: discoveryApi, + fetchApi: new MockFetchApi(), + }); + }); + + it('getPuppetDbNodeReports should return reports', async () => { + const got = await client.getPuppetDbNodeReports(puppetDbCertName); + expect(got).toEqual(reports); + }); + + it('getPuppetDbReportEvents should return events', async () => { + const got = await client.getPuppetDbReportEvents('hash1'); + expect(got).toEqual(events); + }); + + it('getPuppetDbReportLogs should return logs', async () => { + const got = await client.getPuppetDbReportLogs('hash1'); + expect(got).toEqual(logs); + }); +}); diff --git a/plugins/puppetdb/src/api/PuppetDbClient.ts b/plugins/puppetdb/src/api/PuppetDbClient.ts index f97270b5ca..b8f3c6e404 100644 --- a/plugins/puppetdb/src/api/PuppetDbClient.ts +++ b/plugins/puppetdb/src/api/PuppetDbClient.ts @@ -56,24 +56,6 @@ export class PuppetDbClient implements PuppetDbApi { throw await ResponseError.fromResponse(response); } - async getPuppetDbReport( - puppetDbReportHash: string, - ): Promise { - if (!puppetDbReportHash) { - throw new Error('PuppetDB report hash is required'); - } - - const reports = (await this.callApi(`/pdb/query/v4/reports`, { - query: `["=","hash","${puppetDbReportHash}"]`, - })) as PuppetDbReport[]; - - if (!reports || reports.length === 0) { - return undefined; - } - - return reports[0]; - } - async getPuppetDbReportEvents( puppetDbReportHash: string, ): Promise { diff --git a/plugins/puppetdb/src/api/index.ts b/plugins/puppetdb/src/api/index.ts index 46d34a8811..a21728431d 100644 --- a/plugins/puppetdb/src/api/index.ts +++ b/plugins/puppetdb/src/api/index.ts @@ -13,6 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export type { PuppetDbReport, PuppetDbReportEvent } from './types'; +export type { + PuppetDbReport, + PuppetDbReportEvent, + PuppetDbReportLog, +} from './types'; export { puppetDbApiRef } from './types'; export { PuppetDbClient } from './PuppetDbClient'; diff --git a/plugins/puppetdb/src/api/types.ts b/plugins/puppetdb/src/api/types.ts index 7fb132e813..469abd65b2 100644 --- a/plugins/puppetdb/src/api/types.ts +++ b/plugins/puppetdb/src/api/types.ts @@ -62,7 +62,7 @@ export type PuppetDbReport = { /** A flag indicating whether any of the report's events remediated configuration drift. */ corrective_change: boolean; /** Report metrics. */ - metrics: { + metrics?: { /** Metrics data. */ data: PuppetDbReportMetric[]; /** Link to the metrics endpoint. */ @@ -176,16 +176,6 @@ export type PuppetDbApi = { puppetDbCertName: string, ): Promise; - /** - * Get a specific PuppetDB report. - * - * @param puppetDbReportHash - The ID of the report. - * @returns A specific PuppetDB report. - */ - getPuppetDbReport( - puppetDbReportHash: string, - ): Promise; - /** * Get a specific PuppetDB report events. * diff --git a/plugins/puppetdb/src/components/ReportDetailsPage/ReportDetailsEventsTable.test.tsx b/plugins/puppetdb/src/components/ReportDetailsPage/ReportDetailsEventsTable.test.tsx new file mode 100644 index 0000000000..31775014f2 --- /dev/null +++ b/plugins/puppetdb/src/components/ReportDetailsPage/ReportDetailsEventsTable.test.tsx @@ -0,0 +1,105 @@ +/* + * Copyright 2020 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 React from 'react'; +import { ReportDetailsEventsTable } from './ReportDetailsEventsTable'; +import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; +import { puppetDbApiRef, PuppetDbReportEvent } from '../../api'; +import { PuppetDbClient } from '../../api'; +import { ApiProvider } from '@backstage/core-app-api'; +import { puppetDbRouteRef } from '../../routes'; + +const events: PuppetDbReportEvent[] = [ + { + name: 'event3', + message: 'message1', + file: 'file1', + line: 1, + certname: 'node1', + report: 'hash1', + timestamp: '2021-01-01T00:00:00Z', + report_receive_time: '2021-01-01T00:00:00Z', + run_start_time: '2021-01-01T00:00:00Z', + containing_class: 'class1', + environment: 'production', + configuration_version: 'version1', + containment_path: ['path1'], + corrective_change: false, + run_end_time: '2021-01-01T00:00:00Z', + resource_type: 'type1', + resource_title: 'title1', + property: 'property1', + old_value: 'old1', + new_value: 'new1', + status: 'changed', + }, + { + name: 'event2', + message: 'message2', + file: 'file2', + line: 2, + certname: 'node1', + report: 'hash1', + timestamp: '2021-01-01T00:00:00Z', + report_receive_time: '2021-01-01T00:00:00Z', + run_start_time: '2021-01-01T00:00:00Z', + containing_class: 'class2', + environment: 'production', + configuration_version: 'version2', + containment_path: ['path2'], + corrective_change: false, + run_end_time: '2021-01-01T00:00:00Z', + resource_type: 'type2', + resource_title: 'title2', + property: 'property2', + old_value: 'old2', + new_value: 'new2', + status: 'failed', + }, +]; + +const mockPuppetDbApi: Partial = { + getPuppetDbReportEvents: async () => events, +}; + +const apis = TestApiRegistry.from([puppetDbApiRef, mockPuppetDbApi]); + +const hash = 'hash'; + +describe('ReportEventsTable', () => { + it('should render', async () => { + const render = await renderInTestApp( + + + , + { + mountedRoutes: { + '/puppetdb/report/:hash': puppetDbRouteRef, + }, + }, + ); + + expect(render.getByText('Latest events')).toBeInTheDocument(); + expect(render.getByText('Containing Class')).toBeInTheDocument(); + expect(render.getByText('Resource')).toBeInTheDocument(); + expect(render.getByText('Property')).toBeInTheDocument(); + expect(render.getByText('Old Value')).toBeInTheDocument(); + expect(render.getByText('New Value')).toBeInTheDocument(); + expect(render.getByText('Status')).toBeInTheDocument(); + expect(render.getByText('property2')).toBeInTheDocument(); + expect(render.getByText('old1')).toBeInTheDocument(); + expect(render.getByText('old2')).toBeInTheDocument(); + }); +}); diff --git a/plugins/puppetdb/src/components/ReportDetailsPage/ReportDetailsEventsTable.tsx b/plugins/puppetdb/src/components/ReportDetailsPage/ReportDetailsEventsTable.tsx index 57bcf1caf3..b7f5b3c436 100644 --- a/plugins/puppetdb/src/components/ReportDetailsPage/ReportDetailsEventsTable.tsx +++ b/plugins/puppetdb/src/components/ReportDetailsPage/ReportDetailsEventsTable.tsx @@ -15,13 +15,12 @@ */ import Typography from '@material-ui/core/Typography'; import React from 'react'; -import { puppetDbApiRef } from '../../api'; +import { puppetDbApiRef, PuppetDbReportEvent } from '../../api'; import { ResponseErrorPanel, Table, TableColumn, } from '@backstage/core-components'; -import { PuppetDbReportEvent } from '../../api/types'; import useAsync from 'react-use/lib/useAsync'; import { useApi } from '@backstage/core-plugin-api'; import { makeStyles } from '@material-ui/core/styles'; diff --git a/plugins/puppetdb/src/components/ReportDetailsPage/ReportDetailsLogsTable.test.tsx b/plugins/puppetdb/src/components/ReportDetailsPage/ReportDetailsLogsTable.test.tsx new file mode 100644 index 0000000000..2d9d973412 --- /dev/null +++ b/plugins/puppetdb/src/components/ReportDetailsPage/ReportDetailsLogsTable.test.tsx @@ -0,0 +1,74 @@ +/* + * Copyright 2020 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 React from 'react'; +import { ReportDetailsLogsTable } from './ReportDetailsLogsTable'; +import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; +import { puppetDbApiRef, PuppetDbReportLog } from '../../api'; +import { PuppetDbClient } from '../../api'; +import { ApiProvider } from '@backstage/core-app-api'; +import { puppetDbRouteRef } from '../../routes'; + +const logs: PuppetDbReportLog[] = [ + { + level: 'level1', + file: 'file1', + line: 1, + time: '2021-01-01T00:00:00Z', + message: 'message1', + source: 'source1', + tags: ['tag1'], + }, + { + level: 'level2', + file: 'file2', + line: 2, + time: '2021-01-01T00:00:00Z', + message: 'message2', + source: 'source2', + tags: ['tag2'], + }, +]; + +const mockPuppetDbApi: Partial = { + getPuppetDbReportLogs: async () => logs, +}; + +const apis = TestApiRegistry.from([puppetDbApiRef, mockPuppetDbApi]); + +const hash = 'hash'; + +describe('ReportLogsTable', () => { + it('should render', async () => { + const render = await renderInTestApp( + + + , + { + mountedRoutes: { + '/puppetdb/report/:hash': puppetDbRouteRef, + }, + }, + ); + + expect(render.getByText('Latest logs')).toBeInTheDocument(); + expect(render.getByText('Level')).toBeInTheDocument(); + expect(render.getByText('Timestamp')).toBeInTheDocument(); + expect(render.getByText('Source')).toBeInTheDocument(); + expect(render.getByText('Message')).toBeInTheDocument(); + expect(render.getByText('source1')).toBeInTheDocument(); + expect(render.getByText('source2')).toBeInTheDocument(); + }); +}); diff --git a/plugins/puppetdb/src/components/ReportDetailsPage/ReportDetailsLogsTable.tsx b/plugins/puppetdb/src/components/ReportDetailsPage/ReportDetailsLogsTable.tsx index 587cf4fffe..f512fcd935 100644 --- a/plugins/puppetdb/src/components/ReportDetailsPage/ReportDetailsLogsTable.tsx +++ b/plugins/puppetdb/src/components/ReportDetailsPage/ReportDetailsLogsTable.tsx @@ -15,13 +15,12 @@ */ import Typography from '@material-ui/core/Typography'; import React from 'react'; -import { puppetDbApiRef } from '../../api'; +import { puppetDbApiRef, PuppetDbReportLog } from '../../api'; import { ResponseErrorPanel, Table, TableColumn, } from '@backstage/core-components'; -import { PuppetDbReportLog } from '../../api/types'; import useAsync from 'react-use/lib/useAsync'; import { useApi } from '@backstage/core-plugin-api'; import { makeStyles } from '@material-ui/core/styles'; diff --git a/plugins/puppetdb/src/components/ReportDetailsPage/ReportDetailsPage.test.tsx b/plugins/puppetdb/src/components/ReportDetailsPage/ReportDetailsPage.test.tsx new file mode 100644 index 0000000000..e6ade0e596 --- /dev/null +++ b/plugins/puppetdb/src/components/ReportDetailsPage/ReportDetailsPage.test.tsx @@ -0,0 +1,45 @@ +/* + * Copyright 2020 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 React from 'react'; +import { ReportDetailsPage } from './ReportDetailsPage'; +import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; +import { puppetDbRouteRef } from '../../routes'; +import { puppetDbApiRef, PuppetDbClient } from '../../api'; +import { ApiProvider } from '@backstage/core-app-api'; + +const mockPuppetDbApi: Partial = { + getPuppetDbReportEvents: async () => [], +}; + +const apis = TestApiRegistry.from([puppetDbApiRef, mockPuppetDbApi]); + +describe('ReportDetailsPage', () => { + it('should render', async () => { + const render = await renderInTestApp( + + + , + { + mountedRoutes: { + '/puppetdb/report': puppetDbRouteRef, + }, + }, + ); + expect(render.getByText('PuppetDB Reports')).toBeInTheDocument(); + expect(render.getByText('Events')).toBeInTheDocument(); + expect(render.getByText('Logs')).toBeInTheDocument(); + }); +}); diff --git a/plugins/puppetdb/src/components/ReportsPage/ReportsPage.test.tsx b/plugins/puppetdb/src/components/ReportsPage/ReportsPage.test.tsx new file mode 100644 index 0000000000..d43e564ff9 --- /dev/null +++ b/plugins/puppetdb/src/components/ReportsPage/ReportsPage.test.tsx @@ -0,0 +1,85 @@ +/* + * Copyright 2020 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 React from 'react'; +import { ReportsPage } from './ReportsPage'; +import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; +import { EntityProvider } from '@backstage/plugin-catalog-react'; +import { puppetDbApiRef, PuppetDbClient } from '../../api'; +import { ANNOTATION_PUPPET_CERTNAME } from '../../constants'; +import { Entity } from '@backstage/catalog-model/'; +import { isPluginApplicableToEntity } from '../../index'; +import { ApiProvider } from '@backstage/core-app-api'; +import { puppetDbRouteRef } from '../../routes'; + +const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Resource', + metadata: { + name: 'test', + annotations: { + [ANNOTATION_PUPPET_CERTNAME]: 'node1', + }, + }, +}; + +const entityWithoutAnnotations: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Resource', + metadata: { + name: 'test', + annotations: {}, + }, +}; + +const mockPuppetDbApi: Partial = { + getPuppetDbNodeReports: async () => [], +}; + +const apis = TestApiRegistry.from([puppetDbApiRef, mockPuppetDbApi]); + +describe('isPluginApplicableToEntity', () => { + describe('when entity has no annotations', () => { + it('returns false', () => { + expect(isPluginApplicableToEntity(entityWithoutAnnotations)).toBe(false); + }); + }); + + describe('when entity has the puppet annotation', () => { + it('returns true', () => { + expect(isPluginApplicableToEntity(entity)).toBe(true); + }); + }); +}); + +describe('ReportsPage', () => { + it('should render', async () => { + const render = await renderInTestApp( + + + + + , + { + mountedRoutes: { + '/puppetdb': puppetDbRouteRef, + }, + }, + ); + expect( + render.getByText('Latest PuppetDB reports from node node1'), + ).toBeInTheDocument(); + }); +}); diff --git a/plugins/puppetdb/src/components/ReportsPage/ReportsTable.test.tsx b/plugins/puppetdb/src/components/ReportsPage/ReportsTable.test.tsx new file mode 100644 index 0000000000..fadfb1a3f9 --- /dev/null +++ b/plugins/puppetdb/src/components/ReportsPage/ReportsTable.test.tsx @@ -0,0 +1,103 @@ +/* + * Copyright 2020 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 React from 'react'; +import { ReportsTable } from './ReportsTable'; +import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; +import { puppetDbApiRef, PuppetDbReport, PuppetDbClient } from '../../api'; +import { ApiProvider } from '@backstage/core-app-api'; +import { puppetDbRouteRef } from '../../routes'; + +const reports: PuppetDbReport[] = [ + { + hash: 'hash1', + puppet_version: 'version1', + report_format: 1, + certname: 'node1', + start_time: '2021-01-01T00:00:00Z', + end_time: '2021-01-01T00:00:00Z', + producer_timestamp: '2021-01-01T00:00:00Z', + receive_time: '2021-01-01T00:00:00Z', + producer: 'producer1', + transaction_uuid: 'uuid1', + catalog_uuid: 'uuid1', + code_id: 'id1', + cached_catalog_status: 'status1', + type: 'type1', + corrective_change: false, + configuration_version: 'version1', + environment: 'production', + noop: true, + status: 'changed', + }, + { + hash: 'hash2', + puppet_version: 'version2', + report_format: 2, + certname: 'node1', + start_time: '2021-01-01T00:00:00Z', + end_time: '2021-01-01T00:00:00Z', + producer_timestamp: '2021-01-01T00:00:00Z', + receive_time: '2021-01-01T00:00:00Z', + producer: 'producer2', + transaction_uuid: 'uuid2', + catalog_uuid: 'uuid2', + code_id: 'id2', + cached_catalog_status: 'status2', + type: 'type2', + corrective_change: false, + configuration_version: 'version2', + environment: 'production', + noop: false, + status: 'failed', + }, +]; + +const mockPuppetDbApi: Partial = { + getPuppetDbNodeReports: async () => reports, +}; + +const apis = TestApiRegistry.from([puppetDbApiRef, mockPuppetDbApi]); + +const certName = 'node1'; + +describe('ReportsTable', () => { + it('should render', async () => { + const render = await renderInTestApp( + + + , + { + mountedRoutes: { + '/puppetdb': puppetDbRouteRef, + }, + }, + ); + + expect( + render.getByText('Latest PuppetDB reports from node node1'), + ).toBeInTheDocument(); + expect(render.getByText('Configuration Version')).toBeInTheDocument(); + expect(render.getByText('Start Time')).toBeInTheDocument(); + expect(render.getByText('End Time')).toBeInTheDocument(); + expect(render.getByText('Run Duration')).toBeInTheDocument(); + expect(render.getByText('Mode')).toBeInTheDocument(); + expect(render.getByText('Status')).toBeInTheDocument(); + expect(render.getByText('NO-NOOP')).toBeInTheDocument(); + expect(render.getByText('NOOP')).toBeInTheDocument(); + expect(render.getByText('FAILED')).toBeInTheDocument(); + expect(render.getByText('CHANGED')).toBeInTheDocument(); + }); +}); diff --git a/plugins/puppetdb/src/components/Router.tsx b/plugins/puppetdb/src/components/Router.tsx index 7a71eb26ed..3a8a05911b 100644 --- a/plugins/puppetdb/src/components/Router.tsx +++ b/plugins/puppetdb/src/components/Router.tsx @@ -21,7 +21,7 @@ import { ANNOTATION_PUPPET_CERTNAME } from '../constants'; import { Entity } from '@backstage/catalog-model'; import { useEntity } from '@backstage/plugin-catalog-react'; import { MissingAnnotationEmptyState } from '@backstage/core-components'; -import { ReportsPage } from './ReportsPage/ReportsPage'; +import { ReportsPage } from './ReportsPage'; import { ReportDetailsPage } from './ReportDetailsPage'; /** diff --git a/plugins/puppetdb/src/components/StatusField/StatusField.test.tsx b/plugins/puppetdb/src/components/StatusField/StatusField.test.tsx new file mode 100644 index 0000000000..1aa8c94ce9 --- /dev/null +++ b/plugins/puppetdb/src/components/StatusField/StatusField.test.tsx @@ -0,0 +1,52 @@ +/* + * Copyright 2020 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 React from 'react'; +import { StatusField } from './StatusField'; +import { renderInTestApp } from '@backstage/test-utils'; + +describe('StatusField', () => { + it('should render failed', async () => { + const render = await renderInTestApp(); + expect(render.getByText('FAILED')).toBeInTheDocument(); + expect( + render.container.querySelector('span[aria-label="Status error"]'), + ).toBeInTheDocument(); + }); + + it('should render changed', async () => { + const render = await renderInTestApp(); + expect(render.getByText('CHANGED')).toBeInTheDocument(); + expect( + render.container.querySelector('span[aria-label="Status running"]'), + ).toBeInTheDocument(); + }); + + it('should render unchanged', async () => { + const render = await renderInTestApp(); + expect(render.getByText('UNCHANGED')).toBeInTheDocument(); + expect( + render.container.querySelector('span[aria-label="Status pending"]'), + ).toBeInTheDocument(); + }); + + it('should render default', async () => { + const render = await renderInTestApp(); + expect(render.getByText('SUCCESSFUL')).toBeInTheDocument(); + expect( + render.container.querySelector('span[aria-label="Status ok"]'), + ).toBeInTheDocument(); + }); +});