mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-29 07:20:43 +00:00
146 lines
4.8 KiB
TypeScript
146 lines
4.8 KiB
TypeScript
import { expect, test, type Page } from '@playwright/test'
|
|
import { signIn } from './session'
|
|
|
|
interface MockEntry {
|
|
key: string
|
|
isDir: boolean
|
|
size: number
|
|
lastModified: number
|
|
}
|
|
|
|
async function mockDriveApi(page: Page, initialEntries: MockEntry[] = []) {
|
|
let entries = [...initialEntries]
|
|
|
|
await page.route('**/v1/s3/buckets', (route) => {
|
|
if (route.request().method() === 'GET') {
|
|
return route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({
|
|
buckets: [{ name: 'test-bucket', createdAt: Date.now() }],
|
|
}),
|
|
})
|
|
}
|
|
return route.continue()
|
|
})
|
|
|
|
await page.route('**/v1/s3/buckets/test-bucket/objects**', (route) => {
|
|
const url = new URL(route.request().url())
|
|
const method = route.request().method()
|
|
|
|
if (method === 'GET') {
|
|
const prefix = url.searchParams.get('prefix') || ''
|
|
const filtered = entries.filter((e) => {
|
|
if (!prefix) return !e.key.includes('/') || e.key.endsWith('/') && e.key.indexOf('/') === e.key.length - 1
|
|
return e.key.startsWith(prefix)
|
|
})
|
|
return route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({
|
|
objects: filtered,
|
|
}),
|
|
})
|
|
}
|
|
|
|
if (method === 'POST') {
|
|
const body = route.request().postDataJSON()
|
|
const key = body?.key || 'new-item'
|
|
const isDir = key.endsWith('/')
|
|
entries.push({
|
|
key,
|
|
isDir,
|
|
size: isDir ? 0 : 128,
|
|
lastModified: Date.now(),
|
|
})
|
|
return route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({ url: 'http://localhost:5173/mock-upload' }),
|
|
})
|
|
}
|
|
|
|
if (method === 'DELETE') {
|
|
const key = decodeURIComponent(url.pathname.split('/objects/')[1] || '')
|
|
entries = entries.filter((e) => e.key !== key && !e.key.startsWith(key))
|
|
return route.fulfill({ status: 200, contentType: 'application/json', body: '{}' })
|
|
}
|
|
|
|
return route.continue()
|
|
})
|
|
|
|
await page.route('http://localhost:5173/mock-upload', (route) => {
|
|
return route.fulfill({ status: 200 })
|
|
})
|
|
}
|
|
|
|
test.describe('Workspace Drive component', () => {
|
|
test('signed-out visitor sees sign-in prompt', async ({ page }) => {
|
|
await page.setViewportSize({ width: 1440, height: 900 })
|
|
await page.goto('/drive')
|
|
await expect(page.getByText(/sign in to open your drive/i)).toBeVisible({ timeout: 15_000 })
|
|
})
|
|
|
|
test('signed-in user can view bucket, navigate files, and toggle grid/list', async ({ page }) => {
|
|
await signIn(page)
|
|
await mockDriveApi(page, [
|
|
{ key: 'documents/', isDir: true, size: 0, lastModified: Date.now() - 3600000 },
|
|
{ key: 'hello.txt', isDir: false, size: 1024, lastModified: Date.now() },
|
|
])
|
|
|
|
await page.setViewportSize({ width: 1440, height: 900 })
|
|
await page.goto('/drive')
|
|
|
|
// Click bucket if on bucket list
|
|
const bucketItem = page.getByText('test-bucket')
|
|
await expect(bucketItem).toBeVisible({ timeout: 15_000 })
|
|
await bucketItem.click()
|
|
|
|
// Check breadcrumb and entries
|
|
await expect(page.getByText('My drive')).toBeVisible({ timeout: 15_000 })
|
|
await expect(page.getByText('documents')).toBeVisible()
|
|
await expect(page.getByText('hello.txt')).toBeVisible()
|
|
|
|
// Test search filter
|
|
const searchInput = page.getByPlaceholder('Search in this folder')
|
|
await searchInput.fill('doc')
|
|
await expect(page.getByText('documents')).toBeVisible()
|
|
await expect(page.getByText('hello.txt')).not.toBeVisible()
|
|
await searchInput.fill('')
|
|
await expect(page.getByText('hello.txt')).toBeVisible()
|
|
|
|
// Test List view toggle
|
|
const listBtn = page.getByRole('button', { name: 'List' })
|
|
await listBtn.click()
|
|
await expect(page.getByText('Last modified')).toBeVisible()
|
|
|
|
// Test Grid view toggle
|
|
const gridBtn = page.getByRole('button', { name: 'Grid' })
|
|
await gridBtn.click()
|
|
|
|
// Test New folder flow
|
|
const newBtn = page.getByRole('button', { name: 'New', exact: true })
|
|
await newBtn.click()
|
|
const newFolderOption = page.getByRole('button', { name: 'New folder' })
|
|
await newFolderOption.click()
|
|
|
|
const nameInput = page.getByPlaceholder('Name')
|
|
await expect(nameInput).toBeVisible()
|
|
await nameInput.fill('archive')
|
|
await nameInput.press('Enter')
|
|
|
|
await expect(page.getByText('archive')).toBeVisible()
|
|
|
|
// Test deleting an item via 3-dot verbs menu
|
|
const docCard = page.getByRole('button', { name: 'documents/' })
|
|
const moreBtn = docCard.getByRole('button', { name: 'More' })
|
|
await moreBtn.click()
|
|
|
|
const deleteBtn = page.getByRole('button', { name: 'Delete' })
|
|
await expect(deleteBtn).toBeVisible()
|
|
await deleteBtn.click()
|
|
|
|
await expect(page.getByRole('button', { name: 'documents/' })).not.toBeVisible()
|
|
})
|
|
})
|