From d7a19d58fa7ccf46c68c2340de417198126bacd9 Mon Sep 17 00:00:00 2001 From: Alex Freska Date: Wed, 5 Jun 2024 09:45:13 -0400 Subject: [PATCH] fix: renterd dialogs, bucket policy, delete --- .changeset/lovely-teachers-move.md | 5 ++ .changeset/tender-pants-decide.md | 5 ++ apps/hostd-e2e/src/fixtures/login.ts | 2 +- .../src/fixtures/navigateToConfig.ts | 4 +- .../src/fixtures/navigateToDashboard.ts | 2 +- apps/hostd-e2e/src/specs/login.spec.ts | 2 +- apps/renterd-e2e/src/fixtures/buckets.ts | 47 +++++++++++++++++++ apps/renterd-e2e/src/fixtures/login.ts | 2 +- .../src/fixtures/navigateToBuckets.ts | 2 +- .../src/fixtures/navigateToConfig.ts | 4 +- apps/renterd-e2e/src/specs/buckets.spec.ts | 29 ++++++++++++ apps/renterd-e2e/src/specs/login.spec.ts | 2 +- .../components/Files/BucketContextMenu.tsx | 7 ++- .../config/useAutopilotEvaluations.tsx | 14 ++---- apps/renterd/contexts/config/useForm.tsx | 1 - apps/renterd/contexts/dialog.tsx | 30 ++++++------ apps/walletd-e2e/src/fixtures/login.ts | 2 +- libs/design-system/src/app/AppNavbar.tsx | 2 +- 18 files changed, 126 insertions(+), 36 deletions(-) create mode 100644 .changeset/lovely-teachers-move.md create mode 100644 .changeset/tender-pants-decide.md create mode 100644 apps/renterd-e2e/src/fixtures/buckets.ts create mode 100644 apps/renterd-e2e/src/specs/buckets.spec.ts diff --git a/.changeset/lovely-teachers-move.md b/.changeset/lovely-teachers-move.md new file mode 100644 index 000000000..525cbed1e --- /dev/null +++ b/.changeset/lovely-teachers-move.md @@ -0,0 +1,5 @@ +--- +'renterd': patch +--- + +Fixed an issue where selecting a bucket context menu option would also navigate into the bucket. Closes https://github.com/SiaFoundation/renterd/issues/1277 diff --git a/.changeset/tender-pants-decide.md b/.changeset/tender-pants-decide.md new file mode 100644 index 000000000..2edac2373 --- /dev/null +++ b/.changeset/tender-pants-decide.md @@ -0,0 +1,5 @@ +--- +'renterd': patch +--- + +Fixed an issue that broke some dialogs including the bucket policy and bucket delete dialogs. Closes https://github.com/SiaFoundation/renterd/issues/1277 diff --git a/apps/hostd-e2e/src/fixtures/login.ts b/apps/hostd-e2e/src/fixtures/login.ts index 11ce3ab1a..b07160115 100644 --- a/apps/hostd-e2e/src/fixtures/login.ts +++ b/apps/hostd-e2e/src/fixtures/login.ts @@ -13,5 +13,5 @@ export async function login({ page }: { page: Page }) { process.env.HOSTD_E2E_TEST_API_PASSWORD ) await page.locator('input[name=password]').press('Enter') - await expect(page.locator('#navbar').getByText('Overview')).toBeVisible() + await expect(page.getByTestId('navbar').getByText('Overview')).toBeVisible() } diff --git a/apps/hostd-e2e/src/fixtures/navigateToConfig.ts b/apps/hostd-e2e/src/fixtures/navigateToConfig.ts index bb68cb2ff..5cfb6114d 100644 --- a/apps/hostd-e2e/src/fixtures/navigateToConfig.ts +++ b/apps/hostd-e2e/src/fixtures/navigateToConfig.ts @@ -2,5 +2,7 @@ import { Page, expect } from '@playwright/test' export async function navigateToConfig({ page }: { page: Page }) { await page.getByLabel('Configuration').click() - await expect(page.locator('#navbar').getByText('Configuration')).toBeVisible() + await expect( + page.getByTestId('navbar').getByText('Configuration') + ).toBeVisible() } diff --git a/apps/hostd-e2e/src/fixtures/navigateToDashboard.ts b/apps/hostd-e2e/src/fixtures/navigateToDashboard.ts index 06e4cf108..604eccf5d 100644 --- a/apps/hostd-e2e/src/fixtures/navigateToDashboard.ts +++ b/apps/hostd-e2e/src/fixtures/navigateToDashboard.ts @@ -2,5 +2,5 @@ import { Page, expect } from '@playwright/test' export async function navigateToDashboard({ page }: { page: Page }) { await page.getByLabel('Overview').click() - await expect(page.locator('#navbar').getByText('Overview')).toBeVisible() + await expect(page.getByTestId('navbar').getByText('Overview')).toBeVisible() } diff --git a/apps/hostd-e2e/src/specs/login.spec.ts b/apps/hostd-e2e/src/specs/login.spec.ts index 8f3297d2e..46371d653 100644 --- a/apps/hostd-e2e/src/specs/login.spec.ts +++ b/apps/hostd-e2e/src/specs/login.spec.ts @@ -3,5 +3,5 @@ import { login } from '../fixtures/login' test('login', async ({ page }) => { await login({ page }) - await expect(page.locator('#navbar').getByText('Overview')).toBeVisible() + await expect(page.getByTestId('navbar').getByText('Overview')).toBeVisible() }) diff --git a/apps/renterd-e2e/src/fixtures/buckets.ts b/apps/renterd-e2e/src/fixtures/buckets.ts new file mode 100644 index 000000000..36dea103e --- /dev/null +++ b/apps/renterd-e2e/src/fixtures/buckets.ts @@ -0,0 +1,47 @@ +import { Page, expect } from '@playwright/test' +import { navigateToBuckets } from './navigateToBuckets' +import { fillTextInputByName } from './textInput' +import { clearToasts } from './clearToasts' + +export async function createBucket(page: Page, name: string) { + await navigateToBuckets({ page }) + await expect(page.getByTestId('navbar').getByText('Buckets')).toBeVisible() + await page.getByText('Create bucket').click() + await fillTextInputByName(page, 'name', name) + await page.locator('input[name=name]').press('Enter') + await expect(page.getByRole('dialog')).toBeHidden() + await expect(page.getByText('Bucket created')).toBeVisible() + await clearToasts({ page }) + await expect(page.getByRole('cell', { name })).toBeVisible() +} + +export async function deleteBucket(page: Page, name: string) { + await openBucketContextMenu(page, name) + await page.getByRole('menuitem', { name: 'Delete bucket' }).click() + await fillTextInputByName(page, 'name', name) + await page.locator('input[name=name]').press('Enter') + await expect(page.getByRole('dialog')).toBeHidden() + await bucketNotInList(page, name) +} + +export async function deleteBucketIfExists(page: Page, name: string) { + const doesBucketExist = await page + .getByRole('table') + .getByText(name) + .isVisible() + if (doesBucketExist) { + await deleteBucket(page, name) + } +} + +export async function openBucketContextMenu(page: Page, name: string) { + await page.getByRole('row', { name }).getByRole('button').first().click() +} + +export async function bucketInList(page: Page, name: string) { + await expect(page.getByRole('table').getByText(name)).toBeVisible() +} + +export async function bucketNotInList(page: Page, name: string) { + await expect(page.getByRole('table').getByText(name)).toBeHidden() +} diff --git a/apps/renterd-e2e/src/fixtures/login.ts b/apps/renterd-e2e/src/fixtures/login.ts index 49426c487..b49fdf1f0 100644 --- a/apps/renterd-e2e/src/fixtures/login.ts +++ b/apps/renterd-e2e/src/fixtures/login.ts @@ -13,5 +13,5 @@ export async function login({ page }: { page: Page }) { process.env.RENTERD_E2E_TEST_API_PASSWORD ) await page.locator('input[name=password]').press('Enter') - await expect(page.locator('#navbar').getByText('Buckets')).toBeVisible() + await expect(page.getByTestId('navbar').getByText('Buckets')).toBeVisible() } diff --git a/apps/renterd-e2e/src/fixtures/navigateToBuckets.ts b/apps/renterd-e2e/src/fixtures/navigateToBuckets.ts index b11f4b477..7c6ef4b16 100644 --- a/apps/renterd-e2e/src/fixtures/navigateToBuckets.ts +++ b/apps/renterd-e2e/src/fixtures/navigateToBuckets.ts @@ -2,5 +2,5 @@ import { Page, expect } from '@playwright/test' export async function navigateToBuckets({ page }: { page: Page }) { await page.getByLabel('Files').click() - await expect(page.locator('#navbar').getByText('Buckets')).toBeVisible() + await expect(page.getByTestId('navbar').getByText('Buckets')).toBeVisible() } diff --git a/apps/renterd-e2e/src/fixtures/navigateToConfig.ts b/apps/renterd-e2e/src/fixtures/navigateToConfig.ts index bb68cb2ff..5cfb6114d 100644 --- a/apps/renterd-e2e/src/fixtures/navigateToConfig.ts +++ b/apps/renterd-e2e/src/fixtures/navigateToConfig.ts @@ -2,5 +2,7 @@ import { Page, expect } from '@playwright/test' export async function navigateToConfig({ page }: { page: Page }) { await page.getByLabel('Configuration').click() - await expect(page.locator('#navbar').getByText('Configuration')).toBeVisible() + await expect( + page.getByTestId('navbar').getByText('Configuration') + ).toBeVisible() } diff --git a/apps/renterd-e2e/src/specs/buckets.spec.ts b/apps/renterd-e2e/src/specs/buckets.spec.ts new file mode 100644 index 000000000..5376bb7dd --- /dev/null +++ b/apps/renterd-e2e/src/specs/buckets.spec.ts @@ -0,0 +1,29 @@ +import { test, expect } from '@playwright/test' +import { navigateToBuckets } from '../fixtures/navigateToBuckets' +import { login } from '../fixtures/login' +import { + bucketInList, + createBucket, + deleteBucket, + deleteBucketIfExists, + openBucketContextMenu, +} from '../fixtures/buckets' + +test('can change a buckets policy', async ({ page }) => { + await login({ page }) + await navigateToBuckets({ page }) + await openBucketContextMenu(page, 'default') + await page.getByRole('menuitem', { name: 'Change policy' }).click() + await page.getByRole('heading', { name: 'Change Policy: default' }).click() + await page.getByRole('combobox').selectOption('public') + await page.getByRole('button', { name: 'Update policy' }).click() + await expect(page.getByText('Bucket policy has been updated')).toBeVisible() + await bucketInList(page, 'default') +}) + +test('can create and delete a bucket', async ({ page }) => { + await login({ page }) + await deleteBucketIfExists(page, 'my-new-bucket') + await createBucket(page, 'my-new-bucket') + await deleteBucket(page, 'my-new-bucket') +}) diff --git a/apps/renterd-e2e/src/specs/login.spec.ts b/apps/renterd-e2e/src/specs/login.spec.ts index e1d4672e2..048ba23ae 100644 --- a/apps/renterd-e2e/src/specs/login.spec.ts +++ b/apps/renterd-e2e/src/specs/login.spec.ts @@ -3,5 +3,5 @@ import { login } from '../fixtures/login' test('login', async ({ page }) => { await login({ page }) - await expect(page.locator('#navbar').getByText('Buckets')).toBeVisible() + await expect(page.getByTestId('navbar').getByText('Buckets')).toBeVisible() }) diff --git a/apps/renterd/components/Files/BucketContextMenu.tsx b/apps/renterd/components/Files/BucketContextMenu.tsx index 72a9d8c0c..921629038 100644 --- a/apps/renterd/components/Files/BucketContextMenu.tsx +++ b/apps/renterd/components/Files/BucketContextMenu.tsx @@ -21,7 +21,12 @@ export function BucketContextMenu({ name }: Props) { } - contentProps={{ align: 'start' }} + contentProps={{ + align: 'start', + onClick: (e) => { + e.stopPropagation() + }, + }} > Actions resources: Resources isAutopilotEnabled: boolean - configViewMode: ConfigViewMode estimatedSpendingPerMonth: BigNumber }) { const values = form.watch() const renterdState = useBusState() const hasDataToEvaluate = useMemo(() => { + if (!isAutopilotEnabled) { + return false + } if (!checkIfAllResourcesLoaded(resources)) { return false } @@ -46,7 +42,7 @@ export function useAutopilotEvaluations({ return false } return true - }, [form.formState.isValid, resources, renterdState.data]) + }, [isAutopilotEnabled, form.formState.isValid, resources, renterdState.data]) // We need to pass valid settings data into transformUp to get the payloads. // The form can be invalid or have empty fields depending on the mode, so we diff --git a/apps/renterd/contexts/config/useForm.tsx b/apps/renterd/contexts/config/useForm.tsx index 6a19a65a9..7ce9c30b5 100644 --- a/apps/renterd/contexts/config/useForm.tsx +++ b/apps/renterd/contexts/config/useForm.tsx @@ -68,7 +68,6 @@ export function useForm({ resources }: { resources: Resources }) { form, resources, isAutopilotEnabled, - configViewMode, estimatedSpendingPerMonth, }) diff --git a/apps/renterd/contexts/dialog.tsx b/apps/renterd/contexts/dialog.tsx index b541b1c64..aeb33f18c 100644 --- a/apps/renterd/contexts/dialog.tsx +++ b/apps/renterd/contexts/dialog.tsx @@ -149,7 +149,7 @@ export function Dialogs() { address={wallet.data?.address} isValidating={wallet.isValidating} open={dialog === 'addressDetails'} - onOpenChange={(val) => (val ? openDialog(dialog) : closeDialog())} + onOpenChange={onOpenChange} /> (val ? openDialog(dialog) : closeDialog())} + onOpenChange={onOpenChange} /> (val ? openDialog(dialog) : closeDialog())} + onOpenChange={onOpenChange} /> (val ? openDialog(dialog) : closeDialog())} + onOpenChange={onOpenChange} /> (val ? openDialog(dialog) : closeDialog())} + onOpenChange={onOpenChange} /> (val ? openDialog(dialog) : closeDialog())} + onOpenChange={onOpenChange} /> (val ? openDialog(dialog) : closeDialog())} + onOpenChange={onOpenChange} /> (val ? openDialog(dialog) : closeDialog())} + onOpenChange={onOpenChange} /> (val ? openDialog(dialog) : closeDialog())} + onOpenChange={onOpenChange} /> (val ? openDialog(dialog) : closeDialog())} + onOpenChange={onOpenChange} /> (val ? openDialog(dialog) : closeDialog())} + onOpenChange={onOpenChange} /> (val ? openDialog(dialog) : closeDialog())} + onOpenChange={onOpenChange} /> (val ? openDialog(dialog) : closeDialog())} + onOpenChange={onOpenChange} /> (val ? openDialog(dialog) : closeDialog())} + onOpenChange={onOpenChange} /> (val ? openDialog(dialog) : closeDialog())} + onOpenChange={onOpenChange} />