1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-08 23:35:31 +02:00

chore(data-cy): require data-cy attributes [EE-6880] (#11453)
Some checks are pending
ci / build_images (map[arch:amd64 platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:amd64 platform:windows version:1809]) (push) Waiting to run
ci / build_images (map[arch:amd64 platform:windows version:ltsc2022]) (push) Waiting to run
ci / build_images (map[arch:arm platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:arm64 platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:ppc64le platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:s390x platform:linux version:]) (push) Waiting to run
ci / build_manifests (push) Blocked by required conditions
/ triage (push) Waiting to run
Lint / Run linters (push) Waiting to run
Test / test-client (push) Waiting to run
Test / test-server (map[arch:amd64 platform:linux]) (push) Waiting to run
Test / test-server (map[arch:amd64 platform:windows version:1809]) (push) Waiting to run
Test / test-server (map[arch:amd64 platform:windows version:ltsc2022]) (push) Waiting to run
Test / test-server (map[arch:arm64 platform:linux]) (push) Waiting to run

This commit is contained in:
Ali 2024-04-11 12:11:38 +12:00 committed by GitHub
parent 3cad13388c
commit d38085a560
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
538 changed files with 2571 additions and 595 deletions

View file

@ -20,8 +20,10 @@ export function BackupFailedPanel() {
<TextTip>
The latest automated backup has failed at {isoDate(status.TimestampUTC)}
. For details please see the log files and have a look at the{' '}
<Link to="portainer.settings">settings</Link> to verify the backup
configuration.
<Link to="portainer.settings" data-cy="backup-failed-settings-link">
settings
</Link>{' '}
to verify the backup configuration.
</TextTip>
</InformationPanel>
);

View file

@ -35,7 +35,12 @@ export function AMTButton({
return (
<>
<Button onClick={openDialog} icon={Link} color="light">
<Button
onClick={openDialog}
icon={Link}
color="light"
data-cy="associate-amt-button"
>
Associate with OpenAMT
</Button>
{isOpenDialog && (

View file

@ -53,6 +53,7 @@ export function AssociateAMTDialog({
<div className="flex h-8 items-center">
<Checkbox
id="settings-container-truncate-name"
data-cy="select-all-checkbox"
label="Select all (in this page)"
checked={isAllPageSelected}
onChange={handleSelectAll}
@ -67,6 +68,7 @@ export function AssociateAMTDialog({
>
<Checkbox
id={`${env.Id}`}
data-cy={`environment-checkbox-${env.Name}`}
label={`${env.Name} (${env.URL})`}
checked={selection.includes(env.Id)}
onChange={() =>
@ -89,11 +91,16 @@ export function AssociateAMTDialog({
</div>
</Modal.Body>
<Modal.Footer>
<Button onClick={onClose} color="default">
<Button
onClick={onClose}
color="default"
data-cy="associate-amt-dialog-cancel-button"
>
Cancel
</Button>
<LoadingButton
onClick={handleSubmit}
data-cy="associate-amt-dialog-associate-button"
disabled={selection.length === 0}
loadingText="Associating..."
isLoading={activateDeviceMutation.isLoading}

View file

@ -39,6 +39,7 @@ export function EditButtons({ environment }: { environment: Environment }) {
size="medium"
className={buttonsClasses}
title="Edit"
data-cy={`edit-environment-link-${environment.Name}`}
/>
<LinkButton
@ -50,6 +51,7 @@ export function EditButtons({ environment }: { environment: Environment }) {
size="medium"
className={buttonsClasses}
title="Configuration"
data-cy={`configure-environment-link-${environment.Name}`}
/>
</ButtonsGrid>
);

View file

@ -48,12 +48,14 @@ export function EnvironmentBrowseButtons({
? 'Browse snapshot is only available for async environments'
: ''
}
data-cy={`browse-snapshot-link-${environment.Name}`}
>
Browse snapshot
</LinkButton>
) : (
<Button
icon={X}
data-cy={`close-snapshot-link-${environment.Name}`}
onClick={onClickDisconnect}
className="!m-0 w-full !py-0 opacity-60"
size="medium"
@ -78,11 +80,13 @@ export function EnvironmentBrowseButtons({
onClick={onClickBrowse}
color="primary"
className="!m-0 w-full !py-0"
data-cy={`live-connect-link-${environment.Name}`}
>
Live connect
</LinkButton>
) : (
<Button
data-cy={`disconnect-link-${environment.Name}`}
icon={WifiOff}
onClick={onClickDisconnect}
className="!m-0 w-full !py-0 opacity-60"

View file

@ -23,7 +23,12 @@ function Option<TValue = number>(props: OptionProps<OptionType<TValue>, true>) {
{...props}
>
<div className="flex items-center gap-2">
<input type="checkbox" checked={isSelected} onChange={() => null} />
<input
type="checkbox"
checked={isSelected}
onChange={() => null}
data-cy={`homepage-filter-option-${label}`}
/>
<label className="whitespace-nowrap">{label}</label>
</div>
</components.Option>
@ -46,6 +51,7 @@ export function HomepageFilter<TValue = number>({
components={{ Option }}
onChange={(option) => onChange([...option])}
bindToBody
data-cy="homepage-filter"
/>
);
}

View file

@ -31,6 +31,7 @@ export function KubeconfigButton({ environments, envQueryParams }: Props) {
<>
<Button
onClick={handleClick}
data-cy="download-kubeconfig-button"
size="medium"
className="!m-0"
icon={Download}

View file

@ -76,6 +76,7 @@ export function KubeconfigPrompt({
<div className="mt-2 flex h-8 items-center">
<Checkbox
id="settings-container-truncate-name"
data-cy="select-all-checkbox"
label="Select all (in this page)"
checked={isAllPageSelected}
onChange={handleSelectAll}
@ -95,6 +96,7 @@ export function KubeconfigPrompt({
>
<Checkbox
id={`${env.Id}`}
data-cy={`select-environment-checkbox-${env.Name}`}
label={`${env.Name} (${env.URL})`}
checked={selection.includes(env.Id)}
onChange={() =>
@ -118,10 +120,18 @@ export function KubeconfigPrompt({
</Modal.Body>
<Modal.Footer>
<Button onClick={onClose} color="default">
<Button
onClick={onClose}
color="default"
data-cy="cancel-kubeconfig-download-button"
>
Cancel
</Button>
<Button onClick={handleDownload} disabled={selection.length === 0}>
<Button
onClick={handleDownload}
disabled={selection.length === 0}
data-cy="download-kubeconfig-confirbutton"
>
Download File
</Button>
</Modal.Footer>

View file

@ -9,8 +9,13 @@ export function NoEnvironmentsInfoPanel({ isAdmin }: { isAdmin: boolean }) {
{isAdmin ? (
<span>
No environment available for management. Please head over the{' '}
<Link to="portainer.wizard.endpoints">environment wizard</Link> to
add an environment.
<Link
to="portainer.wizard.endpoints"
data-cy="wizard-add-environments-link"
>
environment wizard
</Link>{' '}
to add an environment.
</span>
) : (
<span>

View file

@ -45,6 +45,7 @@ export function SortbySelector({
onChange={(option: ListSortType) => onChange(option)}
isClearable
value={value}
data-cy="home-view-sortby-selector"
/>
<button

View file

@ -28,6 +28,7 @@ export function UpdateBadge() {
'th-dark:bg-blue-3 th-dark:text-blue-8 th-dark:hover:bg-blue-5 th-dark:hover:text-blue-8',
'th-highcontrast:border-white th-highcontrast:bg-transparent th-highcontrast:text-white th-highcontrast:hover:bg-gray-warm-7 th-highcontrast:hover:text-white'
)}
data-cy="home-schedule-update-link"
>
Schedule Update
</Link>

View file

@ -70,7 +70,11 @@ export function AccessControlPanel({
{!isEditDisabled && !isEditMode && (
<div className="row">
<div>
<Button color="link" onClick={toggleEditMode}>
<Button
color="link"
onClick={toggleEditMode}
data-cy="change-ownership-button"
>
<Icon icon={Edit} className="space-right" />
Change ownership
</Button>

View file

@ -134,7 +134,11 @@ function getInheritanceMessage(
return (
<InheritanceMessage tooltip="Access control applied on a service is also applied on each container of that service.">
Access control on this resource is inherited from the following service:
<Link to="docker.services.service" params={{ id: resourceId }}>
<Link
to="docker.services.service"
params={{ id: resourceId }}
data-cy="docker-access-inherited-service"
>
{truncate(resourceId)}
</Link>
</InheritanceMessage>
@ -149,7 +153,11 @@ function getInheritanceMessage(
<InheritanceMessage tooltip="Access control applied on a container created using a template is also applied on each volume associated to the container.">
Access control on this resource is inherited from the following
container:
<Link to="docker.containers.container" params={{ id: resourceId }}>
<Link
to="docker.containers.container"
params={{ id: resourceId }}
data-cy="docker-access-inherited-container"
>
{truncate(resourceId)}
</Link>
</InheritanceMessage>

View file

@ -102,11 +102,17 @@ export function AccessControlPanelForm({
<div className="form-group">
<div className="col-sm-12">
<Button size="small" color="default" onClick={onCancelClick}>
<Button
size="small"
color="default"
onClick={onCancelClick}
data-cy="cancel-access-control-update-button"
>
Cancel
</Button>
<LoadingButton
size="small"
data-cy="update-access-control-button"
color="primary"
type="submit"
isLoading={isSubmitting}

View file

@ -40,11 +40,15 @@ export function TeamsField({
onChange={onChange}
value={value}
inputId="teams-selector"
dataCy="teams-selector"
/>
) : (
<span className="small text-muted">
You have not yet created any teams. Head over to the{' '}
<Link to="portainer.teams">Teams view</Link> to manage teams.
<Link to="portainer.teams" data-cy="teams-view-link">
Teams view
</Link>{' '}
to manage teams.
</span>
)}
</FormControl>

View file

@ -31,11 +31,15 @@ export function UsersField({ name, users, value, onChange, errors }: Props) {
onChange={onChange}
value={value}
inputId="users-selector"
dataCy="users-selector"
/>
) : (
<span className="small text-muted">
You have not yet created any users. Head over to the{' '}
<Link to="portainer.users">Users view</Link> to manage users.
<Link to="portainer.users" data-cy="access-control-users-link">
Users view
</Link>{' '}
to manage users.
</span>
)}
</FormControl>

View file

@ -27,6 +27,7 @@ export function AccessTokensDatatable({ canExit }: { canExit?: boolean }) {
renderTableActions={(selectedItems) => (
<TableActions selectedItems={selectedItems} canExit={canExit} />
)}
data-cy="access-tokens-datatable"
/>
);
}

View file

@ -22,9 +22,14 @@ export function TableActions({
disabled={selectedItems.length === 0}
confirmMessage="Do you want to remove the selected access token(s)? Any script or application using these tokens will no longer be able to invoke the Portainer API."
onConfirmed={handleRemove}
data-cy="access-tokens-delete-button"
/>
<AddButton to=".new-access-token" disabled={!canExit}>
<AddButton
to=".new-access-token"
disabled={!canExit}
data-cy="access-tokens-add-button"
>
Add access token
</AddButton>
</>

View file

@ -40,6 +40,7 @@ export function ApplicationSettingsForm() {
</TextTip>
<SwitchField
label="Enable front-end data caching for Kubernetes environments"
data-cy="account-applicationSettingsUseCacheSwitch"
checked={values.useCache}
onChange={(value) => setFieldValue('useCache', value)}
labelClass="col-lg-2 col-sm-3" // match the label width of the other fields in the page

View file

@ -73,6 +73,7 @@ export function HelmRepositoryDatatable() {
emptyContentLabel="No Helm repository found"
isLoading={helmReposQuery.isLoading}
isRowSelectable={(row) => !row.original.Global}
data-cy="helm-repositories-datatable"
/>
);
}
@ -84,7 +85,11 @@ function HelmDatatableDescription({ isAdmin }: { isAdmin: boolean }) {
account&apos;s Portainer UI. Helm charts are pulled down from these repos
(plus the{' '}
{isAdmin ? (
<Link to="portainer.settings" params={{ '#': 'kubernetes-settings' }}>
<Link
to="portainer.settings"
params={{ '#': 'kubernetes-settings' }}
data-cy="k8s-globally-select-repo-link"
>
<span>globally-set Helm repo</span>
</Link>
) : (

View file

@ -52,6 +52,7 @@ export function CreateUserAccessTokenInnerForm({ showAuthentication }: Props) {
</FormControl>
<LoadingButton
disabled={!isValid || !dirty}
data-cy="create-access-token-button"
isLoading={false}
loadingText="Adding access token..."
>

View file

@ -17,13 +17,18 @@ export function DisplayUserAccessToken({ apikey }: { apikey: string }) {
<div className="inline-flex">
<div className="">{apikey}</div>
<div>
<CopyButton copyText={apikey} color="link" />
<CopyButton
copyText={apikey}
color="link"
data-cy="create-access-token-copy-button"
/>
</div>
</div>
<hr />
</div>
<Button
type="button"
data-cy="create-access-token-done-button"
onClick={() => router.stateService.go('portainer.account')}
>
Done

View file

@ -57,6 +57,7 @@ export function HelmRepositoryForm({
<div className="col-sm-12 mt-3">
<LoadingButton
disabled={!isValid || !dirty}
data-cy="helm-repository-save-button"
isLoading={isLoading}
loadingText="Saving Helm repository..."
>
@ -65,6 +66,7 @@ export function HelmRepositoryForm({
{isEditing && (
<Button
color="default"
data-cy="helm-repository-cancel-button"
onClick={() => router.stateService.go('portainer.account')}
>
Cancel

View file

@ -32,6 +32,7 @@ export function CommonFields({
>
<Input
name="title"
data-cy="custom-templates-title-input"
placeholder="e.g. mytemplate"
id="template-title"
required
@ -50,6 +51,7 @@ export function CommonFields({
>
<Input
name="description"
data-cy="custom-templates-description-input"
id="template-description"
required
value={values.Description}
@ -62,6 +64,7 @@ export function CommonFields({
<FormControl label="Note" inputId="template-note" errors={errors?.Note}>
<Input
name="note"
data-cy="custom-templates-note-input"
id="template-note"
value={values.Note}
onChange={(e) => {
@ -73,6 +76,7 @@ export function CommonFields({
<FormControl label="Logo" inputId="template-logo" errors={errors?.Logo}>
<Input
name="logo"
data-cy="custom-templates-logo-input"
id="template-logo"
value={values.Logo}
onChange={(e) => {

View file

@ -50,6 +50,7 @@ export function CustomTemplatesVariablesDefinitionField({
errors={errors}
textTip="List should map the mustache variables in the template file, if default value is empty, the variable will be required."
isAddButtonHidden={isVariablesNamesFromParent}
data-cy="custom-templates-variables-field"
/>
);
}
@ -58,7 +59,13 @@ interface DefinitionItemProps extends ItemProps<VariableDefinition> {
isNameReadonly?: boolean;
}
function Item({ item, onChange, error, isNameReadonly }: DefinitionItemProps) {
function Item({
item,
onChange,
error,
isNameReadonly,
index,
}: DefinitionItemProps) {
const errorObj = typeof error === 'object' ? error : {};
return (
@ -70,6 +77,7 @@ function Item({ item, onChange, error, isNameReadonly }: DefinitionItemProps) {
onChange={handleChange}
placeholder="Name (e.g var_name)"
readOnly={isNameReadonly}
data-cy={`custom-templates-item-name-field_${index}`}
/>
{errorObj?.name && <FormError>{errorObj.name}</FormError>}
</div>
@ -79,6 +87,7 @@ function Item({ item, onChange, error, isNameReadonly }: DefinitionItemProps) {
onChange={handleChange}
placeholder="Label"
name="label"
data-cy={`custom-templates-item-label-field_${index}`}
/>
{errorObj?.label && <FormError>{errorObj.label}</FormError>}
</div>
@ -88,6 +97,7 @@ function Item({ item, onChange, error, isNameReadonly }: DefinitionItemProps) {
value={item.description}
onChange={handleChange}
placeholder="Description"
data-cy={`custom-templates-item-description-field_${index}`}
/>
{errorObj?.description && <FormError>{errorObj.description}</FormError>}
</div>
@ -97,6 +107,7 @@ function Item({ item, onChange, error, isNameReadonly }: DefinitionItemProps) {
onChange={handleChange}
placeholder="Default Value"
name="defaultValue"
data-cy={`custom-templates-item-default-value-field_${index}`}
/>
{errorObj?.defaultValue && (
<FormError>{errorObj.defaultValue}</FormError>

View file

@ -28,6 +28,7 @@ export function VariableFieldItem({
>
<Input
name={`variables.${definition.name}`}
data-cy={`custom-template-variables-${definition.name}`}
id={inputId}
value={value}
onChange={(e) => onChange(e.target.value)}

View file

@ -19,6 +19,7 @@ export function PlatformField({
<FormControl label="Platform" required inputId="template-platform">
<Select
name="platform"
data-cy="custom-tempalte-platform-select"
id="template-platform"
required
options={platformOptions}

View file

@ -19,6 +19,7 @@ export function TemplateTypeSelector({
<FormControl label="Type" required inputId="template-type">
<Select
name="type"
data-cy="custom-template-template-type"
id="template-type"
required
options={typeOptions}

View file

@ -75,8 +75,13 @@ export function AutomaticEdgeEnvCreation() {
{!edgeComputeConfigurationOK ? (
<TextTip color="orange">
In order to use this feature, please turn on Edge Compute features{' '}
<Link to="portainer.settings.edgeCompute">here</Link> and have
Portainer API server URL and tunnel server address properly
<Link
to="portainer.settings.edgeCompute"
data-cy="edge-disabled-portainer-edge-settings-link"
>
here
</Link>{' '}
and have Portainer API server URL and tunnel server address properly
configured.
</TextTip>
) : (
@ -147,7 +152,12 @@ function EdgeKeyInfo({
<code>{edgeKey}</code>
</div>
<CopyButton copyText={edgeKey}>Copy token</CopyButton>
<CopyButton
copyText={edgeKey}
data-cy="edge-auto-create-copy-token-button"
>
Copy token
</CopyButton>
</FormSection>
<hr />
@ -159,19 +169,28 @@ function EdgeKeyInfo({
showMetaFields
>
<FormControl label="Portainer API server URL">
<Input value={url} readOnly />
<Input value={url} readOnly data-cy="edge-auto-create-url-input" />
</FormControl>
{!asyncMode && (
<FormControl label="Portainer tunnel server address">
<Input value={tunnelUrl} readOnly />
<Input
value={tunnelUrl}
readOnly
data-cy="edge-auto-create-tunnel-address-input"
/>
</FormControl>
)}
<TextTip color="blue">
Portainer Server URL{' '}
{!asyncMode ? 'and tunnel server address are' : 'is'} set{' '}
<Link to="portainer.settings.edgeCompute">here</Link>
<Link
to="portainer.settings.edgeCompute"
data-cy="server-url-portainer-edge-settings-link"
>
here
</Link>
</TextTip>
</EdgeScriptForm>
</>

View file

@ -18,7 +18,11 @@ export function EdgeKeyDisplay({ edgeKey }: { edgeKey: string }) {
<Code>{edgeKey}</Code>
<CopyButton copyText={edgeKey} className="mt-2">
<CopyButton
copyText={edgeKey}
className="mt-2"
data-cy="copy-edge-key-button"
>
Copy token
</CopyButton>
</FormSection>

View file

@ -78,6 +78,7 @@ export function EnvironmentsDatatable({
onClick={() => onRemove(selectedRows)}
icon={Trash2}
className="!m-0"
data-cy="remove-environments-button"
>
Remove
</Button>
@ -87,6 +88,7 @@ export function EnvironmentsDatatable({
{isBE && (
<AddButton
color="secondary"
data-cy="environments-auto-onboarding-button"
to="portainer.endpoints.edgeAutoCreateScript"
>
Auto onboarding
@ -96,11 +98,13 @@ export function EnvironmentsDatatable({
<AddButton
to="portainer.wizard.endpoints"
params={{ referrer: 'environments' }}
data-cy="environments-add-environments-button"
>
Add environment
</AddButton>
</div>
)}
data-cy="environments-datatable"
/>
);
}

View file

@ -20,7 +20,11 @@ export function ImportFdoDeviceButton() {
return (
<div className="ml-[5px]">
<AddButton color="secondary" to="portainer.endpoints.importDevice">
<AddButton
color="secondary"
to="portainer.endpoints.importDevice"
data-cy="import-fdo-device-button"
>
Import FDO device
</AddButton>
</div>

View file

@ -31,9 +31,11 @@ function Cell({
props={{
to: 'portainer.endpoints.endpoint.access',
params: { id: environment.Id },
'data-cy': `environment-manage-access-${environment.Name}`,
}}
color="link"
icon={Users}
data-cy={`environment-manage-access-button-${environment.Name}`}
>
Manage access
</Button>

View file

@ -13,7 +13,11 @@ export const name = columnHelper.accessor('Name', {
}
return (
<Link to="portainer.endpoints.endpoint" params={{ id: environment.Id }}>
<Link
to="portainer.endpoints.endpoint"
params={{ id: environment.Id }}
data-cy={`environment-link-${environment.Id}`}
>
{name}
</Link>
);

View file

@ -50,6 +50,7 @@ function Cell({
<div className="mt-2 text-right">
<Button
color="link"
data-cy={`dismiss-error-${environment.Id}`}
className="small !ml-0 p-0"
onClick={handleDismissButton}
>

View file

@ -43,8 +43,10 @@ export function TagsDatatable({
disabled={selectedItems.length === 0}
confirmMessage="Are you sure you want to remove the selected tag(s)?"
onConfirmed={() => onRemove(selectedItems)}
data-cy="remove-tag-button"
/>
)}
data-cy="tags-datatable"
/>
);
}

View file

@ -30,6 +30,7 @@ export function TimePickerInput({
<div className="flex flex-col">
<Button
color="link"
data-cy="env-time-picker-hours-up-button"
size="medium"
className="!ml-0 w-full"
icon={ChevronUp}
@ -42,12 +43,14 @@ export function TimePickerInput({
/>
<Input
type="text"
data-cy="time-picker-hours-input"
value={hours}
className="w-12 !cursor-default text-center"
disabled
/>
<Button
color="link"
data-cy="env-time-picker-hours-down-button"
size="medium"
className="!ml-0 w-full"
icon={ChevronDown}
@ -63,6 +66,7 @@ export function TimePickerInput({
<div className="flex flex-col">
<Button
color="link"
data-cy="env-time-picker-minutes-up-button"
size="medium"
className="!ml-0 w-full"
icon={ChevronUp}
@ -75,12 +79,14 @@ export function TimePickerInput({
/>
<Input
type="text"
data-cy="time-picker-minutes-input"
value={minutes}
className="w-12 !cursor-default text-center"
disabled
/>
<Button
color="link"
data-cy="env-time-picker-minutes-down-button"
size="medium"
className="!ml-0 w-full"
icon={ChevronDown}
@ -94,6 +100,7 @@ export function TimePickerInput({
</div>
<Button
color="default"
data-cy="env-time-picker-ampm-button"
className="h-[34px]"
onClick={() => {
const newTime = moment(localTime24h, valueFormat)

View file

@ -72,6 +72,7 @@ export function TimeWindowPicker({
{!isEditMode && (
<Button
color="default"
data-cy="edit-change-window-button"
className="!ml-0"
onClick={() => setIsEditMode(true)}
>
@ -81,6 +82,7 @@ export function TimeWindowPicker({
{isEditMode && (
<Button
color="default"
data-cy="cancel-change-window-button"
className="!ml-0"
onClick={() => {
setIsEditMode(false);

View file

@ -90,7 +90,7 @@ export function TimeWindowPickerInputGroup({
<Select<Option<string>>
options={timeZoneOptions}
value={timeZoneOptions[timeZoneOptionIndex]}
className="basis-[fit-content] flex-1 min-w-fit max-w-xs"
className="min-w-fit max-w-xs flex-1 basis-[fit-content]"
onChange={(newTimeZone) => {
if (!newTimeZone) return;
// update the utc time so that the local time displayed remains the same
@ -111,6 +111,7 @@ export function TimeWindowPickerInputGroup({
});
onChangeTimeZone(newTimeZone.value);
}}
data-cy="time-window-picker-timezone-select"
/>
</div>
{errors?.StartTime && <FormError>{errors.StartTime}</FormError>}

View file

@ -27,6 +27,7 @@ export function EnvironmentGroupsDatatable() {
renderTableActions={(selectedItems) => (
<TableActions selectedItems={selectedItems} />
)}
data-cy="environment-groups-datatable"
/>
);
}

View file

@ -20,9 +20,10 @@ export function TableActions({
disabled={selectedItems.length === 0}
confirmMessage="Are you sure you want to remove the selected environment group(s)?"
onConfirmed={handleRemove}
data-cy="remove-environment-groups-button"
/>
<AddButton>Add group</AddButton>
<AddButton data-cy="add-environment-group-button">Add group</AddButton>
</>
);

View file

@ -10,7 +10,7 @@ import { EnvironmentGroup } from '../../types';
const columnHelper = createColumnHelper<EnvironmentGroup>();
export const columns = [
buildNameColumn<EnvironmentGroup>('Name', '.group'),
buildNameColumn<EnvironmentGroup>('Name', '.group', 'environment-group-name'),
columnHelper.display({
header: 'Actions',
cell: ActionsCell,
@ -26,9 +26,11 @@ function ActionsCell({
props={{
to: '.group.access',
params: { id: item.Id },
'data-cy': `manage-access-link_${item.Name}`,
}}
color="link"
icon={Users}
data-cy={`manage-access-button_${item.Name}`}
>
Manage access
</Button>

View file

@ -53,6 +53,7 @@ export function AssociatedEnvironmentsSelector({
);
}
}}
data-cy="edgeGroupCreate-associatedEndpoints"
/>
</div>
</div>

View file

@ -69,8 +69,13 @@ function CreateView() {
<Widget.Body>
<TextTip color="blue" className="mb-2">
Devices need to be allocated to an Edge group, visit the{' '}
<Link to="edge.groups">Edge Groups</Link> page to assign
environments and create groups.
<Link
to="edge.groups"
data-cy="update-schedules-create-edge-groups-link"
>
Edge Groups
</Link>{' '}
page to assign environments and create groups.
</TextTip>
<Formik
@ -106,6 +111,7 @@ function CreateView() {
<div className="col-sm-12">
<LoadingButton
disabled={!isValid}
data-cy="update-schedules-create-submit-button"
isLoading={createMutation.isLoading}
loadingText="Creating..."
>

View file

@ -93,8 +93,13 @@ function ItemView() {
<Widget.Body>
<TextTip color="blue">
Devices need to be allocated to an Edge group, visit the{' '}
<Link to="edge.groups">Edge Groups</Link> page to assign
environments and create groups.
<Link
to="edge.groups"
data-cy="update-schedules-edge-groups-link"
>
Edge Groups
</Link>{' '}
page to assign environments and create groups.
</TextTip>
<Formik
@ -159,6 +164,7 @@ function ItemView() {
<div className="col-sm-12">
<LoadingButton
disabled={!isValid}
data-cy="update-schedule-button"
isLoading={updateMutation.isLoading}
loadingText="Updating..."
>

View file

@ -76,6 +76,7 @@ export function ListView() {
<TableActions selectedRows={selectedRows} />
)}
isRowSelectable={(row) => row.original.status === StatusType.Pending}
data-cy="environment-update-schedules-datatable"
/>
</>
);
@ -92,9 +93,12 @@ function TableActions({
<DeleteButton
onConfirmed={() => handleRemove()}
disabled={selectedRows.length === 0}
data-cy="remove-update-schedules-button"
confirmMessage="Are you sure you want to remove these schedules?"
/>
<AddButton to=".create">Add update & rollback schedule</AddButton>
<AddButton to=".create" data-cy="add-update-schedules-button">
Add update & rollback schedule
</AddButton>
</>
);

View file

@ -9,7 +9,7 @@ import { scheduledTime } from './scheduled-time';
import { scheduleType } from './type';
export const columns = [
buildNameColumn<DecoratedItem>('name', '.item'),
buildNameColumn<DecoratedItem>('name', '.item', 'update-schedules-name'),
scheduledTime,
groups,
scheduleType,

View file

@ -53,6 +53,7 @@ export function EdgeGroupsField({
getOptionValue={(group) => group.Id.toString()}
closeMenuOnSelect={false}
isDisabled={disabled}
data-cy="update-schedules-edge-groups-select"
/>
</FormControl>
<TextTip color="blue">

View file

@ -55,7 +55,11 @@ export function ScheduledTimeField({ disabled }: Props) {
minDate={new Date(Date.now() - 24 * 60 * 60 * 1000)}
/>
) : (
<Input defaultValue={value} disabled />
<Input
defaultValue={value}
disabled
data-cy="update-schedules-time-input"
/>
)}
</FormControl>
{!disabled && value && (

View file

@ -63,6 +63,7 @@ export function EnvironmentTypeSelectView() {
</div>
<Button
disabled={types.length === 0}
data-cy="start-wizard-button"
onClick={() => startWizard()}
>
Start Wizard

View file

@ -93,10 +93,17 @@ export function EnvironmentCreationView() {
'flex justify-between'
)}
>
<Button disabled={isFirstStep} onClick={onPreviousClick}>
<Button
disabled={isFirstStep}
onClick={onPreviousClick}
data-cy="environment-wizard-previous-button"
>
<Icon icon={ArrowLeft} /> Previous
</Button>
<Button onClick={onNextClick}>
<Button
onClick={onNextClick}
data-cy="environment-wizard-next-button"
>
{isLastStep ? 'Close' : 'Next'}
<Icon icon={ArrowRight} />
</Button>

View file

@ -127,6 +127,7 @@ export function WizardAzure({ onCreate }: Props) {
<div className="col-sm-12">
<LoadingButton
className="vertical-center"
data-cy="create-azure-environment-button"
loadingText="Connecting environment..."
isLoading={mutation.isLoading}
disabled={!dirty || !isValid}

View file

@ -87,6 +87,7 @@ export function APIForm({ onCreate }: Props) {
<div className="col-sm-12">
<LoadingButton
className="wizard-connect-button vertical-center"
data-cy="docker-aconnect-button"
loadingText="Connecting environment..."
isLoading={mutation.isLoading}
disabled={!dirty || !isValid}

View file

@ -52,7 +52,9 @@ function DeployCode({ code }: DeployCodeProps) {
<Code>{code}</Code>
<div className="mt-2">
<CopyButton copyText={code}>Copy command</CopyButton>
<CopyButton copyText={code} data-cy="copy-deployment-command">
Copy command
</CopyButton>
</div>
</>
);

View file

@ -83,7 +83,9 @@ function DeployCode({ code }: DeployCodeProps) {
<Code>{code}</Code>
</div>
<div className="mt-2">
<CopyButton copyText={code}>Copy command</CopyButton>
<CopyButton copyText={code} data-cy="copy-deployment-script">
Copy command
</CopyButton>
</div>
</>
);

View file

@ -53,6 +53,7 @@ export function SocketForm({ onCreate }: Props) {
<div className="col-sm-12">
<LoadingButton
className="wizard-connect-button vertical-center"
data-cy="docker-socket-connect-button"
loadingText="Connecting environment..."
isLoading={mutation.isLoading}
disabled={!dirty || !isValid}
@ -94,6 +95,7 @@ function OverrideSocketFieldset() {
<div className="col-sm-12">
<SwitchField
checked={values.overridePath}
data-cy="create-docker-env-socket-override-switch"
onChange={(checked) => setFieldValue('overridePath', checked)}
label="Override default socket path"
labelClass="col-sm-3 col-lg-2"

View file

@ -110,7 +110,9 @@ function DeployCode({
)}
<Code>{code}</Code>
<div className="mt-2">
<CopyButton copyText={code}>Copy command</CopyButton>
<CopyButton copyText={code} data-cy="copy-deploy-agent-command-button">
Copy command
</CopyButton>
</div>
</>
);

View file

@ -78,13 +78,16 @@ export function KubeConfigTeaserForm() {
required
inputId="kubeconfig_file"
>
<Button disabled>Select a file</Button>
<Button disabled data-cy="kubeconfig-file-upload">
Select a file
</Button>
</FormControl>
<div className="form-group">
<div className="col-sm-12">
<LoadingButton
className="wizard-connect-button !ml-0"
data-cy="kubeconfig-connect-environment-button"
loadingText="Connecting environment..."
isLoading={false}
disabled

View file

@ -53,6 +53,7 @@ export function AgentForm({ onCreate }: Props) {
<div className="col-sm-12">
<LoadingButton
className="wizard-connect-button vertical-center"
data-cy="agent-connect-environment-button"
loadingText="Connecting environment..."
isLoading={mutation.isLoading}
disabled={!dirty || !isValid}

View file

@ -76,6 +76,7 @@ export function EdgeAgentForm({ onCreate, readonly, asyncMode }: Props) {
<div className="col-sm-12">
<LoadingButton
className="vertical-center"
data-cy="edge-agent-form-submit-button"
isLoading={createMutation.isLoading}
loadingText="Creating environment..."
disabled={!isValid}

View file

@ -50,7 +50,12 @@ export function EdgeAgentTab({ onCreate, commands, asyncMode = false }: Props) {
<div className="row">
<div className="flex justify-end">
<Button color="primary" type="reset" onClick={handleReset}>
<Button
color="primary"
type="reset"
onClick={handleReset}
data-cy="edge-agent-tab-add-environment-button"
>
Add another environment
</Button>
</div>

View file

@ -23,6 +23,7 @@ export function GroupField({ name = 'meta.groupId' }: { name?: string }) {
<FormControl label="Group" errors={metaProps.error}>
<Select
name={name}
data-cy="environment-group-select"
options={options}
value={fieldProps.value}
onChange={(e) => handleChange(e.target.value)}

View file

@ -35,10 +35,10 @@ export function NameField({
>
<Input
id={id}
data-cy="environmentCreate-nameInput"
name="name"
onChange={(e) => setDebouncedValue(e.target.value)}
value={debouncedValue}
data-cy="endpointCreate-nameInput"
placeholder={placeholder}
readOnly={readonly}
/>

View file

@ -62,7 +62,11 @@ export function HomeView() {
<div className="flex flex-wrap gap-4">
{localEnvironmentAdded.status === 'success' && (
<Link to="portainer.home" className={styles.link}>
<Link
to="portainer.home"
className={styles.link}
data-cy="wizard-get-started-link"
>
<Option
icon={
localEnvironmentAdded.type === EnvironmentType.Docker
@ -75,7 +79,11 @@ export function HomeView() {
/>
</Link>
)}
<Link to="portainer.wizard.endpoints" className={styles.link}>
<Link
to="portainer.wizard.endpoints"
className={styles.link}
data-cy="wizard-add-environments-link"
>
<Option
title="Add Environments"
icon={Plug2}

View file

@ -22,6 +22,7 @@ export function AdditionalFileField({ onChange, value, errors }: Props) {
addLabel="Add file"
item={Item}
itemBuilder={() => ''}
data-cy="gitops-additional-files"
/>
);
}
@ -32,6 +33,7 @@ function Item({
disabled,
error,
readOnly,
index,
}: ItemProps<string>) {
const [inputValue, updateInputValue] = useStateWrapper(item, onChange);
@ -47,6 +49,7 @@ function Item({
onChange={(e) => {
updateInputValue(e.target.value);
}}
data-cy={`gitops-additional-files_${index}`}
/>
</InputGroup>
{error && (

View file

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

View file

@ -23,6 +23,7 @@ export function NewCredentialForm({
<div className="flex items-center gap-2">
<Checkbox
id="repository-save-credential"
data-cy="gitops-save-credential-checkbox"
label="save credential"
checked={value.SaveCredential || false}
className="[&+label]:mb-0"
@ -30,6 +31,7 @@ export function NewCredentialForm({
/>
<Input
value={value.NewCredentialName || ''}
data-cy="gitops-new-credential-name-input"
name="new_credential_name"
placeholder="credential name"
className="ml-4 w-48"

View file

@ -32,6 +32,7 @@ export function AutoUpdateFieldset({
<div className="col-sm-12">
<SwitchField
name="autoUpdate"
data-cy="gitops-auto-update-switch"
checked={value.RepositoryAutomaticUpdates}
label="GitOps updates"
tooltip="When enabled, at each polling interval or webhook invocation, if the

View file

@ -72,6 +72,7 @@ export function AutoUpdateSettings({
<div className="col-sm-12">
<SwitchField
name="forcePullImage"
data-cy="gitops-force-pull-image-switch"
featureId={FeatureId.STACK_PULL_IMAGE}
checked={value.ForcePullImage || false}
label="Re-pull image"

View file

@ -20,6 +20,7 @@ export function ForceDeploymentSwitch({
<div className="col-sm-12">
<SwitchField
name="forceUpdate"
data-cy="gitops-force-redeployment-switch"
featureId={FeatureId.FORCE_REDEPLOYMENT}
checked={checked}
label={label}

View file

@ -26,6 +26,7 @@ export function IntervalField({
>
<Input
mRef={ref}
data-cy="repository-fetch-interval-input"
id="repository_fetch_interval"
name="repository_fetch_interval"
placeholder="5m"

View file

@ -32,7 +32,11 @@ export function WebhookSettings({
>
<div className="flex items-center gap-2">
<span className="text-muted">{truncateLeftRight(url)}</span>
<CopyButton copyText={url} color="light">
<CopyButton
copyText={url}
color="light"
data-cy="copy-webhook-link-button"
>
Copy link
</CopyButton>
</div>

View file

@ -71,6 +71,7 @@ export function ComposePathField({
) : (
<Input
value={inputValue}
data-cy="stack-repository-path-input"
onChange={(e) => {
updateInputValue(e.target.value);
}}

View file

@ -50,6 +50,7 @@ export function PathSelector({
placeholder={placeholder}
readOnly={readOnly}
inputId={inputId}
data-cy="git-ops-path-selector"
/>
);
}

View file

@ -121,6 +121,7 @@ export function GitForm({
<div className="col-sm-12">
<SwitchField
label="Skip TLS Verification"
data-cy="gitops-skip-tls-verification-switch"
checked={value.TLSSkipVerify || false}
onChange={(value) => handleChange({ TLSSkipVerify: value })}
name="TLSSkipVerify"

View file

@ -92,6 +92,7 @@ export function GitFormUrlField({
<Button
onClick={onRefresh}
data-cy="component-gitUrlRefreshButton"
size="medium"
className="vertical-center"
color="light"

View file

@ -72,6 +72,7 @@ export function RefField({
>
<Input
id={inputId}
data-cy="repository-reference-input"
value={inputValue}
onChange={(e) => updateInputValue(e.target.value)}
placeholder="refs/heads/main"

View file

@ -55,6 +55,7 @@ export function RelativePathFieldset({
<div className="col-sm-12">
<SwitchField
name="EnableRelativePaths"
data-cy="gitops-enable-relative-paths-switch"
label="Enable relative path volumes"
labelClass="col-sm-3 col-lg-2"
tooltip="Enabling this means you can specify relative path volumes in your Compose files, with Portainer pulling the content from your git repository to the environment the stack is deployed to."
@ -86,6 +87,7 @@ export function RelativePathFieldset({
>
<Input
name="FilesystemPath"
data-cy="relative-path-filesystem-path-input"
placeholder="/mnt"
disabled={isEditing || !enableFsPath0}
value={value.FilesystemPath}
@ -114,6 +116,7 @@ export function RelativePathFieldset({
<div className="col-sm-12">
<SwitchField
name="EnablePerDeviceConfigs"
data-cy="gitops-enable-per-device-configs-switch"
label="GitOps Edge configurations"
labelClass="col-sm-3 col-lg-2"
tooltip="By enabling the GitOps Edge Configurations feature, you gain the ability to define relative path volumes in your configuration files. Portainer will then automatically fetch the content from your git repository by matching the folder name or file name with the Portainer Edge ID, and apply it to the environment where the stack is deployed"
@ -148,6 +151,7 @@ export function RelativePathFieldset({
>
<Input
name="FilesystemPath"
data-cy="per-device-configs-filesystem-path-input"
placeholder="/mnt"
disabled={isEditing || !enableFsPath1}
value={value.FilesystemPath}
@ -210,6 +214,7 @@ export function RelativePathFieldset({
<FormControl label="Device matching rule">
<Select
value={value.PerDeviceConfigsMatchType}
data-cy="per-device-configs-match-type-select"
onChange={(e) =>
innerOnChange({
PerDeviceConfigsMatchType: getPerDevConfigsFilterType(
@ -242,6 +247,7 @@ export function RelativePathFieldset({
<FormControl label="Group matching rule">
<Select
value={value.PerDeviceConfigsGroupMatchType}
data-cy="per-device-configs-group-match-type-select"
onChange={(e) =>
innerOnChange({
PerDeviceConfigsGroupMatchType:

View file

@ -38,7 +38,12 @@ const columns = [
enableSorting: false,
cell: ({ row, getValue }) =>
getValue() ? (
<Button color="link" onClick={() => row.toggleExpanded()} icon={Search}>
<Button
color="link"
onClick={() => row.toggleExpanded()}
icon={Search}
data-cy={`activity-logs-inspect_${row.index}`}
>
inspect
</Button>
) : null,
@ -95,6 +100,7 @@ export function ActivityLogsTable({
totalCount={totalItems}
disableSelect
renderSubRow={(row) => <SubRow item={row.original} />}
data-cy="activity-logs-datatable"
/>
);
}

View file

@ -33,6 +33,7 @@ export function FilterBar({
icon={DownloadIcon}
onClick={onExport}
className="!ml-0"
data-cy="activity-logs-export-csv-button"
>
Export as CSV
</Button>

View file

@ -52,6 +52,7 @@ export function AuthenticationLogsTable({
isServerSidePagination
totalCount={totalItems}
disableSelect
data-cy="authentication-logs-datatable"
/>
);
}

View file

@ -53,6 +53,7 @@ export function NotificationsView() {
)}
getRowId={(row) => row.id}
highlightedItemId={activeItemId}
data-cy="notifications-datatable"
/>
</>
);
@ -65,6 +66,7 @@ function TableActions({ selectedRows }: { selectedRows: ToastNotification[] }) {
<DeleteButton
onConfirmed={() => handleRemove()}
disabled={selectedRows.length === 0}
data-cy="remove-notifications-button"
confirmMessage="Are you sure you want to remove the selected notifications?"
/>
);

View file

@ -46,6 +46,7 @@ export function GitlabProjectTable({
value.map(({ Id }) => `${Id}`)
)}
isRowSelectable={({ original: item }) => item.RegistryEnabled}
data-cy="gitlab-projects-datatable"
/>
);
}

View file

@ -35,6 +35,7 @@ export function RegistriesDatatable() {
</>
)}
isRowSelectable={(row) => !!row.original.Id}
data-cy="registries-datatable"
/>
);
}

View file

@ -31,6 +31,7 @@ export function DefaultRegistryAction() {
<div className="vertical-center">
<Button
color="danger"
data-cy="hide-default-registry-button"
icon={EyeOff}
onClick={() => handleShowOrHide(true)}
disabled={isLimited}
@ -47,7 +48,11 @@ export function DefaultRegistryAction() {
</div>
) : (
<div className="vertical-center">
<Button icon={Eye} onClick={() => handleShowOrHide(false)}>
<Button
data-cy="show-default-registry-button"
icon={Eye}
onClick={() => handleShowOrHide(false)}
>
Show for all users
</Button>
<Tooltip

View file

@ -9,7 +9,7 @@ import { Button } from '@@/buttons';
import { BEFeatureIndicator } from '@@/BEFeatureIndicator';
import { DecoratedRegistry } from '../types';
import { RegistryId, RegistryTypes } from '../../../types/registry';
import { RegistryTypes } from '../../../types/registry';
import { columnHelper } from './helper';
import { DefaultRegistryAction } from './DefaultRegistryAction';
@ -32,19 +32,17 @@ function Cell({
return <DefaultRegistryAction />;
}
return <BrowseButton registryId={item.Id} registryType={item.Type} />;
return <BrowseButton registry={item} />;
}
export function BrowseButton({
registryId,
registryType,
registry,
environmentId,
}: {
registryId: RegistryId;
registryType: RegistryTypes;
registry: DecoratedRegistry;
environmentId?: EnvironmentId;
}) {
const canBrowse = !nonBrowsableTypes.includes(registryType);
const canBrowse = !nonBrowsableTypes.includes(registry.Type);
if (!canBrowse) {
return null;
@ -58,10 +56,12 @@ export function BrowseButton({
as={Link}
props={{
to: 'portainer.registries.registry.repositories',
params: { id: registryId, endpointId: environmentId },
params: { id: registry.Id, endpointId: environmentId },
'data-cy': `browse-registry-link-${registry.Name}`,
}}
disabled={isLimited}
icon={Search}
data-cy={`browse-registry-button-${registry.Name}`}
>
Browse
</Button>

View file

@ -36,7 +36,11 @@ export function NameCell({
return (
<>
{isEdgeAdminQuery.isAdmin && hasLink ? (
<Link to="portainer.registries.registry" params={{ id: item.Id }}>
<Link
to="portainer.registries.registry"
params={{ id: item.Id }}
data-cy={`registry-link-${item.Name}`}
>
{item.Name}
</Link>
) : (

View file

@ -34,6 +34,7 @@ export function EnvironmentRegistriesDatatable() {
titleIcon={Radio}
renderTableActions={() => <AddButton />}
disableSelect
data-cy="environment-registries-datatable"
/>
);
}

View file

@ -40,17 +40,18 @@ function Cell({
color="link"
icon={Users}
as={Link}
props={{ to: '.access', params: { id: item.Id } }}
props={{
to: '.access',
params: { id: item.Id },
'data-cy': `manage-access-link-${item.Name}`,
}}
data-cy={`registry-manage-access-button-${item.Name}`}
>
Manage access
</Button>
</Authorized>
)}
<BrowseButton
registryId={item.Id}
registryType={item.Type}
environmentId={environmentId}
/>
<BrowseButton registry={item} environmentId={environmentId} />
</>
);
}

View file

@ -41,6 +41,7 @@ export function TagsDatatable({
<DeleteButton
confirmMessage="Are you sure you want to remove the selected tags?"
onConfirmed={() => onRemove(selectedItems)}
data-cy="remove-registry-tags-button"
/>
)
}
@ -52,6 +53,7 @@ export function TagsDatatable({
},
table: 'registry-repository-tags',
})}
data-cy="registry-tags-datatable"
/>
);
}

View file

@ -43,6 +43,7 @@ function ActionsCell({
color="link"
icon={TagIcon}
onClick={() => state.setName(item.Name, tagDetails)}
data-cy={`retag-${item.Name}`}
>
Retag
</Button>
@ -101,12 +102,23 @@ function EditTag({
}}
autoFocus
onClick={(e) => e.stopPropagation()}
data-cy={`retag-input-${initialName}`}
/>
{errors.name && <FormError>{errors.name}</FormError>}
<Button color="none" icon={X} onClick={onCancel} />
<Button type="submit" color="none" icon={Check} />
<Button
color="none"
icon={X}
onClick={onCancel}
data-cy={`retag-cancel-${initialName}`}
/>
<Button
type="submit"
color="none"
icon={Check}
data-cy={`retag-submit-${initialName}`}
/>
</Form>
)}
</Formik>

View file

@ -17,6 +17,7 @@ const columns = [
'Name',
'portainer.registries.registry.repository.tag',
'tag',
'registry-tag-name',
(item) => item.Name
),
helper.display({

View file

@ -18,6 +18,7 @@ export function RepositoriesDatatable({ dataset }: { dataset?: Repository[] }) {
settingsManager={tableState}
emptyContentLabel="No repository available."
disableSelect
data-cy="registry-repositories-datatable"
/>
);
}

View file

@ -49,6 +49,7 @@ function NameCell({ getValue }: CellContext<Repository, string>) {
to="portainer.registries.registry.repository"
params={{ repository: name, endpointId: environmentId }}
title={name}
data-cy={`repository-name-link-${name}`}
>
{name}
</Link>

View file

@ -14,6 +14,7 @@ export function SaveAuthSettingsButton({ onSubmit, isLoading }: Props) {
<div className="col-sm-12">
<LoadingButton
loadingText="Saving..."
data-cy="save-auth-settings-button"
isLoading={isLoading}
onClick={() => onSubmit()}
>

View file

@ -24,6 +24,7 @@ export function LDAPGroupsTable({ dataset }: { dataset?: Value[] }) {
settingsManager={tableState}
emptyContentLabel="No groups found."
disableSelect
data-cy="ldap-groups-datatable"
/>
);
}

View file

@ -23,6 +23,7 @@ export function LDAPUsersTable({ dataset }: { dataset?: string[] }) {
settingsManager={tableState}
emptyContentLabel="No users found."
disableSelect
data-cy="ldap-users-datatable"
/>
);
}

View file

@ -63,6 +63,7 @@ export function AutoEnvCreationSettingsForm({ settings }: Props) {
<div className="col-sm-12">
<LoadingButton
loadingText="generating..."
data-cy="save-auto-env-settings-button"
isLoading={mutation.isLoading}
disabled={!isValid || !dirty}
className="!ml-0"

View file

@ -18,6 +18,7 @@ export function EnabledWaitingRoomSwitch() {
>
<Switch
id="edge_waiting_room"
data-cy="edge-waiting-room-switch"
name="EnableWaitingRoom"
className="space-right"
checked={inputProps.value}

View file

@ -69,6 +69,7 @@ export function EdgeComputeSettings({ settings, onSubmit }: Props) {
>
<Switch
id="edge_enable"
data-cy="edge-enable-switch"
name="edge_enable"
className="space-right"
checked={values.EnableEdgeComputeFeatures}
@ -103,6 +104,7 @@ export function EdgeComputeSettings({ settings, onSubmit }: Props) {
>
<Switch
id="edge_enforce_id"
data-cy="edge-enforce-id-switch"
name="edge_enforce_id"
className="space-right"
checked={values.EnforceEdgeID}

Some files were not shown because too many files have changed in this diff Show more