Files
supabase/e2e/studio/features/storage.spec.ts
Ali Waseem fef1f043ad chore: added tests for users and minor refactor (#41279)
* added tests for users and minor refactor

* fix helpers

* addressed PR feedback

* remove before await

* missed the await
2025-12-11 13:31:43 -07:00

254 lines
8.0 KiB
TypeScript

import { expect } from '@playwright/test'
import path from 'path'
import { test } from '../utils/test.js'
import { waitForApiResponse } from '../utils/wait-for-response.js'
import {
createBucket,
createFolder,
deleteAllBuckets,
deleteBucket,
deleteItem,
downloadFile,
navigateToBucket,
renameItem,
uploadFile,
} from '../utils/storage-helpers.js'
import { dismissToastsIfAny } from '../utils/dismiss-toast.js'
const bucketNamePrefix = 'pw_bucket'
test.describe.serial('Storage', () => {
test.beforeEach(async ({ page, ref }) => {
await deleteAllBuckets(page, ref)
})
test('can navigate to storage page', async ({ page, ref }) => {
await expect(
page.getByRole('button', { name: 'New bucket' }),
'New bucket button should be visible'
).toBeVisible()
// Verify we're on the storage files page
await expect(page).toHaveURL(new RegExp(`/project/${ref}/storage/files`))
})
test('can create a private bucket', async ({ page, ref }) => {
const bucketName = `${bucketNamePrefix}_private`
await createBucket(page, ref, bucketName, false)
// Verify it's marked as private (no "Public" badge should be visible)
const bucketRow = page.getByRole('row').filter({ hasText: bucketName })
await expect(bucketRow, 'Bucket row should be visible').toBeVisible()
await expect(
bucketRow.getByText('Public'),
'Private bucket should not have Public badge'
).not.toBeVisible()
})
test('can create a public bucket', async ({ page, ref }) => {
const bucketName = `${bucketNamePrefix}_public`
await createBucket(page, ref, bucketName, true)
// Verify it's marked as public - wait for the badge to appear
const bucketRow = page.getByRole('row').filter({ hasText: bucketName })
await expect(bucketRow, 'Bucket row should be visible').toBeVisible()
// The Public badge should be visible within the bucket row
await expect(
bucketRow.getByText('Public', { exact: true }),
'Bucket should be marked as Public'
).toBeVisible()
})
test('can edit bucket settings', async ({ page, ref }) => {
const bucketName = `${bucketNamePrefix}_edit`
// Create a private bucket
await createBucket(page, ref, bucketName, false)
// Navigate to the bucket
await navigateToBucket(page, ref, bucketName)
// Open edit bucket dropdown
await page.getByRole('button', { name: 'Edit bucket' }).click()
await page.getByRole('menuitem', { name: 'Bucket settings' }).click()
// Toggle public setting
const publicToggle = page.getByRole('switch', { name: 'Public bucket' })
await expect(publicToggle, 'Public toggle should be visible').toBeVisible()
await publicToggle.click()
// Save changes
const apiPromise = waitForApiResponse(page, 'storage', ref, `buckets/${bucketName}`, {
method: 'PATCH',
})
await page.getByRole('button', { name: 'Save' }).click()
await apiPromise
// Verify the bucket is now public
await expect(
page.getByText('Public').first(),
'Bucket should now be marked as Public'
).toBeVisible()
})
test('can delete a bucket', async ({ page, ref }) => {
const bucketName = `${bucketNamePrefix}_delete`
// Create a bucket
await createBucket(page, ref, bucketName, false)
// Delete it
await deleteBucket(page, ref, bucketName)
// Verify it's gone
await expect(
page.getByRole('row').filter({ hasText: bucketName }),
'Bucket should not be visible after deletion'
).not.toBeVisible()
})
test('can search for buckets', async ({ page, ref }) => {
const bucketName1 = `${bucketNamePrefix}_search_1`
const bucketName2 = `${bucketNamePrefix}_search_2`
// Create two buckets
await createBucket(page, ref, bucketName1, false)
await dismissToastsIfAny(page)
await createBucket(page, ref, bucketName2, false)
// Search for first bucket
const searchInput = page.getByPlaceholder('Search for a bucket')
await searchInput.fill('search_1')
// Verify only first bucket is visible
await expect(
page.getByRole('row').filter({ hasText: bucketName1 }),
'First bucket should be visible in search results'
).toBeVisible()
await expect(
page.getByRole('row').filter({ hasText: bucketName2 }),
'Second bucket should not be visible in search results'
).not.toBeVisible()
// Clear search
await searchInput.clear()
// Verify both buckets are visible
await expect(
page.getByRole('row').filter({ hasText: bucketName1 }),
'First bucket should be visible after clearing search'
).toBeVisible()
await expect(
page.getByRole('row').filter({ hasText: bucketName2 }),
'Second bucket should be visible after clearing search'
).toBeVisible()
})
test('can upload a file', async ({ page, ref }) => {
const bucketName = `${bucketNamePrefix}_upload`
const fileName = 'test-file.txt'
// Create a bucket and navigate to it
await createBucket(page, ref, bucketName, false)
await navigateToBucket(page, ref, bucketName)
// Upload a file
const filePath = path.join(import.meta.dirname, 'files', fileName)
await uploadFile(page, filePath, fileName)
// Clean up
await deleteBucket(page, ref, bucketName)
})
test('can create a folder', async ({ page, ref }) => {
const bucketName = `${bucketNamePrefix}_folder`
const folderName = 'test_folder'
// Create a bucket and navigate to it
await createBucket(page, ref, bucketName, false)
await navigateToBucket(page, ref, bucketName)
// Create a folder
await createFolder(page, folderName)
})
test('can rename a file', async ({ page, ref }) => {
const bucketName = `${bucketNamePrefix}_rename_file`
const fileName = 'test-file.txt'
const newFileName = 'renamed-file.txt'
// Create a bucket, navigate to it, and upload a file
await createBucket(page, ref, bucketName, false)
await navigateToBucket(page, ref, bucketName)
const filePath = path.join(import.meta.dirname, 'files', fileName)
await uploadFile(page, filePath, fileName)
// Rename the file
await renameItem(page, fileName, newFileName)
// Clean up
await deleteBucket(page, ref, bucketName)
})
test('can rename a folder', async ({ page, ref }) => {
const bucketName = `${bucketNamePrefix}_rename_folder`
const folderName = 'old_folder'
const newFolderName = 'new_folder'
// Create a bucket, navigate to it, and create a folder
await createBucket(page, ref, bucketName, false)
await navigateToBucket(page, ref, bucketName)
await createFolder(page, folderName)
// Rename the folder
await renameItem(page, folderName, newFolderName)
})
test('can delete a file', async ({ page, ref }) => {
const bucketName = `${bucketNamePrefix}_delete_file`
const fileName = 'test-file.txt'
// Create a bucket, navigate to it, and upload a file
await createBucket(page, ref, bucketName, false)
await navigateToBucket(page, ref, bucketName)
const filePath = path.join(import.meta.dirname, 'files', fileName)
await uploadFile(page, filePath, fileName)
// Delete the file
await deleteItem(page, fileName)
})
test('can delete a folder', async ({ page, ref }) => {
const bucketName = `${bucketNamePrefix}_delete_folder`
const folderName = 'test_folder'
// Create a bucket, navigate to it, and create a folder
await createBucket(page, ref, bucketName, false)
await navigateToBucket(page, ref, bucketName)
await createFolder(page, folderName)
// Delete the folder
await deleteItem(page, folderName)
})
test('can download a file', async ({ page, ref }) => {
const bucketName = `${bucketNamePrefix}_download`
const fileName = 'test-file.txt'
// Create a bucket, navigate to it, and upload a file
await createBucket(page, ref, bucketName, false)
await navigateToBucket(page, ref, bucketName)
const filePath = path.join(import.meta.dirname, 'files', fileName)
await uploadFile(page, filePath, fileName)
// Download the file
await downloadFile(page, fileName)
})
})