chore(sidebar): add data-cys [EE-3605] (#7143)

* chore(sidebar): add data-cys [EE-3605]

fix [EE-3605]
pull/7153/head
Chaim Lev-Ari 2022-06-28 19:36:40 +03:00 committed by GitHub
parent ed8f9b5931
commit 882051cc30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 158 additions and 25 deletions

View File

@ -12,12 +12,17 @@ interface Props {
export function AzureSidebar({ environmentId }: Props) { export function AzureSidebar({ environmentId }: Props) {
return ( return (
<> <>
<DashboardLink environmentId={environmentId} platformPath="azure" /> <DashboardLink
environmentId={environmentId}
platformPath="azure"
data-cy="azureSidebar-dashboard"
/>
<SidebarItem <SidebarItem
to="azure.containerinstances" to="azure.containerinstances"
params={{ endpointId: environmentId }} params={{ endpointId: environmentId }}
icon={Box} icon={Box}
label="Container instances" label="Container instances"
data-cy="azureSidebar-containerInstances"
/> />
</> </>
); );

View File

@ -58,27 +58,35 @@ export function DockerSidebar({ environmentId, environment }: Props) {
label: 'Swarm', label: 'Swarm',
icon: Trello, icon: Trello,
to: 'docker.swarm', to: 'docker.swarm',
dataCy: 'portainerSidebar-swarm',
} }
: { : {
label: 'Host', label: 'Host',
icon: Trello, icon: Trello,
to: 'docker.host', to: 'docker.host',
dataCy: 'portainerSidebar-host',
}; };
return ( return (
<> <>
<DashboardLink environmentId={environmentId} platformPath="docker" /> <DashboardLink
environmentId={environmentId}
platformPath="docker"
data-cy="dockerSidebar-dashboard"
/>
<SidebarItem <SidebarItem
label="App Templates" label="App Templates"
icon={Edit} icon={Edit}
to="docker.templates" to="docker.templates"
params={{ endpointId: environmentId }} params={{ endpointId: environmentId }}
data-cy="portainerSidebar-appTemplates"
> >
<SidebarItem <SidebarItem
label="Custom Templates" label="Custom Templates"
to="docker.templates.custom" to="docker.templates.custom"
params={{ endpointId: environmentId }} params={{ endpointId: environmentId }}
data-cy="dockerSidebar-customTemplates"
/> />
</SidebarItem> </SidebarItem>
@ -88,6 +96,7 @@ export function DockerSidebar({ environmentId, environment }: Props) {
params={{ endpointId: environmentId }} params={{ endpointId: environmentId }}
icon={Layers} icon={Layers}
label="Stacks" label="Stacks"
data-cy="dockerSidebar-stacks"
/> />
)} )}
@ -97,6 +106,7 @@ export function DockerSidebar({ environmentId, environment }: Props) {
params={{ endpointId: environmentId }} params={{ endpointId: environmentId }}
icon={Shuffle} icon={Shuffle}
label="Services" label="Services"
data-cy="dockerSidebar-services"
/> />
)} )}
@ -105,6 +115,7 @@ export function DockerSidebar({ environmentId, environment }: Props) {
params={{ endpointId: environmentId }} params={{ endpointId: environmentId }}
icon={Box} icon={Box}
label="Containers" label="Containers"
data-cy="dockerSidebar-containers"
/> />
<SidebarItem <SidebarItem
@ -112,6 +123,7 @@ export function DockerSidebar({ environmentId, environment }: Props) {
params={{ endpointId: environmentId }} params={{ endpointId: environmentId }}
icon={List} icon={List}
label="Images" label="Images"
data-cy="dockerSidebar-images"
/> />
<SidebarItem <SidebarItem
@ -119,9 +131,14 @@ export function DockerSidebar({ environmentId, environment }: Props) {
params={{ endpointId: environmentId }} params={{ endpointId: environmentId }}
icon={Share2} icon={Share2}
label="Networks" label="Networks"
data-cy="dockerSidebar-networks"
/> />
<VolumesLink environmentId={environmentId} platformPath="docker" /> <VolumesLink
environmentId={environmentId}
platformPath="docker"
data-cy="dockerSidebar-volumes"
/>
{apiVersion >= 1.3 && isSwarmManager && ( {apiVersion >= 1.3 && isSwarmManager && (
<SidebarItem <SidebarItem
@ -129,6 +146,7 @@ export function DockerSidebar({ environmentId, environment }: Props) {
params={{ endpointId: environmentId }} params={{ endpointId: environmentId }}
icon={Clipboard} icon={Clipboard}
label="Configs" label="Configs"
data-cy="dockerSidebar-configs"
/> />
)} )}
@ -138,6 +156,7 @@ export function DockerSidebar({ environmentId, environment }: Props) {
params={{ endpointId: environmentId }} params={{ endpointId: environmentId }}
icon={Lock} icon={Lock}
label="Secrets" label="Secrets"
data-cy="dockerSidebar-secrets"
/> />
)} )}
@ -147,6 +166,7 @@ export function DockerSidebar({ environmentId, environment }: Props) {
params={{ endpointId: environmentId }} params={{ endpointId: environmentId }}
icon={Clock} icon={Clock}
label="Events" label="Events"
data-cy="dockerSidebar-events"
/> />
)} )}
@ -155,6 +175,7 @@ export function DockerSidebar({ environmentId, environment }: Props) {
icon={setupSubMenuProps.icon} icon={setupSubMenuProps.icon}
to={setupSubMenuProps.to} to={setupSubMenuProps.to}
params={{ endpointId: environmentId }} params={{ endpointId: environmentId }}
data-cy={setupSubMenuProps.dataCy}
> >
<Authorized <Authorized
authorizations="PortainerEndpointUpdateSettings" authorizations="PortainerEndpointUpdateSettings"

View File

@ -6,10 +6,30 @@ import { SidebarSection } from './SidebarSection';
export function EdgeComputeSidebar() { export function EdgeComputeSidebar() {
return ( return (
<SidebarSection title="Edge compute"> <SidebarSection title="Edge compute">
<SidebarItem to="edge.devices" label="Edge Devices" icon={Box} /> <SidebarItem
<SidebarItem to="edge.groups" label="Edge Groups" icon={Grid} /> to="edge.devices"
<SidebarItem to="edge.stacks" label="Edge Stacks" icon={Layers} /> label="Edge Devices"
<SidebarItem to="edge.jobs" label="Edge Jobs" icon={Clock} /> icon={Box}
data-cy="portainerSidebar-edgeDevices"
/>
<SidebarItem
to="edge.groups"
label="Edge Groups"
icon={Grid}
data-cy="portainerSidebar-edgeGroups"
/>
<SidebarItem
to="edge.stacks"
label="Edge Stacks"
icon={Layers}
data-cy="portainerSidebar-edgeStacks"
/>
<SidebarItem
to="edge.jobs"
label="Edge Jobs"
icon={Clock}
data-cy="portainerSidebar-edgeJobs"
/>
</SidebarSection> </SidebarSection>
); );
} }

View File

@ -21,13 +21,18 @@ export function KubernetesSidebar({ environmentId }: Props) {
<> <>
{isOpen && <KubectlShellButton environmentId={environmentId} />} {isOpen && <KubectlShellButton environmentId={environmentId} />}
<DashboardLink environmentId={environmentId} platformPath="kubernetes" /> <DashboardLink
environmentId={environmentId}
platformPath="kubernetes"
data-cy="k8sSidebar-dashboard"
/>
<SidebarItem <SidebarItem
to="kubernetes.templates.custom" to="kubernetes.templates.custom"
params={{ endpointId: environmentId }} params={{ endpointId: environmentId }}
icon={Edit} icon={Edit}
label="Custom Templates" label="Custom Templates"
data-cy="k8sSidebar-customTemplates"
/> />
<SidebarItem <SidebarItem
@ -35,6 +40,7 @@ export function KubernetesSidebar({ environmentId }: Props) {
params={{ endpointId: environmentId }} params={{ endpointId: environmentId }}
icon={Layers} icon={Layers}
label="Namespaces" label="Namespaces"
data-cy="k8sSidebar-namespaces"
/> />
<Authorized authorizations="HelmInstallChart"> <Authorized authorizations="HelmInstallChart">
@ -43,6 +49,7 @@ export function KubernetesSidebar({ environmentId }: Props) {
params={{ endpointId: environmentId }} params={{ endpointId: environmentId }}
icon={Loader} icon={Loader}
label="Helm" label="Helm"
data-cy="k8sSidebar-helm"
/> />
</Authorized> </Authorized>
@ -51,6 +58,7 @@ export function KubernetesSidebar({ environmentId }: Props) {
params={{ endpointId: environmentId }} params={{ endpointId: environmentId }}
icon={Box} icon={Box}
label="Applications" label="Applications"
data-cy="k8sSidebar-applications"
/> />
<SidebarItem <SidebarItem
@ -58,21 +66,28 @@ export function KubernetesSidebar({ environmentId }: Props) {
params={{ endpointId: environmentId }} params={{ endpointId: environmentId }}
icon={Lock} icon={Lock}
label="ConfigMaps & Secrets" label="ConfigMaps & Secrets"
data-cy="k8sSidebar-configurations"
/> />
<VolumesLink environmentId={environmentId} platformPath="kubernetes" /> <VolumesLink
environmentId={environmentId}
platformPath="kubernetes"
data-cy="k8sSidebar-volumes"
/>
<SidebarItem <SidebarItem
label="Cluster" label="Cluster"
to="kubernetes.cluster" to="kubernetes.cluster"
icon={Server} icon={Server}
params={{ endpointId: environmentId }} params={{ endpointId: environmentId }}
data-cy="k8sSidebar-cluster"
> >
<Authorized authorizations="K8sClusterSetupRW" adminOnlyCE> <Authorized authorizations="K8sClusterSetupRW" adminOnlyCE>
<SidebarItem <SidebarItem
to="portainer.k8sendpoint.kubernetesConfig" to="portainer.k8sendpoint.kubernetesConfig"
params={{ id: environmentId }} params={{ id: environmentId }}
label="Setup" label="Setup"
data-cy="k8sSidebar-setup"
/> />
</Authorized> </Authorized>
@ -81,6 +96,7 @@ export function KubernetesSidebar({ environmentId }: Props) {
to="portainer.k8sendpoint.securityConstraint" to="portainer.k8sendpoint.securityConstraint"
params={{ id: environmentId }} params={{ id: environmentId }}
label="Security constraints" label="Security constraints"
data-cy="k8sSidebar-securityConstraints"
/> />
</Authorized> </Authorized>
@ -88,6 +104,7 @@ export function KubernetesSidebar({ environmentId }: Props) {
to="kubernetes.registries" to="kubernetes.registries"
params={{ endpointId: environmentId }} params={{ endpointId: environmentId }}
label="Registries" label="Registries"
data-cy="k8sSidebar-registries"
/> />
</SidebarItem> </SidebarItem>
</> </>

View File

@ -27,10 +27,25 @@ export function SettingsSidebar({ isAdmin }: Props) {
return ( return (
<SidebarSection title="Settings"> <SidebarSection title="Settings">
{showUsersSection && ( {showUsersSection && (
<SidebarItem to="portainer.users" label="Users" icon={Users}> <SidebarItem
<SidebarItem to="portainer.teams" label="Teams" /> to="portainer.users"
label="Users"
icon={Users}
data-cy="portainerSidebar-users"
>
<SidebarItem
to="portainer.teams"
label="Teams"
data-cy="portainerSidebar-teams"
/>
{isAdmin && <SidebarItem to="portainer.roles" label="Roles" />} {isAdmin && (
<SidebarItem
to="portainer.roles"
label="Roles"
data-cy="portainerSidebar-roles"
/>
)}
</SidebarItem> </SidebarItem>
)} )}
{isAdmin && ( {isAdmin && (
@ -40,15 +55,25 @@ export function SettingsSidebar({ isAdmin }: Props) {
to="portainer.endpoints" to="portainer.endpoints"
icon={HardDrive} icon={HardDrive}
openOnPaths={['portainer.wizard.endpoints']} openOnPaths={['portainer.wizard.endpoints']}
data-cy="portainerSidebar-environments"
> >
<SidebarItem to="portainer.groups" label="Groups" /> <SidebarItem
<SidebarItem to="portainer.tags" label="Tags" /> to="portainer.groups"
label="Groups"
data-cy="portainerSidebar-environmentGroups"
/>
<SidebarItem
to="portainer.tags"
label="Tags"
data-cy="portainerSidebar-environmentTags"
/>
</SidebarItem> </SidebarItem>
<SidebarItem <SidebarItem
label="Registries" label="Registries"
to="portainer.registries" to="portainer.registries"
icon={Radio} icon={Radio}
data-cy="portainerSidebar-registries"
/> />
{process.env.PORTAINER_EDITION !== 'CE' && ( {process.env.PORTAINER_EDITION !== 'CE' && (
@ -56,6 +81,7 @@ export function SettingsSidebar({ isAdmin }: Props) {
to="portainer.licenses" to="portainer.licenses"
label="Licenses" label="Licenses"
icon={Award} icon={Award}
data-cy="portainerSidebar-licenses"
/> />
)} )}
@ -63,22 +89,38 @@ export function SettingsSidebar({ isAdmin }: Props) {
label="Authentication logs" label="Authentication logs"
to="portainer.authLogs" to="portainer.authLogs"
icon={FileText} icon={FileText}
data-cy="portainerSidebar-authLogs"
> >
<SidebarItem to="portainer.activityLogs" label="Activity Logs" /> <SidebarItem
to="portainer.activityLogs"
label="Activity Logs"
data-cy="portainerSidebar-activityLogs"
/>
</SidebarItem> </SidebarItem>
<SidebarItem to="portainer.settings" label="Settings" icon={Settings}> <SidebarItem
to="portainer.settings"
label="Settings"
icon={Settings}
data-cy="portainerSidebar-settings"
>
{!window.ddExtension && ( {!window.ddExtension && (
<SidebarItem <SidebarItem
to="portainer.settings.authentication" to="portainer.settings.authentication"
label="Authentication" label="Authentication"
data-cy="portainerSidebar-authentication"
/> />
)} )}
<SidebarItem to="portainer.settings.cloud" label="Cloud" /> <SidebarItem
to="portainer.settings.cloud"
label="Cloud"
data-cy="portainerSidebar-cloud"
/>
<SidebarItem <SidebarItem
to="portainer.settings.edgeCompute" to="portainer.settings.edgeCompute"
label="Edge Compute" label="Edge Compute"
data-cy="portainerSidebar-edgeCompute"
/> />
<SidebarItem.Wrapper label="Help / About"> <SidebarItem.Wrapper label="Help / About">
@ -90,7 +132,7 @@ export function SettingsSidebar({ isAdmin }: Props) {
} }
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"
className="px-3 rounded flex h-full items-center" className="px-3 rounded flex h-8 items-center"
> >
Help / About Help / About
</a> </a>

View File

@ -41,7 +41,12 @@ export function Sidebar() {
{/* negative margin + padding -> scrollbar won't hide the content */} {/* negative margin + padding -> scrollbar won't hide the content */}
<div className="mt-6 overflow-y-auto flex-1 -mr-4 pr-4"> <div className="mt-6 overflow-y-auto flex-1 -mr-4 pr-4">
<ul className="space-y-9"> <ul className="space-y-9">
<SidebarItem to="portainer.home" icon={Home} label="Home" /> <SidebarItem
to="portainer.home"
icon={Home}
label="Home"
data-cy="portainerSidebar-home"
/>
<EnvironmentSidebar /> <EnvironmentSidebar />

View File

@ -6,12 +6,17 @@ import {
import clsx from 'clsx'; import clsx from 'clsx';
import { ComponentProps } from 'react'; import { ComponentProps } from 'react';
import { AutomationTestingProps } from '@/types';
import { Link } from '@@/Link'; import { Link } from '@@/Link';
import { IconProps, Icon } from '@@/Icon'; import { IconProps, Icon } from '@@/Icon';
import { useSidebarState } from '../useSidebarState'; import { useSidebarState } from '../useSidebarState';
interface Props extends IconProps, ComponentProps<typeof Link> { interface Props
extends IconProps,
ComponentProps<typeof Link>,
AutomationTestingProps {
label: string; label: string;
ignorePaths?: string[]; ignorePaths?: string[];
} }
@ -23,6 +28,7 @@ export function Head({
label, label,
icon, icon,
ignorePaths = [], ignorePaths = [],
'data-cy': dataCy,
}: Props) { }: Props) {
const { isOpen } = useSidebarState(); const { isOpen } = useSidebarState();
const anchorProps = useSrefActive( const anchorProps = useSrefActive(
@ -43,6 +49,7 @@ export function Head({
'text-inherit no-underline hover:no-underline hover:text-inherit focus:no-underline focus:text-inherit w-full flex-1 rounded-md', 'text-inherit no-underline hover:no-underline hover:text-inherit focus:no-underline focus:text-inherit w-full flex-1 rounded-md',
{ 'px-3': isOpen } { 'px-3': isOpen }
)} )}
data-cy={dataCy}
> >
<div <div
className={clsx('flex items-center h-8 space-x-4 text-sm', { className={clsx('flex items-center h-8 space-x-4 text-sm', {

View File

@ -1,12 +1,14 @@
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import { Icon } from 'react-feather'; import { Icon } from 'react-feather';
import { AutomationTestingProps } from '@/types';
import { Wrapper } from './Wrapper'; import { Wrapper } from './Wrapper';
import { Menu } from './Menu'; import { Menu } from './Menu';
import { Head } from './Head'; import { Head } from './Head';
import { getPathsForChildren } from './utils'; import { getPathsForChildren } from './utils';
interface Props { interface Props extends AutomationTestingProps {
icon?: Icon; icon?: Icon;
to: string; to: string;
params?: object; params?: object;
@ -22,6 +24,7 @@ export function SidebarItem({
params, params,
label, label,
openOnPaths = [], openOnPaths = [],
'data-cy': dataCy,
}: Props) { }: Props) {
const childrenPath = getPathsForChildren(children); const childrenPath = getPathsForChildren(children);
const head = ( const head = (
@ -31,6 +34,7 @@ export function SidebarItem({
params={params} params={params}
label={label} label={label}
ignorePaths={childrenPath} ignorePaths={childrenPath}
data-cy={dataCy}
/> />
); );

View File

@ -1,21 +1,27 @@
import { Layout } from 'react-feather'; import { Layout } from 'react-feather';
import { EnvironmentId } from '@/portainer/environments/types'; import { EnvironmentId } from '@/portainer/environments/types';
import { AutomationTestingProps } from '@/types';
import { SidebarItem } from '../SidebarItem'; import { SidebarItem } from '../SidebarItem';
interface Props { interface Props extends AutomationTestingProps {
environmentId: EnvironmentId; environmentId: EnvironmentId;
platformPath: string; platformPath: string;
} }
export function DashboardLink({ environmentId, platformPath }: Props) { export function DashboardLink({
environmentId,
platformPath,
'data-cy': dataCy,
}: Props) {
return ( return (
<SidebarItem <SidebarItem
to={`${platformPath}.dashboard`} to={`${platformPath}.dashboard`}
params={{ endpointId: environmentId }} params={{ endpointId: environmentId }}
icon={Layout} icon={Layout}
label="Dashboard" label="Dashboard"
data-cy={dataCy}
/> />
); );
} }

View File

@ -1,21 +1,27 @@
import { Database } from 'react-feather'; import { Database } from 'react-feather';
import { EnvironmentId } from '@/portainer/environments/types'; import { EnvironmentId } from '@/portainer/environments/types';
import { AutomationTestingProps } from '@/types';
import { SidebarItem } from '../SidebarItem'; import { SidebarItem } from '../SidebarItem';
interface Props { interface Props extends AutomationTestingProps {
environmentId: EnvironmentId; environmentId: EnvironmentId;
platformPath: string; platformPath: string;
} }
export function VolumesLink({ environmentId, platformPath }: Props) { export function VolumesLink({
environmentId,
platformPath,
'data-cy': dataCy,
}: Props) {
return ( return (
<SidebarItem <SidebarItem
to={`${platformPath}.volumes`} to={`${platformPath}.volumes`}
params={{ endpointId: environmentId }} params={{ endpointId: environmentId }}
icon={Database} icon={Database}
label="Volumes" label="Volumes"
data-cy={dataCy}
/> />
); );
} }