1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-07-19 13:29:41 +02:00

chore(automation): give unique selectors [r8s-168] (#345)

Co-authored-by: JamesPlayer <james.player@portainer.io>
This commit is contained in:
Ali 2025-01-30 15:42:32 +13:00 committed by GitHub
parent b30a1b5250
commit c80cc6e268
29 changed files with 38 additions and 4 deletions

View file

@ -104,6 +104,7 @@ export function TagSelector({
onCreateOption={handleCreateOption} onCreateOption={handleCreateOption}
aria-label="Tags" aria-label="Tags"
data-cy="environment-tags-selector" data-cy="environment-tags-selector"
id="environment-tags-selector"
/> />
</FormControl> </FormControl>
</> </>

View file

@ -36,6 +36,7 @@ export function UsersSelector({
onChange(selectedUsers.map((user) => user.Id)) onChange(selectedUsers.map((user) => user.Id))
} }
data-cy={dataCy} data-cy={dataCy}
id={dataCy}
inputId={inputId} inputId={inputId}
placeholder={placeholder} placeholder={placeholder}
isDisabled={disabled} isDisabled={disabled}

View file

@ -18,6 +18,7 @@ export function Select<T extends number | string>({
options, options,
className, className,
'data-cy': dataCy, 'data-cy': dataCy,
id,
...props ...props
}: Props<T> & SelectHTMLAttributes<HTMLSelectElement>) { }: Props<T> & SelectHTMLAttributes<HTMLSelectElement>) {
return ( return (

View file

@ -111,6 +111,7 @@ export function SingleSelect<TValue = string>({
onChange={(option) => onChange(option ? option.value : null)} onChange={(option) => onChange(option ? option.value : null)}
isOptionDisabled={(option) => !!option.disabled} isOptionDisabled={(option) => !!option.disabled}
data-cy={dataCy} data-cy={dataCy}
id={dataCy}
inputId={inputId} inputId={inputId}
placeholder={placeholder} placeholder={placeholder}
isDisabled={disabled} isDisabled={disabled}
@ -177,6 +178,7 @@ export function MultiSelect<TValue = string>({
closeMenuOnSelect={false} closeMenuOnSelect={false}
onChange={(newValue) => onChange(newValue.map((option) => option.value))} onChange={(newValue) => onChange(newValue.map((option) => option.value))}
data-cy={dataCy} data-cy={dataCy}
id={dataCy}
inputId={inputId} inputId={inputId}
placeholder={placeholder} placeholder={placeholder}
isDisabled={disabled} isDisabled={disabled}

View file

@ -65,6 +65,7 @@ export function Select<
}: Props<Option, IsMulti, Group> & }: Props<Option, IsMulti, Group> &
AutomationTestingProps & { AutomationTestingProps & {
isItemVisible?: (item: Option, search: string) => boolean; isItemVisible?: (item: Option, search: string) => boolean;
id: string;
}) { }) {
const Component = isCreatable ? ReactSelectCreatable : ReactSelect; const Component = isCreatable ? ReactSelectCreatable : ReactSelect;
const { options } = props; const { options } = props;

View file

@ -152,6 +152,7 @@ export function GpuFieldset({
options={options} options={options}
components={{ MultiValueRemove }} components={{ MultiValueRemove }}
data-cy="docker-containers-gpu-select" data-cy="docker-containers-gpu-select"
id="docker-containers-gpu-select"
/> />
</div> </div>
)} )}
@ -173,6 +174,7 @@ export function GpuFieldset({
components={{ Option }} components={{ Option }}
onChange={onChangeSelectedCaps} onChange={onChangeSelectedCaps}
data-cy="docker-containers-gpu-capabilities-select" data-cy="docker-containers-gpu-capabilities-select"
id="docker-containers-gpu-capabilities-select"
/> />
</div> </div>
</div> </div>

View file

@ -44,6 +44,7 @@ export function VolumeSelector({
onChange={(vol) => onChange(vol?.Name)} onChange={(vol) => onChange(vol?.Name)}
inputId={inputId} inputId={inputId}
data-cy="docker-containers-volume-selector" data-cy="docker-containers-volume-selector"
id="docker-containers-volume-selector"
size="sm" size="sm"
/> />
); );

View file

@ -43,6 +43,7 @@ export function CreatableSelector({
isDisabled={isLoading} isDisabled={isLoading}
closeMenuOnSelect={false} closeMenuOnSelect={false}
data-cy="edge-devices-assignment-selector" data-cy="edge-devices-assignment-selector"
id="edge-devices-assignment-selector"
/> />
); );

View file

@ -45,6 +45,7 @@ export function GroupSelector() {
placeholder="Select a group" placeholder="Select a group"
isClearable isClearable
data-cy="edge-devices-assignment-selector" data-cy="edge-devices-assignment-selector"
id="edge-devices-assignment-selector"
/> />
); );

View file

@ -50,6 +50,7 @@ export function TemplateSelector({
onChange(getTemplate({ type, id: templateId }), type); onChange(getTemplate({ type, id: templateId }), type);
}} }}
data-cy="edge-stacks-create-template-selector" data-cy="edge-stacks-create-template-selector"
id="edge-stacks-create-template-selector"
/> />
{isLoadingValues && ( {isLoadingValues && (
<InlineLoader>Loading template values...</InlineLoader> <InlineLoader>Loading template values...</InlineLoader>

View file

@ -97,6 +97,7 @@ function InnerSelector({
placeholder="Select one or multiple group(s)" placeholder="Select one or multiple group(s)"
closeMenuOnSelect={false} closeMenuOnSelect={false}
data-cy="edge-stacks-groups-selector" data-cy="edge-stacks-groups-selector"
id="edge-stacks-groups-selector"
inputId={inputId} inputId={inputId}
/> />
) : ( ) : (

View file

@ -102,6 +102,7 @@ export function PrivateRegistryFieldset({
onChange={(value) => onSelect(value?.Id)} onChange={(value) => onSelect(value?.Id)}
className="w-full" className="w-full"
data-cy="private-registry-selector" data-cy="private-registry-selector"
id="private-registry-selector"
/> />
{method !== 'repository' && ( {method !== 'repository' && (
<Button <Button

View file

@ -122,6 +122,7 @@ export function AppIngressPathForm({
onChangeIngressPath(newIngressPath); onChangeIngressPath(newIngressPath);
}} }}
data-cy="k8sAppCreate-ingressPathHostSelect" data-cy="k8sAppCreate-ingressPathHostSelect"
id="k8sAppCreate-ingressPathHostSelect"
/> />
<InputGroup.ButtonWrapper> <InputGroup.ButtonWrapper>
<Button <Button

View file

@ -60,6 +60,7 @@ export function ConfigurationItem({
onChange={onSelectConfigMap} onChange={onSelectConfigMap}
size="sm" size="sm"
data-cy={`k8sAppCreate-add${configurationType}Select_${index}`} data-cy={`k8sAppCreate-add${configurationType}Select_${index}`}
id={`k8sAppCreate-add${configurationType}Select_${index}`}
/> />
</InputGroup> </InputGroup>
{formikError?.selectedConfiguration && ( {formikError?.selectedConfiguration && (

View file

@ -144,6 +144,7 @@ export function PersistedFolderItem({
applicationValues.Containers.length > 1 applicationValues.Containers.length > 1
} }
data-cy={`k8sAppCreate-persistentFolderSizeUnitSelect_${index}`} data-cy={`k8sAppCreate-persistentFolderSizeUnitSelect_${index}`}
id={`k8sAppCreate-persistentFolderSizeUnitSelect_${index}`}
/> />
</InputGroup> </InputGroup>
{formikError?.size && <FormError>{formikError?.size}</FormError>} {formikError?.size && <FormError>{formikError?.size}</FormError>}
@ -175,6 +176,7 @@ export function PersistedFolderItem({
storageClasses.length <= 1 storageClasses.length <= 1
} }
data-cy={`k8sAppCreate-storageSelect_${index}`} data-cy={`k8sAppCreate-storageSelect_${index}`}
id={`k8sAppCreate-storageSelect_${index}`}
/> />
</InputGroup> </InputGroup>
</> </>
@ -207,6 +209,7 @@ export function PersistedFolderItem({
availableVolumes.length < 1 availableVolumes.length < 1
} }
data-cy={`k8sAppCreate-pvcSelect_${index}`} data-cy={`k8sAppCreate-pvcSelect_${index}`}
id={`k8sAppCreate-pvcSelect_${index}`}
/> />
</InputGroup> </InputGroup>
)} )}

View file

@ -49,6 +49,7 @@ export function PlacementItem({
className={clsx({ striked: !!item.needsDeletion })} className={clsx({ striked: !!item.needsDeletion })}
isDisabled={!!item.needsDeletion} isDisabled={!!item.needsDeletion}
data-cy={`k8sAppCreate-placementLabel_${index}`} data-cy={`k8sAppCreate-placementLabel_${index}`}
id={`k8sAppCreate-placementLabel_${index}`}
/> />
{placementError?.label && ( {placementError?.label && (
<FormError>{placementError.label}</FormError> <FormError>{placementError.label}</FormError>
@ -65,6 +66,7 @@ export function PlacementItem({
className={clsx({ striked: !!item.needsDeletion })} className={clsx({ striked: !!item.needsDeletion })}
isDisabled={!!item.needsDeletion} isDisabled={!!item.needsDeletion}
data-cy={`k8sAppCreate-placementName_${index}`} data-cy={`k8sAppCreate-placementName_${index}`}
id={`k8sAppCreate-placementName_${index}`}
/> />
{placementError?.value && ( {placementError?.value && (
<FormError>{placementError.value}</FormError> <FormError>{placementError.value}</FormError>

View file

@ -35,6 +35,7 @@ export function StorageAccessModeSelector({
inputId={inputId} inputId={inputId}
placeholder="Not configured" placeholder="Not configured"
data-cy={`kubeSetup-storageAccessSelect${storageClassName}`} data-cy={`kubeSetup-storageAccessSelect${storageClassName}`}
id={`kubeSetup-storageAccessSelect${storageClassName}`}
/> />
); );
} }

View file

@ -43,6 +43,7 @@ export function NamespacesSelector({
onChange(selectedTeams.map((namespace) => namespace.name)) onChange(selectedTeams.map((namespace) => namespace.name))
} }
data-cy={dataCy} data-cy={dataCy}
id={dataCy}
inputId={inputId} inputId={inputId}
placeholder={placeholder} placeholder={placeholder}
/> />

View file

@ -184,6 +184,7 @@ export function IngressForm({
} }
noOptionsMessage={() => 'No namespaces available'} noOptionsMessage={() => 'No namespaces available'}
data-cy="k8sAppCreate-namespaceSelect" data-cy="k8sAppCreate-namespaceSelect"
id="k8sAppCreate-namespaceSelect"
/> />
)} )}
</div> </div>
@ -266,6 +267,7 @@ export function IngressForm({
} }
noOptionsMessage={() => 'No ingress classes available'} noOptionsMessage={() => 'No ingress classes available'}
data-cy="k8sAppCreate-ingressClassSelect" data-cy="k8sAppCreate-ingressClassSelect"
id="k8sAppCreate-ingressClassSelect"
/> />
{errors.className && ( {errors.className && (
<FormError className="error-inline mt-1"> <FormError className="error-inline mt-1">
@ -464,6 +466,7 @@ export function IngressForm({
noOptionsMessage={() => 'No TLS secrets available'} noOptionsMessage={() => 'No TLS secrets available'}
size="sm" size="sm"
data-cy={`k8sAppCreate-tlsSelect_${hostIndex}`} data-cy={`k8sAppCreate-tlsSelect_${hostIndex}`}
id={`k8sAppCreate-tlsSelect_${hostIndex}`}
/> />
{!host.NoHost && ( {!host.NoHost && (
<div className="input-group-btn"> <div className="input-group-btn">

View file

@ -35,6 +35,7 @@ export function NamespaceAccessUsersSelector({
closeMenuOnSelect={false} closeMenuOnSelect={false}
onChange={onChange} onChange={onChange}
data-cy={dataCy} data-cy={dataCy}
id={dataCy}
inputId={inputId} inputId={inputId}
placeholder={placeholder} placeholder={placeholder}
components={{ MultiValueLabel, Option: OptionComponent }} components={{ MultiValueLabel, Option: OptionComponent }}

View file

@ -67,6 +67,7 @@ export function RegistriesSelector({
onChange={onChange} onChange={onChange}
inputId={inputId} inputId={inputId}
data-cy="namespaceCreate-registrySelect" data-cy="namespaceCreate-registrySelect"
id="namespaceCreate-registrySelect"
placeholder="Select one or more registries" placeholder="Select one or more registries"
isDisabled={isEditingDisabled} isDisabled={isEditingDisabled}
/> />

View file

@ -37,6 +37,7 @@ export function PorAccessManagementUsersSelector({
closeMenuOnSelect={false} closeMenuOnSelect={false}
onChange={onChange} onChange={onChange}
data-cy="component-selectUser" data-cy="component-selectUser"
id="component-selectUser"
inputId="users-selector" inputId="users-selector"
placeholder="Select one or more users and/or teams" placeholder="Select one or more users and/or teams"
components={{ MultiValueLabel, Option: OptionComponent }} components={{ MultiValueLabel, Option: OptionComponent }}

View file

@ -30,7 +30,7 @@ export function TeamsField({
'You can select which team(s) will be able to manage this resource.' 'You can select which team(s) will be able to manage this resource.'
: undefined : undefined
} }
inputId="teams-selector" inputId="authorized-teams-selector"
errors={errors} errors={errors}
> >
{teams.length > 0 ? ( {teams.length > 0 ? (
@ -39,7 +39,7 @@ export function TeamsField({
teams={teams} teams={teams}
onChange={onChange} onChange={onChange}
value={value} value={value}
inputId="teams-selector" inputId="authorized-teams-selector"
dataCy="teams-selector" dataCy="teams-selector"
/> />
) : ( ) : (

View file

@ -21,7 +21,7 @@ export function UsersField({ name, users, value, onChange, errors }: Props) {
? 'You can select which user(s) will be able to manage this resource.' ? 'You can select which user(s) will be able to manage this resource.'
: undefined : undefined
} }
inputId="users-selector" inputId="authorized-users-selector"
errors={errors} errors={errors}
> >
{users.length > 0 ? ( {users.length > 0 ? (
@ -30,7 +30,7 @@ export function UsersField({ name, users, value, onChange, errors }: Props) {
users={users} users={users}
onChange={onChange} onChange={onChange}
value={value} value={value}
inputId="users-selector" inputId="authorized-users-selector"
dataCy="users-selector" dataCy="users-selector"
/> />
) : ( ) : (

View file

@ -26,6 +26,7 @@ export function PorAccessControlFormTeamSelector({
closeMenuOnSelect={false} closeMenuOnSelect={false}
onChange={onChange} onChange={onChange}
data-cy="portainer-selectTeamAccess" data-cy="portainer-selectTeamAccess"
id="portainer-selectTeamAccess"
inputId={inputId} inputId={inputId}
placeholder="Select one or more teams" placeholder="Select one or more teams"
/> />

View file

@ -26,6 +26,7 @@ export function PorAccessControlFormUserSelector({
closeMenuOnSelect={false} closeMenuOnSelect={false}
onChange={onChange} onChange={onChange}
data-cy="portainer-selectUserAccess" data-cy="portainer-selectUserAccess"
id="portainer-selectUserAccess"
inputId={inputId} inputId={inputId}
placeholder="Select one or more users" placeholder="Select one or more users"
/> />

View file

@ -112,6 +112,7 @@ export function TimeWindowPickerInputGroup({
onChangeTimeZone(newTimeZone.value); onChangeTimeZone(newTimeZone.value);
}} }}
data-cy="time-window-picker-timezone-select" data-cy="time-window-picker-timezone-select"
id="time-window-picker-timezone-select"
/> />
</div> </div>
{errors?.StartTime && <FormError>{errors.StartTime}</FormError>} {errors?.StartTime && <FormError>{errors.StartTime}</FormError>}

View file

@ -54,6 +54,7 @@ export function EdgeGroupsField({
closeMenuOnSelect={false} closeMenuOnSelect={false}
isDisabled={disabled} isDisabled={disabled}
data-cy="update-schedules-edge-groups-select" data-cy="update-schedules-edge-groups-select"
id="update-schedules-edge-groups-select"
/> />
</FormControl> </FormControl>
<TextTip color="blue"> <TextTip color="blue">

View file

@ -41,6 +41,7 @@ export function CredentialSelector({
noOptionsMessage={() => 'no saved credentials'} noOptionsMessage={() => 'no saved credentials'}
inputId="git-creds-selector" inputId="git-creds-selector"
data-cy="git-credentials-selector" data-cy="git-credentials-selector"
id="git-credentials-selector"
/> />
</FormControl> </FormControl>
</div> </div>