|
|
@@ -1,124 +0,0 @@
|
|
|
-// 独立视觉/交互测试:只在此测试服务器替换接口与地图,不改变生产页面的数据源。
|
|
|
-// PLAYWRIGHT_MODULE 指向已安装 playwright 的 index.mjs,BROWSER_EXECUTABLE 可指定浏览器。
|
|
|
-import { mkdtemp } from 'node:fs/promises'
|
|
|
-import { tmpdir } from 'node:os'
|
|
|
-import path from 'node:path'
|
|
|
-import { pathToFileURL } from 'node:url'
|
|
|
-import assert from 'node:assert/strict'
|
|
|
-import { createServer } from 'vite'
|
|
|
-import vue from '@vitejs/plugin-vue'
|
|
|
-import AutoImport from 'unplugin-auto-import/vite'
|
|
|
-
|
|
|
-const { chromium } = await import(process.env.PLAYWRIGHT_MODULE ? pathToFileURL(process.env.PLAYWRIGHT_MODULE).href : 'playwright')
|
|
|
-const output = await mkdtemp(path.join(tmpdir(), 'alarm-gis-visual-'))
|
|
|
-const samples = [
|
|
|
- { id: 'a1', equipmentId: 'e1', deviceCode: 'PS-DEMO-001', deviceName: '城北路液位监测点', equipmentLocation: '城北路与人民路交叉口东侧', alarmLevel: 1, actualValue: null, longitude: '110.40', latitude: '28.46' },
|
|
|
- { id: 'a2', equipmentId: 'e1', deviceCode: 'PS-DEMO-001', deviceName: '城北路液位监测点', equipmentLocation: '城北路与人民路交叉口东侧', alarmLevel: 2, actualValue: 0, longitude: '110.40', latitude: '28.46' },
|
|
|
- { id: 'b1', equipmentId: 'e2', deviceCode: 'PS-DEMO-002', deviceName: '沿江路流量监测点', equipmentLocation: '沿江路排水管网检查井', alarmLevel: 2, actualValue: 2.36, longitude: '110.41', latitude: '28.47' },
|
|
|
- { id: 'c1', equipmentId: 'e3', deviceCode: 'PS-DEMO-003', deviceName: '人民路井盖监测点', equipmentLocation: '人民路北侧步行道', alarmLevel: 3, actualValue: null, longitude: null, latitude: null },
|
|
|
- { id: 'd1', equipmentId: 'e4', deviceCode: 'PS-DEMO-004', deviceName: '建设路液位监测点', equipmentLocation: '建设路与文化路交叉口', alarmLevel: 4, actualValue: 1.26, longitude: '110.42', latitude: '28.48' }
|
|
|
-].map((row, index) => ({ ...row, alarmNo: 'BJ20260924102000000' + index, createTime: '2026-09-24 10:20:00', alarmStatus: 0, monitorStatusName: '异常', auditStatus: 0, auditStatusName: '未审核', orderStatusName: '未转工单', warningCode: 'WARN_INSTANT_FLOW', warningType: '液位', warningUnit: 'm', maxValue: 1.8, alarmLevelName: ['一级报警', '二级报警', '三级报警', '四级报警'][row.alarmLevel - 1] }))
|
|
|
-const apiModule = `
|
|
|
-const samples = ${JSON.stringify(samples)};
|
|
|
-const response = data => Promise.resolve({ data });
|
|
|
-export const getAlarmOptions = () => response({ alarmLevels: ['一级报警','二级报警','三级报警','四级报警'].map((label,i)=>({value:i+1,label})), monitorStatuses:[{value:0,label:'异常'},{value:1,label:'已恢复'}] });
|
|
|
-export const getAlarmMap = params => { window.__gisRequests.push(params); return window.__gisDataError ? Promise.reject(new Error('测试接口异常,请重试')) : response(samples.filter(row=>(params.alarmLevel == null || row.alarmLevel===params.alarmLevel) && (params.alarmStatus == null || row.alarmStatus===params.alarmStatus) && (!params.keyword || row.deviceCode.includes(params.keyword) || row.deviceName.includes(params.keyword)))); };
|
|
|
-export const getAlarms = params => { window.__gisHistoryRequests.push(params); const rows=samples.filter(row=>row.deviceCode===params.deviceCode); return response({records:rows,total:rows.length}); };
|
|
|
-export const getAlarmAnalysis = id => { window.__gisAnalysisRequests.push(id); return response({ alarm:samples.find(row=>row.id===id), supported:true, samples:[], message:'测试数据:暂无区间采样' }); };
|
|
|
-export const getAlarm = id => response(samples.find(row=>row.id===id));
|
|
|
-export const getAlarmTimeline = () => response([]);
|
|
|
-`
|
|
|
-const scopeModule = `import { ref, computed } from 'vue'; const scope=ref({rootTypeId:2}); export function useAlarmScope(){return {scope,scopeKey:computed(()=>JSON.stringify(scope.value)),route:{query:{}},menu:()=>null,navigate:()=>{}}}`
|
|
|
-const mapModule = `import { onMounted, h } from 'vue'; export default {props:['points'],emits:['ready','error','point-click','cluster-click'],setup(props,{emit,expose}){expose({fitBounds(){},locatePoint(point){window.__gisLocated=point.deviceCode},zoomIn(){},zoomOut(){}});onMounted(()=>window.__gisMapFails?emit('error','测试环境:底图不可用,列表及详情不受影响。'):emit('ready'));return()=>h('div',{class:'gis-map-canvas','data-testid':'map-fixture',style:'height:100%;background:#f4f7fb'},window.__gisMapFails?[]:props.points.map(point=>h('button',{'data-testid':'map-marker',onClick:()=>emit('point-click',point)},point.name)));}}`
|
|
|
-const entry = `
|
|
|
-import {createApp} from 'vue'; import ElementPlus from 'element-plus'; import 'element-plus/dist/index.css'; import zhCn from 'element-plus/es/locale/lang/zh-cn';
|
|
|
-import Page from '/src/views/subSystem/alarm/drainage/alarmGIS.vue'; import Pagination from '/src/components/Pagination/index.vue';
|
|
|
-window.__gisRequests=[];window.__gisHistoryRequests=[];window.__gisAnalysisRequests=[];window.__gisMapFails=true;
|
|
|
-const app=createApp(Page);app.use(ElementPlus,{locale:zhCn});app.component('pagination',Pagination);app.mount('#app');
|
|
|
-`
|
|
|
-const fixture = {
|
|
|
- name: 'alarm-gis-visual-fixture', enforce: 'pre',
|
|
|
- resolveId(id) {
|
|
|
- if (id === 'virtual:gis-entry') return '\0gis-entry'
|
|
|
- if (id === 'virtual:gis-api') return '\0gis-api'
|
|
|
- if (id.endsWith('/useAlarmScope') || id.endsWith('/useAlarmScope.js')) return '\0gis-scope'
|
|
|
- if (id === 'virtual:gis-map') return '\0gis-map'
|
|
|
- },
|
|
|
- load(id) { return ({ '\0gis-entry': entry, '\0gis-api': apiModule, '\0gis-scope': scopeModule, '\0gis-map': mapModule })[id] },
|
|
|
- configureServer(server) {
|
|
|
- server.middlewares.use((req, res, next) => {
|
|
|
- if (req.url !== '/__alarm-gis-fixture') return next()
|
|
|
- res.setHeader('Content-Type', 'text/html; charset=utf-8')
|
|
|
- res.end('<!doctype html><html lang="zh-CN"><meta charset="utf-8"><style>body{margin:0;font-family:"Microsoft YaHei",sans-serif;background:#f5f7fa}*{box-sizing:border-box}button{font-family:inherit}</style><div id="app"></div><script type="module" src="/@id/virtual:gis-entry"></script></html>')
|
|
|
- })
|
|
|
- }
|
|
|
-}
|
|
|
-const server = await createServer({
|
|
|
- configFile: false, root: process.cwd(), plugins: [fixture, vue(), AutoImport({ imports: ['vue'], dts: false })],
|
|
|
- cacheDir: path.join(output, 'vite-cache'),
|
|
|
- optimizeDeps: { entries: [], include: ['vue', 'element-plus', '@element-plus/icons-vue', 'echarts'] },
|
|
|
- resolve: { alias: [{find:'@/api/alarm',replacement:'virtual:gis-api'},{find:'@/components/GisMapCanvas.vue',replacement:'virtual:gis-map'},{find:'@',replacement:path.resolve('src')}] },
|
|
|
- server: { host: '127.0.0.1', port: 0 }, logLevel: 'error'
|
|
|
-})
|
|
|
-let browser
|
|
|
-try {
|
|
|
- await server.listen()
|
|
|
- browser = await chromium.launch({ headless: true, executablePath: process.env.BROWSER_EXECUTABLE || undefined })
|
|
|
- const page = await browser.newPage({ viewport: { width: 1366, height: 1000 }, deviceScaleFactor: 1 })
|
|
|
- const pageErrors = []
|
|
|
- page.on('pageerror', error => pageErrors.push(error.message))
|
|
|
- await page.route('**/*', route => route.request().url().startsWith('http://127.0.0.1:') ? route.continue() : route.abort())
|
|
|
- await page.goto('http://127.0.0.1:' + server.httpServer.address().port + '/__alarm-gis-fixture')
|
|
|
- await page.getByRole('heading', {name:'当前报警 GIS 一张图'}).waitFor()
|
|
|
- await page.locator('.gis-device-item').nth(3).waitFor()
|
|
|
- assert.equal(await page.locator('.gis-level-metric').count(),4)
|
|
|
- assert.deepEqual(await page.locator('.gis-level-metric > strong').allTextContents(),['1台','1台','1台','1台'])
|
|
|
- assert.equal(await page.getByRole('button',{name:'放大地图'}).isDisabled(),true)
|
|
|
- await page.screenshot({path:path.join(output,'desktop.png'),fullPage:true})
|
|
|
- const mapBefore = await page.locator('.gis-map-stage').boundingBox()
|
|
|
- await page.getByLabel('报警设备列表').getByRole('button',{name:'城北路液位监测点',exact:true}).click()
|
|
|
- await page.locator('.alarm-gis-drawer').waitFor()
|
|
|
- await page.getByRole('tab',{name:'监测曲线',exact:true}).waitFor()
|
|
|
- await page.waitForFunction(()=>window.__gisAnalysisRequests.includes('a2'))
|
|
|
- assert.ok(!(await page.evaluate(()=>window.__gisAnalysisRequests)).includes('a1'))
|
|
|
- assert.equal((await page.locator('.gis-map-stage').boundingBox()).width,mapBefore.width)
|
|
|
- await page.getByRole('tab',{name:'报警记录',exact:true}).click()
|
|
|
- assert.equal(await page.locator('.gis-history-item').count(),2)
|
|
|
- assert.equal(await page.locator('.gis-history-actions').getByRole('button',{name:'查看曲线'}).count(),1)
|
|
|
- assert.equal(await page.locator('.pagination-container').isVisible(),true)
|
|
|
- await page.screenshot({path:path.join(output,'drawer-history.png')})
|
|
|
- await page.getByRole('tab',{name:'设备信息',exact:true}).click()
|
|
|
- assert.equal(await page.locator('.gis-detail-grid').last().getByText('110.4',{exact:true}).count(),1)
|
|
|
- await page.keyboard.press('Escape')
|
|
|
- await page.locator('.alarm-gis-drawer').waitFor({state:'hidden'})
|
|
|
- await page.getByRole('button',{name:'人民路井盖监测点',exact:true}).click()
|
|
|
- assert.equal(await page.getByRole('tab',{name:'报警记录',exact:true}).getAttribute('aria-selected'),'true')
|
|
|
- await page.getByRole('tab',{name:'监测曲线',exact:true}).click()
|
|
|
- await page.getByText('暂无有实际值的报警指标',{exact:true}).waitFor()
|
|
|
- await page.keyboard.press('Escape')
|
|
|
- await page.locator('.alarm-gis-drawer').waitFor({state:'hidden'})
|
|
|
- await page.evaluate(()=>window.__gisMapFails=false)
|
|
|
- await page.getByRole('button',{name:'重试底图',exact:true}).click()
|
|
|
- await page.getByText('地图已就绪',{exact:true}).waitFor()
|
|
|
- assert.equal(await page.getByRole('button',{name:'放大地图'}).isDisabled(),false)
|
|
|
- assert.equal(await page.getByTestId('map-marker').count(),3)
|
|
|
- await page.locator('.gis-device-item').first().getByRole('button',{name:'定位',exact:true}).click()
|
|
|
- assert.equal(await page.evaluate(()=>window.__gisLocated),'PS-DEMO-001')
|
|
|
- await page.getByPlaceholder('搜索设备编码、名称或安装位置').fill('无匹配设备')
|
|
|
- await page.getByRole('button',{name:'查询',exact:true}).click()
|
|
|
- await page.getByText('暂无匹配的报警设备',{exact:true}).waitFor()
|
|
|
- await page.getByRole('button',{name:'重置',exact:true}).click()
|
|
|
- await page.locator('.gis-device-item').nth(3).waitFor()
|
|
|
- await page.setViewportSize({width:390,height:844})
|
|
|
- assert.equal(await page.evaluate(()=>document.documentElement.scrollWidth <= window.innerWidth),true)
|
|
|
- await page.screenshot({path:path.join(output,'mobile.png'),fullPage:true})
|
|
|
- await page.getByLabel('报警设备列表').getByRole('button',{name:'城北路液位监测点',exact:true}).click()
|
|
|
- await page.getByRole('tab',{name:'报警记录',exact:true}).click()
|
|
|
- await page.screenshot({path:path.join(output,'mobile-drawer.png')})
|
|
|
- assert.equal(await page.locator('.alarm-gis-drawer').evaluate(el=>el.scrollWidth <= el.clientWidth),true)
|
|
|
- assert.deepEqual(pageErrors,[])
|
|
|
- console.log('GIS visual/interaction checks passed. Screenshots: ' + output)
|
|
|
-} finally {
|
|
|
- await browser?.close()
|
|
|
- await server.close()
|
|
|
-}
|