Files
shanxia2.0/web-admin/src/views/doclib/enter/browser.test.mjs
T

242 lines
11 KiB
JavaScript

import assert from 'node:assert/strict'
import { chromium } from 'playwright'
const browser = await chromium.launch({ headless: true, channel: 'chrome' })
const context = await browser.newContext({ viewport: { width: 1440, height: 1000 } })
const page = await context.newPage()
page.setDefaultTimeout(20000)
page.on('console', (msg) => {
if (msg.type() === 'error') console.log('CONSOLE', msg.text())
})
page.on('requestfailed', (req) => console.log('REQUESTFAILED', req.url(), req.failure()))
const errors = []
page.on('pageerror', (error) => errors.push(error.message))
let sharedUsers = []
let uploads = 0
let lastUploadBody = ''
let lastParentId = ''
let deletes = 0
let mineDeleted = false
let failList = false
let folders = []
const makeRoot = (scope, name, children = []) => ({
id: `scope:${scope}`,
name,
scope,
folderId: '',
fullPath: `${name} / 全部文件`,
ownerId: '',
canManage: scope === 'mine',
count: 1,
children
})
const file = {
id: 'mine-1',
name: '产品资料.pdf',
folderId: '',
folderPath: '我的文档 / 根目录',
size: 1234,
contentType: 'application/pdf',
ownerId: 'fixture',
ownerName: '测试',
createTime: '2026-10-26 10:00:00',
updateTime: '2026-10-26 10:00:00',
canManage: true,
shares: []
}
const sharedFile = {
...file,
id: 'shared-1',
name: '共享制度.pdf',
ownerId: 'other',
ownerName: '同事',
canManage: false,
shares: [{ id: 'fixture', name: '测试', deptName: '研发部' }]
}
await context.addInitScript(() => {
localStorage.setItem(
'sys-v3.0.2-user',
JSON.stringify({
isLogin: true,
accessToken: 'fixture',
info: { id: 'fixture', userId: 'fixture', userName: '测试', role: 'admin', roles: ['admin'] }
})
)
localStorage.setItem('sys-version', '3.0.2')
})
await context.route('**/api/**', async (route) => {
const req = route.request(),
url = new URL(req.url()),
path = url.pathname.slice(4)
if (!url.pathname.startsWith('/api/')) return route.continue()
const ok = (data) => route.fulfill({ json: { code: 200, data } })
if (path === '/web/auth/current-user')
return ok({
id: 'fixture',
userId: 'fixture',
userName: '测试',
role: 'admin',
roles: ['admin']
})
if (path === '/web/auth/menu-codes') return ok({ all: true, menuCodes: [] })
if (path === '/web/doclib/tree')
return ok({
nodes: [makeRoot('mine', '我的文档', folders), makeRoot('shared', '分享给我')],
isSuperAdmin: false,
maxUploadBytes: 100000
})
if (path === '/web/doclib/files') {
if (failList) return route.fulfill({ status: 400, json: { code: 400, message: '加载失败' } })
const row = url.searchParams.get('scope') === 'shared' ? sharedFile : file
const list =
!mineDeleted &&
(!url.searchParams.get('keyword') || row.name.includes(url.searchParams.get('keyword')))
? [row]
: []
return ok({ list, total: list.length })
}
if (path === '/web/doclib/users') return ok([{ id: 'other', name: '同事', deptName: '生产部' }])
if (path === '/web/doclib/files/batch-shares' && req.method() === 'POST') {
const body = req.postDataJSON()
sharedUsers = body.userIds
file.shares = sharedUsers.map((id) => ({ id, name: '同事', deptName: '生产部' }))
return ok([file])
}
if (path.endsWith('/shares')) {
sharedUsers = req.postDataJSON().userIds
file.shares = sharedUsers.map((id) => ({ id, name: '同事', deptName: '生产部' }))
return ok(file)
}
if (path === '/web/doclib/folders' && req.method() === 'POST') {
const body = req.postDataJSON()
lastParentId = body.parentId
const folder = {
id: `mine:f${folders.length + 1}`,
folderId: `f${folders.length + 1}`,
name: body.name,
fullPath: `我的文档 / ${body.name}`,
scope: 'mine',
ownerId: 'fixture',
canManage: true,
count: 0,
children: []
}
folders.push(folder)
return ok(folder)
}
if (path === '/web/doclib/upload') {
lastUploadBody = req.postData() || ''
uploads++
return ok({ ...file, id: `uploaded-${uploads}`, name: '上传测试.txt' })
}
if (path === '/web/doclib/files/batch-delete') {
mineDeleted = true
deletes++
return ok(null)
}
if (path.endsWith('/download'))
return route.fulfill({ body: 'fixture file', contentType: 'application/octet-stream' })
if (path === '/web/doclib/files/mine-1') return ok(file)
if (path === '/web/doclib/files/shared-1') return ok(sharedFile)
return ok(path.includes('favorites') || path.includes('upgrade-logs') ? [] : {})
})
try {
await page.goto('http://localhost:3006/#/doclib/enter')
await page.getByText('文档库', { exact: true }).first().click()
await page.locator('.doclib-page').waitFor()
assert.equal(context.pages().length, 1)
await page.locator('.doclib-file-text .el-link').filter({ hasText: '产品资料.pdf' }).waitFor()
assert.equal(await page.locator('.doclib-tree-node').count(), 2)
await page.locator('.doclib-tree-node').filter({ hasText: '分享给我' }).click()
await page.locator('.doclib-file-text .el-link').filter({ hasText: '共享制度.pdf' }).waitFor()
await page.locator('.el-table__body .el-checkbox').first().click()
assert.equal(await page.getByRole('button', { name: '设置分享', exact: true }).isDisabled(), true)
assert.equal(await page.getByRole('button', { name: '删除', exact: true }).isDisabled(), true)
assert.equal(await page.getByRole('button', { name: '下载', exact: true }).isEnabled(), true)
assert.equal(await page.getByRole('button', { name: '上传文档', exact: true }).count(), 0)
await page.locator('.doclib-file-text .el-link').filter({ hasText: '共享制度.pdf' }).click()
const detail = page.locator('.system-view-dialog:visible')
await detail.getByRole('button', { name: '下载文档', exact: true }).waitFor()
assert.equal(await detail.getByRole('button', { name: '设置分享', exact: true }).count(), 0)
const downloaded = page.waitForEvent('download')
await detail.getByRole('button', { name: '下载文档', exact: true }).click()
assert.equal((await downloaded).suggestedFilename(), '共享制度.pdf')
await detail.locator('.el-dialog__headerbtn').click()
await page.locator('.doclib-tree-node').filter({ hasText: '我的文档' }).click()
await page.locator('.doclib-file-text .el-link').filter({ hasText: '产品资料.pdf' }).waitFor()
assert.match(await page.locator('.doclib-selected').innerText(), /0/)
await page.locator('.el-table__body .el-checkbox').first().click()
await page.getByRole('button', { name: '设置分享', exact: true }).click()
const share = page.locator('.doclib-dialog:visible')
await share.getByRole('combobox').click()
await page.getByRole('option', { name: /同事/ }).click()
await share.getByRole('button', { name: '保存分享' }).click()
await share.waitFor({ state: 'hidden' })
assert.deepEqual(sharedUsers, ['other'])
await page.getByRole('button', { name: '新建文件夹', exact: true }).click()
const folder = page.locator('.doclib-dialog:visible')
await folder.getByPlaceholder('请输入文件夹名称').fill('测试目录')
await folder.getByRole('button', { name: '保存', exact: true }).click()
await page.locator('.doclib-tree-node').filter({ hasText: '测试目录' }).waitFor()
assert.equal(lastParentId, '')
await page.getByRole('button', { name: '新建文件夹', exact: true }).click()
await folder.getByPlaceholder('请输入文件夹名称').fill('子目录')
await folder.getByRole('combobox', { name: '上级文件夹', exact: true }).click()
await page.getByRole('option', { name: '测试目录', exact: true }).click()
await folder.getByRole('button', { name: '保存', exact: true }).click()
await page.locator('.doclib-tree-node').filter({ hasText: '子目录' }).waitFor()
assert.equal(lastParentId, 'f1')
await page.getByRole('button', { name: '上传文档', exact: true }).click()
const upload = page.locator('.doclib-dialog:visible')
await upload.getByRole('combobox', { name: '上传到', exact: true }).click()
await page.getByRole('option', { name: '测试目录', exact: true }).click()
await upload.locator('input[type=file]').setInputFiles([
{ name: '上传测试.txt', mimeType: 'text/plain', buffer: Buffer.from('上传测试') },
{ name: '空文件.txt', mimeType: 'text/plain', buffer: Buffer.from('') }
])
await upload.getByText('已上传', { exact: true }).waitFor()
await upload.getByText('不能上传空文件', { exact: true }).waitFor()
assert.equal(uploads, 1)
assert.match(lastUploadBody, /name="folderId"\r\n\r\nf1/)
assert.equal(
await upload.getByRole('combobox', { name: '上传到', exact: true }).isDisabled(),
true
)
await page.waitForFunction(() => !document.querySelector('.el-message'))
await page.screenshot({ path: '/tmp/doclib-upload.png', fullPage: true })
await upload.getByRole('button', { name: '完成', exact: true }).click()
await page.screenshot({ path: '/tmp/doclib-desktop.png', fullPage: true })
await page.getByPlaceholder('搜索文档名称').fill('不存在')
await page.getByRole('button', { name: '搜索', exact: true }).click()
await page.getByText('没有匹配的文档').waitFor()
failList = true
await page.getByRole('button', { name: '刷新', exact: true }).click()
await page.getByText('文档加载失败,请点击刷新重试').waitFor()
failList = false
await page.getByRole('button', { name: '刷新', exact: true }).click()
await page.getByText('没有匹配的文档').waitFor()
await page.getByPlaceholder('搜索文档名称').fill('')
await page.getByRole('button', { name: '搜索', exact: true }).click()
await page.locator('.doclib-file-text .el-link').filter({ hasText: '产品资料.pdf' }).waitFor()
await page.locator('.el-table__body .el-checkbox').first().click()
await page.getByRole('button', { name: '删除', exact: true }).click()
await page.getByRole('button', { name: '确认删除', exact: true }).click()
await page.getByText('这里还没有文档', { exact: true }).waitFor()
assert.match(await page.locator('.doclib-selected').innerText(), /0/)
await page.setViewportSize({ width: 700, height: 900 })
assert.equal(
await page.locator('.doclib-layout').evaluate((el) => getComputedStyle(el).flexDirection),
'column'
)
assert.equal(deletes, 1)
assert.deepEqual(errors, [])
console.log(
'PASS doclib browser: roots, shared permissions, selection reset, detail, sharing, folders, upload/validation, search, failed load/retry, responsive layout'
)
} catch (error) {
console.log('PAGE', await page.locator('body').innerText(), errors)
await page.screenshot({ path: '/tmp/doclib-browser-failure.png', fullPage: true })
throw error
} finally {
await browser.close()
}