183 lines
7.3 KiB
JavaScript
183 lines
7.3 KiB
JavaScript
import assert from 'node:assert/strict'
|
|
import { chromium } from 'playwright'
|
|
const browser = await chromium.launch({ headless: true, channel: 'chrome' })
|
|
try {
|
|
for (const allPermissions of [false, true]) {
|
|
const context = await browser.newContext({
|
|
permissions: ['clipboard-read', 'clipboard-write'],
|
|
viewport: { width: 375, height: 812 }
|
|
})
|
|
const page = await context.newPage()
|
|
// 固定起始日期但保持时钟前进;冻结 Date.now 会触发 Vue 嵌套点击事件的时间戳保护。
|
|
await page.clock.install({ time: new Date('2026-10-26T04:00:00Z') })
|
|
page.setDefaultTimeout(20000)
|
|
page.on('console', (msg) => {
|
|
if (msg.type() === 'error') console.log('CONSOLE', msg.text())
|
|
})
|
|
page.on('requestfailed', (r) => console.log('FAILED', r.url(), r.failure()))
|
|
const errors = []
|
|
page.on('pageerror', (e) => errors.push(e.message))
|
|
const rows = [
|
|
{
|
|
id: 'site1',
|
|
dispatchDate: '2026-10-26',
|
|
calendarKind: 'site',
|
|
vehicleId: 'v1',
|
|
licensePlate: '皖H12345',
|
|
productId: 'p1',
|
|
productName: '液碱',
|
|
origin: '山峡',
|
|
destination: '武汉',
|
|
quantity: '32',
|
|
documentType: '出库计划',
|
|
remark: ''
|
|
},
|
|
{
|
|
id: 'site2',
|
|
dispatchDate: '2026-10-26',
|
|
calendarKind: 'site',
|
|
sourceRecordId: 'source2',
|
|
vehicleId: 'v2',
|
|
licensePlate: '皖H54321',
|
|
productId: 'p1',
|
|
productName: '液碱',
|
|
origin: '武汉',
|
|
destination: '云栋',
|
|
quantity: '28',
|
|
documentType: '入库计划',
|
|
remark: ''
|
|
}
|
|
]
|
|
const forbiddenRequests = []
|
|
let lastMonth = ''
|
|
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 user = {
|
|
id: 'fixture',
|
|
userId: 'fixture',
|
|
userName: '测试',
|
|
role: 'admin',
|
|
roles: ['admin']
|
|
}
|
|
if (path === '/web/auth/mp-webview-exchange')
|
|
return route.fulfill({
|
|
json: {
|
|
code: 200,
|
|
data: { token: 'fixture', refreshToken: 'refresh', expiresIn: 3600, userInfo: user }
|
|
}
|
|
})
|
|
if (path === '/web/auth/current-user')
|
|
return route.fulfill({ json: { code: 200, data: user } })
|
|
if (path === '/web/auth/menu-codes')
|
|
return route.fulfill({
|
|
json: {
|
|
code: 200,
|
|
data: {
|
|
all: allPermissions,
|
|
menuCodes: ['mini:pl:site-dispatch-calendar:list']
|
|
}
|
|
}
|
|
})
|
|
if (path === '/transport/site-dispatch-calendar' && req.method() === 'GET') {
|
|
lastMonth = url.searchParams.get('month')
|
|
assert.equal(url.searchParams.has('calendarKind'), false)
|
|
const list = rows.filter((row) => row.dispatchDate.startsWith(lastMonth))
|
|
return route.fulfill({ json: { list, total: list.length } })
|
|
}
|
|
if (path.startsWith('/transport/')) {
|
|
forbiddenRequests.push(req.method() + ' ' + path)
|
|
return route.fulfill({ status: 403, json: { detail: 'forbidden' } })
|
|
}
|
|
return route.fulfill({
|
|
json: {
|
|
code: 200,
|
|
data: path.includes('favorites') || path.includes('upgrade-logs') ? [] : {}
|
|
}
|
|
})
|
|
})
|
|
await page.goto('http://localhost:3006/#/m/pl/site-dispatch-calendar?mpTicket=readonly-test')
|
|
await page.getByText('现场派车日历', { exact: true }).waitFor()
|
|
await page.locator('[data-testid="manual-record"]').nth(1).waitFor()
|
|
assert.equal(await page.getByRole('tab').count(), 0)
|
|
assert.equal(await page.getByRole('button', { name: /新增/ }).count(), 0)
|
|
assert.equal(await page.locator('[data-testid="manual-editor"]').count(), 0)
|
|
for (let index = 0; index < 2; index++) {
|
|
await page.locator('[data-testid="manual-record"]').nth(index).click()
|
|
await page.getByText('派车计划详情', { exact: true }).waitFor()
|
|
assert.equal(await page.getByRole('button', { name: '编辑', exact: true }).count(), 0)
|
|
assert.equal(await page.getByRole('button', { name: '删除', exact: true }).count(), 0)
|
|
await page.locator('.van-popup:visible .van-popup__close-icon').click()
|
|
}
|
|
await page
|
|
.locator('[data-date="2026-10-26"]')
|
|
.getByRole('button', { name: '复制', exact: true })
|
|
.click()
|
|
assert.equal(
|
|
await page.evaluate(() => navigator.clipboard.readText()),
|
|
'2026-10-26 派车计划:\n\n液碱2车\n ·皖H12345 液碱 32吨(出库计划)\n ·皖H54321 液碱 28吨(入库计划)'
|
|
)
|
|
await page.getByLabel('车辆筛选', { exact: true }).click()
|
|
let vehiclePicker = page.locator('.mp-calendar-vehicle-picker:visible')
|
|
await vehiclePicker.getByText('皖H54321', { exact: true }).click()
|
|
await vehiclePicker.getByRole('button', { name: '确认', exact: true }).click()
|
|
await page
|
|
.locator('[data-testid="manual-record"]')
|
|
.filter({ hasText: '皖H12345' })
|
|
.waitFor({ state: 'hidden' })
|
|
assert.equal(await page.locator('[data-testid="manual-record"]').count(), 1)
|
|
await page
|
|
.locator('[data-date="2026-10-26"]')
|
|
.getByRole('button', { name: '复制', exact: true })
|
|
.click()
|
|
assert.equal(
|
|
await page.evaluate(() => navigator.clipboard.readText()),
|
|
'2026-10-26 派车计划:\n\n液碱1车\n ·皖H54321 液碱 28吨(入库计划)'
|
|
)
|
|
await page.getByLabel('车辆筛选', { exact: true }).click()
|
|
vehiclePicker = page.locator('.mp-calendar-vehicle-picker:visible')
|
|
await vehiclePicker.getByText('全部车辆', { exact: true }).click()
|
|
await vehiclePicker.getByRole('button', { name: '确认', exact: true }).click()
|
|
await page.getByLabel('查看月份', { exact: true }).click()
|
|
const popup = page.locator('.mp-calendar-date-picker:visible')
|
|
await popup.locator('.van-picker-column').nth(1).getByText('09', { exact: true }).click()
|
|
await popup.getByRole('button', { name: '确认', exact: true }).click()
|
|
await page.getByText('本月暂无现场派车计划', { exact: true }).waitFor()
|
|
assert.equal(lastMonth, '2026-09')
|
|
await page.getByRole('button', { name: '今天', exact: true }).click()
|
|
await page.locator('[data-testid="manual-record"]').nth(1).waitFor()
|
|
for (const width of [320, 375, 414]) {
|
|
await page.setViewportSize({ width, height: 812 })
|
|
assert.ok(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth + 1))
|
|
}
|
|
await page.screenshot({ path: `/tmp/site-readonly-${allPermissions ? 'admin' : 'staff'}.png` })
|
|
assert.deepEqual(forbiddenRequests, [])
|
|
assert.deepEqual(errors, [])
|
|
console.log(
|
|
`readonly site ${allPermissions ? 'all permissions' : 'site permission only'} passed`
|
|
)
|
|
await context.close()
|
|
}
|
|
} finally {
|
|
await browser.close()
|
|
}
|