From 2a1c32a2e42f586f9fd1784e10a4c0cbeba654d8 Mon Sep 17 00:00:00 2001 From: Tanmay Satam Date: Thu, 21 Sep 2023 12:44:35 -0400 Subject: [PATCH] Replace OverviewComponent with new implementation - Use FluentUI DetailsList for contents - Always display all properties, even if value is not present - Modify E2E test to check each individual property --- .../ClusterDetailListComponents/Overview.tsx | 158 ++++-------------- test/e2e/admin_portal.go | 59 ++++--- 2 files changed, 69 insertions(+), 148 deletions(-) diff --git a/portal/v2/src/ClusterDetailListComponents/Overview.tsx b/portal/v2/src/ClusterDetailListComponents/Overview.tsx index c7778c9c62a..c75427a1eef 100644 --- a/portal/v2/src/ClusterDetailListComponents/Overview.tsx +++ b/portal/v2/src/ClusterDetailListComponents/Overview.tsx @@ -1,6 +1,5 @@ -import { IShimmerStyles, Shimmer, ShimmerElementType } from '@fluentui/react/lib/Shimmer'; -import { Component } from "react" -import { Stack, Text, IStackStyles, IStackItemStyles } from '@fluentui/react'; +import { useMemo } from "react" +import { Stack, ShimmeredDetailsList, SelectionMode } from '@fluentui/react'; import { contentStackStylesNormal } from "../App" import { IClusterDetails } from "../ClusterDetailList" @@ -9,59 +8,6 @@ interface OverviewComponentProps { clusterName: string } -interface IOverviewComponentState { - item: IClusterDetails -} - -export const ShimmerStyle: Partial = { - root: { - margin: "11px 0" - } -} - -export const headShimmerStyle: Partial = { - root: { - margin: "15px 0" - } -} - -export const headerShimmer = [ - { type: ShimmerElementType.line, height: 32, width: '25%' }, -] - -export const rowShimmer = [ - { type: ShimmerElementType.line, height: 18, width: '75%' }, -] - -export const KeyColumnStyle: Partial = { - root: { - paddingTop: 10, - paddingRight: 15, - } -} - -export const ValueColumnStyle: Partial = { - root: { - paddingTop: 10, - } -} - -export const KeyStyle: IStackItemStyles = { - root: { - fontStyle: "bold", - alignSelf: "flex-start", - fontVariantAlternates: "bold", - color: "grey", - paddingBottom: 10 - } -} - -export const ValueStyle: IStackItemStyles = { - root: { - paddingBottom: 10 - } -} - const clusterDetailHeadings : IClusterDetails = { apiServerVisibility: 'ApiServer Visibility', apiServerURL: 'ApiServer URL', @@ -82,71 +28,37 @@ const clusterDetailHeadings : IClusterDetails = { version: 'Version', installStatus: 'Installation Status' } - -function ClusterDetailCell( - value: any, - ): any { - if (typeof (value.value) == typeof (" ")) { - return - {value.value} - - } - } - -export class OverviewComponent extends Component { - constructor(props: OverviewComponentProps | Readonly) { - super(props); - } - - public render() { - const headerEntries = Object.entries(clusterDetailHeadings) - const filteredHeaders: Array<[string, any]> = [] - if (this.props.item.length != 0) { - headerEntries.filter((element: [string, any]) => { - if (this.props.item[element[0]] != null && - this.props.item[element[0]].toString().length > 0) { - filteredHeaders.push(element) - } - }) - return ( - - - - {filteredHeaders.map((value: [string, any], index: number) => ( - - ) - )} - - - - {Array(filteredHeaders.length).fill(':').map((value: [string], index: number) => ( - - ) - )} - - - - {filteredHeaders.map((value: [string, any], index: number) => ( - - ) - )} - - - - ); - } else { - return ( - - - {headerEntries.map(header => ( - - ) - )} - - ) - } - } - } \ No newline at end of file +interface ClusterDetailItem { + key: number, + name: string, + value: string, +} + +export function OverviewComponent(props: OverviewComponentProps) { + const items: ClusterDetailItem[] = useMemo(() => + Object.entries(clusterDetailHeadings) + .map(([property, heading], index) => + ({key: index, name: heading, value: props.item[property]}) + ), + [props.item]) + + return ( + + + ({item.value || '-'})} + ]} + enableShimmer={props.item.length == 0} + selectionMode={SelectionMode.none} + isHeaderVisible={false} + /> + + + ); +} diff --git a/test/e2e/admin_portal.go b/test/e2e/admin_portal.go index e4107cf701e..ef5fb2fb653 100644 --- a/test/e2e/admin_portal.go +++ b/test/e2e/admin_portal.go @@ -78,8 +78,6 @@ var _ = Describe("Admin Portal E2E Testing", func() { }) It("Should be able to populate cluster info panel correctly", func() { - const CLUSTER_INFO_HEADINGS = 10 - err := wd.Wait(conditions.ElementIsLocated(selenium.ByCSSSelector, "div[data-automation-key='name']")) Expect(err).ToNot(HaveOccurred()) @@ -89,34 +87,45 @@ var _ = Describe("Admin Portal E2E Testing", func() { err = cluster.Click() Expect(err).ToNot(HaveOccurred()) - err = wd.WaitWithTimeout(conditions.ElementIsLocated(selenium.ByID, "ClusterDetailCell"), 2*time.Minute) + err = wd.WaitWithTimeout(conditions.ElementIsLocated(selenium.ByClassName, "ClusterOverviewList"), 2*time.Minute) + Expect(err).ToNot(HaveOccurred()) + + list, err := wd.FindElement(selenium.ByClassName, "ClusterOverviewList") Expect(err).ToNot(HaveOccurred()) + expectedProperties := []string{ + "ApiServer Visibility", + "ApiServer URL", + "Architecture Version", + "Console Link", + "Created At", + "Created By", + "Failed Provisioning State", + "Infra Id", + "Last Admin Update Error", + "Last Modified At", + "Last Modified By", + "Last Provisioning State", + "Location", + "Name", + "Provisioning State", + "Resource Id", + "Version", + "Installation Status", + } + Eventually(func(g Gomega) { - panelSpans, err := wd.FindElements(selenium.ByID, "ClusterDetailCell") - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(len(panelSpans)).To(Equal(CLUSTER_INFO_HEADINGS * 3)) - - panelFields := panelSpans[0 : CLUSTER_INFO_HEADINGS-1] - panelColons := panelSpans[CLUSTER_INFO_HEADINGS : CLUSTER_INFO_HEADINGS*2-1] - panelValues := panelSpans[CLUSTER_INFO_HEADINGS*2 : len(panelSpans)-1] - - for _, panelField := range panelFields { - panelText, err := panelField.Text() - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(panelText).To(Not(Equal(""))) - } + for i, wantName := range expectedProperties { + cell, err := list.FindElement(selenium.ByCSSSelector, fmt.Sprintf(".ms-List-cell[data-list-index='%d']", i)) + Expect(err).ToNot(HaveOccurred()) - for _, panelField := range panelColons { - panelText, err := panelField.Text() - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(panelText).To(Equal(":")) - } + name, err := cell.FindElement(selenium.ByCSSSelector, "[data-automation-key='name']") + Expect(err).ToNot(HaveOccurred()) + Expect(name.Text()).To(Equal(wantName)) - for _, panelField := range panelValues { - panelText, err := panelField.Text() - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(panelText).To(Not(Equal(""))) + value, err := cell.FindElement(selenium.ByCSSSelector, "[data-automation-key='value']") + Expect(err).ToNot(HaveOccurred()) + Expect(value.Text()).To(Not(Equal(""))) } }).WithTimeout(time.Minute).WithPolling(time.Second).Should(Succeed()) })