569 lines
23 KiB
JavaScript
569 lines
23 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 },
|
|
permissions: ['clipboard-read', 'clipboard-write']
|
|
})
|
|
const page = await context.newPage()
|
|
await page.clock.setFixedTime(new Date('2026-10-25T04:00:00Z'))
|
|
page.setDefaultTimeout(60000)
|
|
const errors = []
|
|
page.on('pageerror', (error) => errors.push(error.message))
|
|
page.on('console', (msg) => {
|
|
if (msg.type() === 'error') console.error('CONSOLE', msg.text())
|
|
})
|
|
page.on('requestfailed', (request) => console.error('FAILED', request.url(), request.failure()))
|
|
page.on('response', (response) => {
|
|
if (response.status() >= 400) console.error('HTTP', response.status(), response.url())
|
|
})
|
|
const rows = Array.from({ length: 7 }, (_, i) => ({
|
|
id: `plan-${i}`,
|
|
planNo: `PL${i}`,
|
|
planDate: '2026-10-24',
|
|
followStatus: 'pending',
|
|
vehicleId: `v${Math.floor(i / 2)}`,
|
|
licensePlate: ['皖HA3690', '皖H10291', '皖H57837', '皖LB1283'][Math.floor(i / 2)],
|
|
driverId: i < 2 ? 'driver-1' : undefined,
|
|
driverName: i < 2 ? '测试司机' : undefined,
|
|
products: [{ productId: i % 2 ? 'p2' : 'p1', productName: i % 2 ? '98酸' : 'cp酸' }],
|
|
calendarRoute: '山峡库 → 永恒',
|
|
load: { customerName: '山峡化工有限公司', calendarCustomerName: '山峡库' },
|
|
deliveries: [{ customerName: '永恒有限公司', calendarCustomerName: '永恒' }]
|
|
}))
|
|
let failNext = false
|
|
await context.addInitScript(() => {
|
|
localStorage.setItem(
|
|
'sys-v3.0.2-user',
|
|
JSON.stringify({
|
|
isLogin: true,
|
|
accessToken: 'calendar-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 url = new URL(route.request().url())
|
|
if (!url.pathname.startsWith('/api/')) return route.continue()
|
|
const path = url.pathname.replace(/^\/api/, '')
|
|
if (path === '/transport/plan/') {
|
|
if (failNext) {
|
|
failNext = false
|
|
return route.fulfill({ status: 500, json: { detail: 'fixture failure' } })
|
|
}
|
|
const list = url.searchParams.get('planDateFrom')?.slice(0, 7) === '2026-10' ? rows : []
|
|
return route.fulfill({
|
|
json: {
|
|
list: list.map((item) => ({ calendarVehicleType: 'self', ...item })),
|
|
total: list.length
|
|
}
|
|
})
|
|
}
|
|
let data = {}
|
|
if (path === '/web/auth/current-user')
|
|
data = {
|
|
id: 'fixture',
|
|
userId: 'fixture',
|
|
userName: '测试用户',
|
|
role: 'admin',
|
|
roles: ['admin']
|
|
}
|
|
else if (path === '/web/auth/menu-codes')
|
|
data = {
|
|
all: false,
|
|
menuCodes: [
|
|
'pl:dispatch-calendar:list',
|
|
'pl:plan:list',
|
|
'pl:inbound:list',
|
|
'pl:outbound:list'
|
|
]
|
|
}
|
|
else if (path.includes('favorites') || path.includes('upgrade-logs')) data = []
|
|
return route.fulfill({
|
|
json: { code: path.startsWith('/transport/') ? 0 : 200, msg: 'ok', data }
|
|
})
|
|
})
|
|
try {
|
|
await page.goto(
|
|
`${process.env.CALENDAR_TEST_ORIGIN || 'http://localhost:3006'}/#/pl/calendar-module/dispatch-calendar`
|
|
)
|
|
await page.getByText('派车日历', { exact: true }).first().click()
|
|
await page.getByRole('tab', { name: '实际派车信息', exact: true }).click()
|
|
const panel = page.locator('.dispatch-calendar-page')
|
|
await panel.locator('.plate-number').first().waitFor({ timeout: 15000 })
|
|
assert.equal(await panel.locator('.trip-card').count(), 7)
|
|
assert.equal(await panel.locator('.vehicle-card').count(), 4)
|
|
assert.equal(await panel.locator('.calendar-controls label').count(), 0)
|
|
assert.equal(await panel.locator('.calendar-controls .el-select').count(), 1)
|
|
assert.equal(await panel.getByLabel('司机筛选').count(), 0)
|
|
assert.equal(await panel.locator('.trip-route').first().textContent(), '山峡库 → 永恒')
|
|
await page.waitForFunction(() => {
|
|
const button = document.querySelector('.dispatch-calendar-page .el-button--primary')
|
|
return button && getComputedStyle(button).backgroundColor === 'rgb(31, 78, 121)'
|
|
})
|
|
for (const selector of ['.calendar-weekdays', '.plate-number', '.el-button--primary']) {
|
|
assert.equal(
|
|
await panel
|
|
.locator(selector)
|
|
.first()
|
|
.evaluate((el) => getComputedStyle(el).backgroundColor),
|
|
'rgb(31, 78, 121)'
|
|
)
|
|
}
|
|
assert.equal(await panel.locator('.calendar-day').count(), 35)
|
|
const daily = panel.locator('[data-date="2026-10-24"]')
|
|
assert.match(await daily.locator('.day-total').textContent(), /合计\s*7\s*车次/)
|
|
assert.equal(await daily.getByText('未填写司机', { exact: true }).count(), 0)
|
|
assert.equal(await daily.locator('.day-summary:visible').count(), 0)
|
|
const copyButton = daily.getByRole('button', { name: '复制2026-10-24派车计划', exact: true })
|
|
assert.ok(await panel.locator('[data-date="2026-10-01"] .day-copy-button').isDisabled())
|
|
await copyButton.click()
|
|
let copiedText = await page.evaluate(() => navigator.clipboard.readText())
|
|
assert.match(copiedText, /^运输计划 10\.24\n• 皖HA3690 \/ cp酸 山峡库 - 永恒/)
|
|
assert.equal(copiedText.split('\n').length, 5)
|
|
await page.clock.setFixedTime(new Date('2026-10-23T04:00:00Z'))
|
|
await copyButton.click()
|
|
assert.match(await page.evaluate(() => navigator.clipboard.readText()), /^明日计划 10\.24/)
|
|
await page.clock.setFixedTime(new Date('2026-10-22T04:00:00Z'))
|
|
await copyButton.click()
|
|
assert.match(await page.evaluate(() => navigator.clipboard.readText()), /^后日计划 10\.24/)
|
|
await page.clock.setFixedTime(new Date('2026-10-25T04:00:00Z'))
|
|
|
|
await daily.getByRole('button', { name: '查看2026-10-24货品汇总' }).click({ timeout: 2000 })
|
|
const summaryPopup = page.locator('.calendar-summary-popper:visible')
|
|
await summaryPopup.waitFor()
|
|
assert.match(await summaryPopup.textContent(), /2026-10-24.*货品汇总/)
|
|
assert.match(await summaryPopup.locator('.day-total').textContent(), /合计\s*7\s*车次/)
|
|
assert.equal(await summaryPopup.locator('.product-total').count(), 2)
|
|
await page.waitForFunction(() => {
|
|
const popup = Array.from(document.querySelectorAll('.calendar-summary-popper')).find(
|
|
(el) => el.getBoundingClientRect().width > 0
|
|
)
|
|
return popup && getComputedStyle(popup).opacity === '1'
|
|
})
|
|
await summaryPopup.screenshot({ path: '/tmp/shanxia-calendar-summary-popover.png' })
|
|
await panel.locator('.title-bar-heading').click()
|
|
await summaryPopup.waitFor({ state: 'hidden' })
|
|
assert.equal(
|
|
await daily.locator('.day-summary').evaluate((el) => getComputedStyle(el).backgroundColor),
|
|
'rgba(0, 0, 0, 0)'
|
|
)
|
|
await panel.locator('.el-select').click()
|
|
await page
|
|
.locator('.el-select-dropdown__item:visible')
|
|
.getByText('皖HA3690', { exact: true })
|
|
.click()
|
|
assert.equal(await panel.locator('.trip-card').count(), 2)
|
|
await panel.getByRole('button', { name: '重置筛选', exact: true }).click()
|
|
assert.equal(await panel.locator('.trip-card').count(), 7)
|
|
await panel.getByRole('button', { name: '下月', exact: true }).click()
|
|
await panel.getByText('本月暂无派车计划', { exact: true }).waitFor()
|
|
assert.equal(await panel.locator('.calendar-day').count(), 42)
|
|
await panel.getByRole('button', { name: '上月', exact: true }).click()
|
|
await daily.locator('.plate-number').first().waitFor()
|
|
await daily.locator('.day-number').click()
|
|
assert.ok((await daily.getAttribute('class')).includes('selected'))
|
|
await page.setViewportSize({ width: 2560, height: 1300 })
|
|
assert.equal(
|
|
await daily
|
|
.locator('.vehicle-grid')
|
|
.evaluate((el) => getComputedStyle(el).gridTemplateColumns.split(' ').length),
|
|
2
|
|
)
|
|
await daily.screenshot({ path: '/tmp/shanxia-dispatch-calendar-day.png' })
|
|
await page.screenshot({ path: '/tmp/shanxia-dispatch-calendar-web.png' })
|
|
// 捕获浏览器打印调用,验证独立打印文档使用当前月历而非整个后台。
|
|
await page.evaluate(() => {
|
|
const append = document.body.appendChild
|
|
document.body.appendChild = function (node) {
|
|
const result = append.call(this, node)
|
|
if (node.tagName === 'IFRAME') {
|
|
node.contentWindow.print = () => {
|
|
window.calendarPrintCalled = true
|
|
}
|
|
document.body.appendChild = append
|
|
}
|
|
return result
|
|
}
|
|
})
|
|
await panel.getByRole('button', { name: '打印日历', exact: true }).click()
|
|
await page.waitForFunction(() => window.calendarPrintCalled === true)
|
|
const printFrame = page.frameLocator('iframe[aria-hidden="true"]')
|
|
assert.equal(await printFrame.locator('.trip-card').count(), 7)
|
|
assert.match(
|
|
await printFrame.locator('.day-print-summary .day-total').textContent(),
|
|
/合计\s*7\s*车次/
|
|
)
|
|
assert.equal(await printFrame.locator('.calendar-controls').count(), 0)
|
|
assert.equal(await printFrame.locator('h1').textContent(), '2026年10月派车日历')
|
|
await page.emulateMedia({ media: 'print' })
|
|
assert.equal(
|
|
await printFrame
|
|
.locator('.day-content')
|
|
.first()
|
|
.evaluate((el) => getComputedStyle(el).maxHeight),
|
|
'none'
|
|
)
|
|
assert.equal(
|
|
await printFrame
|
|
.locator('.trip-route')
|
|
.first()
|
|
.evaluate((el) => getComputedStyle(el).overflow),
|
|
'visible'
|
|
)
|
|
await page.emulateMedia({ media: 'screen' })
|
|
await page.evaluate(() =>
|
|
document
|
|
.querySelector('iframe[aria-hidden="true"]')
|
|
.contentWindow.dispatchEvent(new Event('afterprint'))
|
|
)
|
|
assert.equal(await page.locator('iframe[aria-hidden="true"]').count(), 0)
|
|
failNext = true
|
|
await panel.getByRole('button', { name: '刷新', exact: true }).click()
|
|
await panel.getByRole('alert').waitFor()
|
|
assert.equal(await panel.locator('.trip-card').count(), 0)
|
|
await panel.getByRole('button', { name: '重试', exact: true }).click()
|
|
await daily.locator('.plate-number').first().waitFor()
|
|
assert.equal(await panel.locator('.trip-card').count(), 7)
|
|
// 繁忙日保持七天等宽、无横向滚动,车辆卡片按车次数倒序。
|
|
rows.splice(
|
|
0,
|
|
rows.length,
|
|
...Array.from({ length: 11 }, (_, index) => ({
|
|
id: `dense-${index}`,
|
|
planNo: `DENSE${index}`,
|
|
planDate: '2026-10-24',
|
|
followStatus: 'pending',
|
|
vehicleId: `dense-v${index % 6}`,
|
|
licensePlate: ['皖H57837', '皖M7A663', '皖H31656', '一票到', '皖AM8516', '皖HA6900'][
|
|
index % 6
|
|
],
|
|
calendarRoute: '安庆山峡 → 厦门圣益',
|
|
products: [
|
|
{
|
|
productId: `product-${index % 7}`,
|
|
productName: [
|
|
'50% 工业硫酸',
|
|
'30%液碱',
|
|
'氨水',
|
|
'30% 工业硫酸',
|
|
'32%液碱',
|
|
'精制硫酸',
|
|
'98% 工业硫酸'
|
|
][index % 7]
|
|
}
|
|
]
|
|
}))
|
|
)
|
|
await page.setViewportSize({ width: 1440, height: 1000 })
|
|
await panel.getByRole('button', { name: '刷新', exact: true }).click()
|
|
await daily.getByText('皖M7A663', { exact: true }).first().waitFor()
|
|
assert.ok(
|
|
await panel.locator('.calendar-scroll').evaluate((el) => el.scrollWidth <= el.clientWidth)
|
|
)
|
|
const widths = await panel
|
|
.locator('.calendar-weekdays span')
|
|
.evaluateAll((nodes) => nodes.map((node) => node.getBoundingClientRect().width))
|
|
assert.equal(widths.length, 7)
|
|
assert.ok(Math.max(...widths) - Math.min(...widths) < 1)
|
|
const actionRow = await daily.locator('.day-vehicle-scope > .el-button').evaluateAll((buttons) =>
|
|
buttons.map((button) => {
|
|
const r = button.getBoundingClientRect()
|
|
return { top: r.top, bottom: r.bottom, right: r.right }
|
|
})
|
|
)
|
|
assert.equal(actionRow.length, 3, '车辆范围、复制在同一行')
|
|
assert.ok(
|
|
await panel.locator('.day-number').evaluateAll((buttons) =>
|
|
buttons.every((button) => {
|
|
const range = document.createRange()
|
|
range.selectNodeContents(button)
|
|
return range.getClientRects().length === 1
|
|
})
|
|
),
|
|
'两位数日期不换行'
|
|
)
|
|
|
|
assert.equal(await daily.locator('.day-heading .day-summary-button').count(), 1)
|
|
assert.ok(
|
|
await daily.locator('.day-heading').evaluate((heading) => {
|
|
const row = heading.getBoundingClientRect()
|
|
const summary = heading.querySelector('.day-summary-button').getBoundingClientRect()
|
|
const date = heading.querySelector('.day-number').getBoundingClientRect()
|
|
const weekday = heading.querySelector('.day-weekday').getBoundingClientRect()
|
|
return (
|
|
Math.abs((row.left + row.right - summary.left - summary.right) / 2) < 1 &&
|
|
date.right <= summary.left &&
|
|
summary.right <= weekday.left
|
|
)
|
|
}),
|
|
'合计在日期标题栏正中间,且不与日期、星期重叠'
|
|
)
|
|
|
|
assert.ok(
|
|
actionRow.every(
|
|
(r) => Math.abs(r.top - actionRow[0].top) < 1 && Math.abs(r.bottom - actionRow[0].bottom) < 1
|
|
)
|
|
)
|
|
assert.ok(
|
|
await daily.locator('.day-vehicle-scope').evaluate((el) => el.scrollWidth <= el.clientWidth),
|
|
'操作行不能横向溢出'
|
|
)
|
|
const tripCounts = await daily
|
|
.locator('.vehicle-card')
|
|
.evaluateAll((cards) => cards.map((card) => card.querySelectorAll('.trip-card').length))
|
|
assert.equal(tripCounts.length, 6)
|
|
assert.deepEqual(
|
|
tripCounts,
|
|
[...tripCounts].sort((a, b) => b - a)
|
|
)
|
|
assert.ok(
|
|
await daily
|
|
.locator('.day-content')
|
|
.evaluate(
|
|
(el) => el.scrollHeight <= el.clientHeight && getComputedStyle(el).overflowY === 'visible'
|
|
)
|
|
)
|
|
assert.equal(await daily.locator('.trip-card').count(), 11)
|
|
const weekdayWidths = await panel
|
|
.locator('.calendar-weekdays')
|
|
.evaluate((el) => getComputedStyle(el).gridTemplateColumns)
|
|
assert.equal(
|
|
await panel
|
|
.locator('.calendar-grid')
|
|
.evaluate((el) => getComputedStyle(el).gridTemplateColumns),
|
|
weekdayWidths
|
|
)
|
|
assert.ok(
|
|
await daily
|
|
.locator('.vehicle-card')
|
|
.evaluateAll((cards) => cards.every((card) => card.scrollWidth <= card.clientWidth))
|
|
)
|
|
await page.setViewportSize({ width: 2560, height: 1300 })
|
|
const rowCards = await daily.locator('.vehicle-card').evaluateAll((cards) =>
|
|
cards.map((card) => {
|
|
const rect = card.getBoundingClientRect()
|
|
return { top: rect.top, bottom: rect.bottom }
|
|
})
|
|
)
|
|
for (const card of rowCards) {
|
|
for (const sibling of rowCards.filter((item) => Math.abs(item.top - card.top) < 1))
|
|
assert.ok(Math.abs(sibling.bottom - card.bottom) < 1)
|
|
}
|
|
await daily.screenshot({ path: '/tmp/shanxia-dispatch-calendar-dense.png' })
|
|
await page.screenshot({ path: '/tmp/shanxia-dispatch-calendar-dense-web.png' })
|
|
await page.setViewportSize({ width: 600, height: 1000 })
|
|
assert.ok(
|
|
await panel.locator('.calendar-grid').evaluate((el) => el.scrollWidth <= el.clientWidth)
|
|
)
|
|
const availableWidth = await daily.locator('.day-content').evaluate((el) => el.clientWidth)
|
|
assert.equal(
|
|
await daily
|
|
.locator('.vehicle-grid')
|
|
.evaluate((el) => getComputedStyle(el).gridTemplateColumns.split(' ').length),
|
|
availableWidth >= 420 ? 3 : availableWidth >= 280 ? 2 : 1
|
|
)
|
|
rows.push({ ...rows[0], id: 'dense-duplicate', planNo: 'DENSE-DUP' })
|
|
await page.setViewportSize({ width: 1440, height: 1000 })
|
|
await panel.getByRole('button', { name: '刷新', exact: true }).click()
|
|
const mergedTask = daily.locator('.trip-card').filter({ hasText: '· 2车次' })
|
|
await mergedTask.waitFor()
|
|
assert.equal(await daily.locator('.trip-card').count(), 11)
|
|
assert.match(await mergedTask.getAttribute('title'), /DENSE0/)
|
|
assert.match(await mergedTask.getAttribute('title'), /DENSE-DUP/)
|
|
assert.match(await daily.locator('.day-summary-button').textContent(), /合计\s*12\s*车次/)
|
|
await daily.getByRole('button', { name: '查看2026-10-24货品汇总' }).click()
|
|
const mergedSummary = page.locator('.calendar-summary-popper:visible')
|
|
await mergedSummary.waitFor()
|
|
assert.match(await mergedSummary.locator('.day-total').textContent(), /合计\s*12\s*车次/)
|
|
const productCounts = await mergedSummary.locator('.product-total dd strong').allTextContents()
|
|
assert.equal(
|
|
productCounts.reduce((sum, value) => sum + Number(value), 0),
|
|
12
|
|
)
|
|
await panel.locator('.title-bar-heading').click()
|
|
await mergedSummary.waitFor({ state: 'hidden' })
|
|
await daily
|
|
.locator('.vehicle-card')
|
|
.first()
|
|
.screenshot({ path: '/tmp/shanxia-calendar-merged-trip.png' })
|
|
// 一计划三送货段,货品和收货方分别对应;相同段再合并,计划车次不膨胀。
|
|
rows.splice(0, rows.length, {
|
|
id: 'multi-stop',
|
|
planNo: 'MULTI',
|
|
planDate: '2026-10-24',
|
|
followStatus: 'pending',
|
|
vehicleId: 'v-multi',
|
|
licensePlate: '皖H21522',
|
|
load: {
|
|
customerId: 'load',
|
|
customerName: '安庆山峡化工有限公司',
|
|
calendarCustomerName: '安庆山峡'
|
|
},
|
|
products: [
|
|
{ id: 'pa', productId: 'a', productName: '氯化钠' },
|
|
{ id: 'pb', productId: 'b', productName: '次氯酸钠' }
|
|
],
|
|
deliveries: [
|
|
{
|
|
id: 's1',
|
|
seq: 1,
|
|
customerId: '甲',
|
|
customerName: '甲有限公司',
|
|
calendarCustomerName: '甲',
|
|
products: [{ planProductId: 'pa', productId: 'a', productName: '氯化钠' }]
|
|
},
|
|
{
|
|
id: 's2',
|
|
seq: 2,
|
|
customerId: '乙',
|
|
customerName: '乙有限公司',
|
|
calendarCustomerName: '乙',
|
|
products: [{ planProductId: 'pb', productId: 'b', productName: '次氯酸钠' }]
|
|
},
|
|
{
|
|
id: 's3',
|
|
seq: 3,
|
|
customerId: '丙',
|
|
customerName: '丙有限公司',
|
|
calendarCustomerName: '丙',
|
|
products: [{ planProductId: 'pa', productId: 'a', productName: '氯化钠' }]
|
|
}
|
|
]
|
|
})
|
|
await panel.getByRole('button', { name: '刷新', exact: true }).click()
|
|
await daily.getByText('皖H21522', { exact: true }).waitFor()
|
|
assert.equal(await daily.locator('.trip-card').count(), 3)
|
|
assert.deepEqual(await daily.locator('.trip-route').allTextContents(), [
|
|
'山峡 → 甲',
|
|
'山峡 → 乙',
|
|
'山峡 → 丙'
|
|
])
|
|
assert.match(await daily.locator('.day-summary-button').textContent(), /合计\s*1\s*车次/)
|
|
rows[0].deliveries[2].customerId = '甲'
|
|
rows[0].deliveries[2].calendarCustomerName = '甲'
|
|
rows[0].deliveries[2].customerName = '甲有限公司'
|
|
await panel.getByRole('button', { name: '刷新', exact: true }).click()
|
|
await daily.getByText(/2段次/).waitFor()
|
|
assert.equal(await daily.locator('.trip-card').count(), 2)
|
|
assert.match(await daily.locator('.trip-card').first().textContent(), /氯化钠.*1车次.*2段次/)
|
|
assert.match(await daily.locator('.day-summary-button').textContent(), /合计\s*1\s*车次/)
|
|
await daily.getByRole('button', { name: '查看2026-10-24货品汇总' }).click()
|
|
const stopSummary = page.locator('.calendar-summary-popper:visible')
|
|
await stopSummary.waitFor()
|
|
assert.match(await stopSummary.locator('.day-total').textContent(), /合计\s*1\s*车次/)
|
|
assert.deepEqual(await stopSummary.locator('.product-total dd strong').allTextContents(), [
|
|
'1',
|
|
'1'
|
|
])
|
|
await panel.locator('.title-bar-heading').click()
|
|
await stopSummary.waitFor({ state: 'hidden' })
|
|
await daily.locator('.vehicle-card').screenshot({ path: '/tmp/shanxia-calendar-multi-stop.png' })
|
|
// 每天独立默认自有;全部包含承运商与未知车辆,汇总随当天筛选变化。
|
|
const base = rows[0]
|
|
rows.splice(
|
|
0,
|
|
rows.length,
|
|
{ ...base, id: 'own', vehicleId: 'own', licensePlate: '皖OWN', calendarVehicleType: 'self' },
|
|
{
|
|
...base,
|
|
id: 'carrier',
|
|
vehicleId: 'carrier',
|
|
licensePlate: '皖OUT',
|
|
calendarVehicleType: 'carrier'
|
|
},
|
|
{
|
|
...base,
|
|
id: 'unknown',
|
|
vehicleId: 'unknown',
|
|
licensePlate: '皖UNKNOWN',
|
|
calendarVehicleType: 'unknown'
|
|
},
|
|
{
|
|
...base,
|
|
id: 'other-day',
|
|
planDate: '2026-10-25',
|
|
vehicleId: 'carrier-next',
|
|
licensePlate: '皖NEXT',
|
|
calendarVehicleType: 'carrier'
|
|
}
|
|
)
|
|
await panel.getByRole('button', { name: '刷新', exact: true }).click()
|
|
await daily.getByText('皖OWN', { exact: true }).waitFor()
|
|
assert.equal(await daily.locator('.vehicle-card').count(), 1)
|
|
const nextDay = panel.locator('[data-date="2026-10-25"]')
|
|
assert.equal(await nextDay.locator('.vehicle-card').count(), 0)
|
|
await daily.getByRole('button', { name: '全部', exact: true }).click()
|
|
assert.equal(await daily.locator('.vehicle-card').count(), 3)
|
|
await copyButton.click()
|
|
copiedText = await page.evaluate(() => navigator.clipboard.readText())
|
|
assert.match(copiedText, /皖OUT/)
|
|
assert.match(copiedText, /皖UNKNOWN/)
|
|
assert.ok(!copiedText.includes('皖NEXT'), '只复制点击的日期')
|
|
|
|
assert.match(await daily.locator('.day-summary-button').textContent(), /合计\s*3\s*车次/)
|
|
assert.equal(await nextDay.locator('.vehicle-card').count(), 0)
|
|
await daily.getByRole('button', { name: '查看2026-10-24货品汇总' }).click()
|
|
const ownershipSummary = page.locator('.calendar-summary-popper:visible')
|
|
assert.match(await ownershipSummary.locator('.day-total').textContent(), /合计\s*3\s*车次/)
|
|
await panel.locator('.title-bar-heading').click()
|
|
await nextDay.getByRole('button', { name: '全部', exact: true }).click()
|
|
assert.equal(await nextDay.locator('.vehicle-card').count(), 1)
|
|
await daily.getByRole('button', { name: '山峡车辆', exact: true }).click()
|
|
assert.equal(await daily.locator('.vehicle-card').count(), 1)
|
|
assert.equal(await nextDay.locator('.vehicle-card').count(), 1)
|
|
await page.locator('.calendar-weekdays').click()
|
|
await page.locator('.calendar-summary-popper:visible').waitFor({ state: 'hidden' })
|
|
await copyButton.click()
|
|
copiedText = await page.evaluate(() => navigator.clipboard.readText())
|
|
assert.match(copiedText, /皖OWN/)
|
|
assert.ok(
|
|
!copiedText.includes('皖OUT') && !copiedText.includes('皖UNKNOWN'),
|
|
'复制跟随当天自有车辆筛选'
|
|
)
|
|
await page.evaluate(() => {
|
|
window.__copyWrite = navigator.clipboard.writeText.bind(navigator.clipboard)
|
|
window.__copyExec = document.execCommand
|
|
navigator.clipboard.writeText = async () => {
|
|
throw new Error('fixture clipboard denied')
|
|
}
|
|
document.execCommand = () => false
|
|
})
|
|
await copyButton.click()
|
|
await page.getByText('复制失败,请检查浏览器剪贴板权限后重试', { exact: true }).waitFor()
|
|
await page.evaluate(() => {
|
|
navigator.clipboard.writeText = window.__copyWrite
|
|
document.execCommand = window.__copyExec
|
|
})
|
|
await page.screenshot({ path: '/tmp/calendar-copy-web.png' })
|
|
await page.screenshot({ path: '/tmp/calendar-daily-ownership-web.png' })
|
|
assert.deepEqual(errors, [])
|
|
console.log(
|
|
'PASS: 日历加载、权限路由、相同任务合并且总车次不变、货品统计弹出、日格无独立滚动、车辆筛选、客户简称和蓝色配色、重置、切月、日期定位、七天无横向溢出、车辆车次排序、同排对齐和窄屏布局、隔离打印和错误重试。'
|
|
)
|
|
} catch (error) {
|
|
console.error('PAGE:', await page.locator('body').innerText())
|
|
console.error('ERRORS:', errors)
|
|
console.error(
|
|
'ROUTES:',
|
|
await page.evaluate(() =>
|
|
document
|
|
.querySelector('#app')
|
|
?.__vue_app__?.config.globalProperties.$router?.getRoutes()
|
|
.filter((r) => r.path.startsWith('/pl'))
|
|
.map((r) => ({ name: r.name, path: r.path }))
|
|
)
|
|
)
|
|
await page.screenshot({ path: '/tmp/shanxia-dispatch-calendar-failure.png' })
|
|
throw error
|
|
} finally {
|
|
await browser.close()
|
|
}
|