From f278597490288abb4d57f17c63b26269e6684feb Mon Sep 17 00:00:00 2001 From: mcbattirola Date: Wed, 30 Oct 2024 09:08:54 -0300 Subject: [PATCH] Storybook, tests --- lib/web/apiserver_test.go | 53 ++++++++++++++ .../teleport/src/Clusters/Clusters.story.tsx | 4 +- .../ManageCluster/ManageCluster.story.tsx | 73 +++++++++++++++++++ .../ManageCluster/ManageCluster.test.tsx | 70 ++++++++++++++++++ .../teleport/src/Clusters/fixtures/index.ts | 15 ++++ 5 files changed, 213 insertions(+), 2 deletions(-) create mode 100644 web/packages/teleport/src/Clusters/ManageCluster/ManageCluster.story.tsx create mode 100644 web/packages/teleport/src/Clusters/ManageCluster/ManageCluster.test.tsx diff --git a/lib/web/apiserver_test.go b/lib/web/apiserver_test.go index a585579f7ddda..a793ce6772486 100644 --- a/lib/web/apiserver_test.go +++ b/lib/web/apiserver_test.go @@ -11266,3 +11266,56 @@ func Test_setEntitlementsWithLegacyLogic(t *testing.T) { }) } } + +// TestGetClusterInfo tests the getClusterInfo handler. +func TestGetClusterInfo(t *testing.T) { + tests := []struct { + name string + cloud bool + assert func(t *testing.T, err error, statusCode int, resp GetClusterInfoResponse) + }{ + { + name: "cloud cluster", + cloud: true, + assert: func(t *testing.T, err error, statusCode int, resp GetClusterInfoResponse) { + require.NoError(t, err) + require.Equal(t, http.StatusOK, statusCode) + require.True(t, resp.IsCloud) + }, + }, + { + name: "non-cloud cluster", + cloud: false, + assert: func(t *testing.T, err error, statusCode int, resp GetClusterInfoResponse) { + require.NoError(t, err) + require.Equal(t, http.StatusOK, statusCode) + require.False(t, resp.IsCloud) + }, + }, + } + + // Iterate over test cases. + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + modules.SetTestModules(t, &modules.TestModules{ + TestFeatures: modules.Features{ + Cloud: tc.cloud, + }, + }) + + env := newWebPack(t, 1) + proxy := env.proxies[0] + pack := proxy.authPack(t, "test-user@example.com", auth.GetPresetRoles()) + endpoint := pack.clt.Endpoint("webapi", "sites", env.server.ClusterName(), "info") + + var clusterInfo GetClusterInfoResponse + resp, reqErr := pack.clt.Get(context.Background(), endpoint, url.Values{}) + if reqErr != nil && resp.Code() == http.StatusOK { + err := json.Unmarshal(resp.Bytes(), &clusterInfo) + require.NoError(t, err) + } + + tc.assert(t, reqErr, resp.Code(), clusterInfo) + }) + } +} diff --git a/web/packages/teleport/src/Clusters/Clusters.story.tsx b/web/packages/teleport/src/Clusters/Clusters.story.tsx index 03fd1184c931f..899ba8de53a90 100644 --- a/web/packages/teleport/src/Clusters/Clusters.story.tsx +++ b/web/packages/teleport/src/Clusters/Clusters.story.tsx @@ -26,7 +26,7 @@ import { FeaturesContextProvider } from 'teleport/FeaturesContext'; import { getOSSFeatures } from 'teleport/features'; -import { Clusters } from './Clusters'; +import { ClusterListPage } from './Clusters'; import * as fixtures from './fixtures'; export default { @@ -40,7 +40,7 @@ export function Story({ value }: { value: teleport.Context }) { - + diff --git a/web/packages/teleport/src/Clusters/ManageCluster/ManageCluster.story.tsx b/web/packages/teleport/src/Clusters/ManageCluster/ManageCluster.story.tsx new file mode 100644 index 0000000000000..8d6732bd3b743 --- /dev/null +++ b/web/packages/teleport/src/Clusters/ManageCluster/ManageCluster.story.tsx @@ -0,0 +1,73 @@ +/** + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import React from 'react'; +import { MemoryRouter } from 'react-router'; + +import { createTeleportContext } from 'teleport/mocks/contexts'; +import { ContextProvider } from 'teleport/index'; +import { ContentMinWidth } from 'teleport/Main/Main'; +import { Route } from 'teleport/components/Router'; + +import { clusterInfoFixture } from '../fixtures'; + +import { ManageCluster } from './ManageCluster'; + +export default { + title: 'Teleport/Clusters/ManageCluster', +}; + +function render(fetchClusterDetails: (clusterId: string) => Promise) { + const ctx = createTeleportContext(); + + ctx.clusterService.fetchClusterDetails = fetchClusterDetails; + return ( + + + + + + + + + + ); +} + +export function Loading() { + const fetchClusterDetails = () => { + // promise never resolves to simulate loading state + return new Promise(() => {}); + }; + return render(fetchClusterDetails); +} + +export function Failed() { + const fetchClusterDetails = () => + Promise.reject(new Error('Failed to load cluster details')); + return render(fetchClusterDetails); +} + +export function Success() { + const fetchClusterDetails = () => { + return new Promise(resolve => { + resolve(clusterInfoFixture); + }); + }; + return render(fetchClusterDetails); +} diff --git a/web/packages/teleport/src/Clusters/ManageCluster/ManageCluster.test.tsx b/web/packages/teleport/src/Clusters/ManageCluster/ManageCluster.test.tsx new file mode 100644 index 0000000000000..c2c9a7290f073 --- /dev/null +++ b/web/packages/teleport/src/Clusters/ManageCluster/ManageCluster.test.tsx @@ -0,0 +1,70 @@ +import React from 'react'; +import { MemoryRouter, Route } from 'react-router-dom'; + +import { render, waitFor, screen } from 'design/utils/testing'; + +import { ContextProvider } from 'teleport/index'; +import { createTeleportContext } from 'teleport/mocks/contexts'; +import { ContentMinWidth } from 'teleport/Main/Main'; + +import { clusterInfoFixture } from '../fixtures'; + +import { ManageCluster } from './ManageCluster'; + +function renderElement(element, ctx) { + return render( + + + + {element} + + + + ); +} + +describe('test ManageCluster component', () => { + beforeEach(() => { + jest.resetAllMocks(); + jest.spyOn(console, 'error').mockImplementation(); + }); + + test('fetches cluster information on load', async () => { + const ctx = createTeleportContext(); + jest + .spyOn(ctx.clusterService, 'fetchClusterDetails') + .mockResolvedValueOnce({ ...clusterInfoFixture }); + + renderElement(, ctx); + await waitFor(() => { + expect( + screen.getByText(clusterInfoFixture.authVersion) + ).toBeInTheDocument(); + }); + + expect(screen.getByText(clusterInfoFixture.clusterId)).toBeInTheDocument(); + expect(screen.getByText(clusterInfoFixture.publicURL)).toBeInTheDocument(); + + expect(ctx.clusterService.fetchClusterDetails).toHaveBeenCalledTimes(1); + }); + + test('shows error when load fails', async () => { + const ctx = createTeleportContext(); + jest + .spyOn(ctx.clusterService, 'fetchClusterDetails') + .mockRejectedValue({ message: 'error message' }); + + renderElement(, ctx); + await waitFor(() => { + expect( + screen.queryByText(clusterInfoFixture.authVersion) + ).not.toBeInTheDocument(); + }); + + await waitFor(() => { + expect(screen.getByText('error message')).toBeInTheDocument(); + }); + + expect(ctx.clusterService.fetchClusterDetails).toHaveBeenCalledTimes(1); + }); +}); diff --git a/web/packages/teleport/src/Clusters/fixtures/index.ts b/web/packages/teleport/src/Clusters/fixtures/index.ts index 41344401a5a7d..f228835cf2626 100644 --- a/web/packages/teleport/src/Clusters/fixtures/index.ts +++ b/web/packages/teleport/src/Clusters/fixtures/index.ts @@ -16,6 +16,8 @@ * along with this program. If not, see . */ +import { ClusterInfo } from "teleport/services/clusters"; + export const clusters = [ { clusterId: 'localhost', @@ -428,3 +430,16 @@ export const clusters = [ proxyVersion: '1.14.3', }, ]; + +export const clusterInfoFixture: ClusterInfo = { + authVersion: 'v17.0.0', + clusterId: 'cluster-id', + connectedText: '', + isCloud: false, + lastConnected: new Date(), + proxyVersion: 'v17.0.0', + publicURL: 'example.teleport.com', + status: 'active', + url: 'example.teleport.com', + licenseExpiryDateText: new Date().toISOString(), +};