103 lines
5.3 KiB
JavaScript
103 lines
5.3 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import { readFile } from 'node:fs/promises';
|
|
import test from 'node:test';
|
|
|
|
const read = (path) => readFile(new URL(path, import.meta.url), 'utf8');
|
|
|
|
const centeredButtonRule = (source, selector) => {
|
|
const rule = source.match(new RegExp(`\\.${selector}\\s*\\{([^}]*)\\}`))?.[1] || '';
|
|
|
|
assert.ok(rule, `missing .${selector} style rule`);
|
|
assert.match(rule, /display:\s*flex/);
|
|
assert.match(rule, /align-items:\s*center/);
|
|
assert.match(rule, /justify-content:\s*center/);
|
|
assert.match(rule, /padding:\s*0(?:;|\s)/);
|
|
assert.match(rule, /line-height:\s*1(?:;|\s)/);
|
|
};
|
|
|
|
test('银城大喇叭仅使用认证后的真实广播接口', async () => {
|
|
const service = await read('../src/services/broadcast.ts');
|
|
|
|
assert.match(service, /\/api\/aihr\/broadcast\/unread-count/);
|
|
assert.match(service, /\/api\/aihr\/broadcast\/messages\?pageNum=/);
|
|
assert.match(service, /\/api\/aihr\/broadcast\/messages\/\$\{id\}/);
|
|
assert.match(service, /\/read`/);
|
|
assert.doesNotMatch(service, /auth:\s*false/);
|
|
});
|
|
|
|
test('首页喇叭只在确认有未读消息时显示红点,未登录保留回跳', async () => {
|
|
const page = await read('../src/pages/user/today/index.vue');
|
|
|
|
assert.match(page, /v-if="hasUnreadBroadcast" class="bell-dot(?:\s+[^\"]*)?"/);
|
|
assert.match(page, /getBroadcastUnreadCount/);
|
|
assert.match(page, /const unreadBroadcastCount = ref<number \| null>\(null\)/);
|
|
assert.match(page, /const hasUnreadBroadcast = computed\(\(\) => typeof unreadBroadcastCount\.value === 'number'/);
|
|
assert.match(page, /const request = requests\.begin\('broadcast-unread'\);\s*unreadBroadcastCount\.value = null;/);
|
|
assert.match(page, /visibleAccountKey !== nextAccountKey[\s\S]*unreadBroadcastCount\.value = null;/);
|
|
assert.match(page, /<button class="brand-bell" :aria-label="broadcastBellLabel"/);
|
|
assert.match(page, /'银城大喇叭,未读状态暂不可用'/);
|
|
assert.match(page, /'银城大喇叭,无未读消息'/);
|
|
assert.match(page, /`银城大喇叭,\$\{unreadBroadcastCount\.value\} 条未读消息`/);
|
|
assert.match(page, /rememberLoginRedirect\(path\)/);
|
|
assert.match(page, /uni\.navigateTo\(\{ url: path \}\)/);
|
|
});
|
|
|
|
test('频道支持失败重试、分页和请求失效保护', async () => {
|
|
const [list, detail] = await Promise.all([
|
|
read('../src/pages/user/broadcast/index.vue'),
|
|
read('../src/pages/user/broadcast/detail.vue')
|
|
]);
|
|
|
|
assert.match(list, /v-else-if="loadFailed"/);
|
|
assert.match(list, /role="alert" aria-live="assertive"/);
|
|
assert.match(list, /role="status" aria-live="polite"/);
|
|
assert.match(list, /@click="load">重新加载/);
|
|
assert.match(list, /v-if="hasMore" class="load-more"/);
|
|
assert.match(list, /const loadMore = async \(\)/);
|
|
assert.match(list, /listBroadcastMessages\(nextPageNum, pageSize, scope\.value\)/);
|
|
assert.match(list, /createPageRequestScope/);
|
|
assert.match(list, /const clearLoading = \(\) => \{[\s\S]*loadingMore\.value = false;/);
|
|
assert.match(list, /onHide\(\(\) => \{[\s\S]*clearLoading\(\);[\s\S]*requests\.invalidate\(\);/);
|
|
assert.match(list, /onUnload\(\(\) => \{[\s\S]*clearLoading\(\);[\s\S]*requests\.invalidate\(\);/);
|
|
assert.match(list, /uni\.redirectTo\(\{ url: '\/pages\/auth\/login\/index' \}\)/);
|
|
assert.match(detail, /markBroadcastMessageRead\(id\.value\)/);
|
|
assert.match(detail, /item\.value = \{ \.\.\.next, read: true \}/);
|
|
assert.match(detail, /Number\.isSafeInteger\(nextId\) \|\| nextId <= 0/);
|
|
assert.match(detail, /role="alert" aria-live="assertive"/);
|
|
assert.match(detail, /role="status" aria-live="polite"/);
|
|
assert.match(list, /onShow\(\(\) => \{[\s\S]*void load\(\)/);
|
|
});
|
|
|
|
test('消息详情只交接短期且账号绑定的消息 ID,再进入问模块', async () => {
|
|
const [detail, service] = await Promise.all([
|
|
read('../src/pages/user/broadcast/detail.vue'),
|
|
read('../src/services/broadcast.ts')
|
|
]);
|
|
|
|
assert.match(detail, /@click="askAboutMessage">问这条消息/);
|
|
assert.match(detail, /saveBroadcastQuestionContext\(item\.value\.id, currentAccountKey\(\)\)/);
|
|
assert.match(detail, /uni\.switchTab\(\{[\s\S]*url: '\/pages\/user\/sop\/index'/);
|
|
assert.match(detail, /error\.statusCode === 404 \|\| error\.bizCode === 404/);
|
|
assert.match(detail, /readBroadcastQuestionContext\(currentAccountKey\(\)\)\?\.messageId === id\.value/);
|
|
assert.match(detail, /clearBroadcastQuestionContext\(\)/);
|
|
assert.match(service, /broadcastQuestionContextTtlMs = 15 \* 60 \* 1000/);
|
|
assert.match(service, /messageId,\s*accountKey,\s*expiresAt: Date\.now\(\) \+ ttlMs/);
|
|
assert.match(service, /context\.accountKey !== accountKey \|\| context\.expiresAt <= now/);
|
|
assert.match(service, /clearBroadcastQuestionContext\(\)/);
|
|
});
|
|
|
|
test('M0/M1 的短文本操作控件始终在可点击区域内居中', async () => {
|
|
const [base, list, detail, ask] = await Promise.all([
|
|
read('../src/styles/base.css'),
|
|
read('../src/pages/user/broadcast/index.vue'),
|
|
read('../src/pages/user/broadcast/detail.vue'),
|
|
read('../src/pages/user/sop/index.vue')
|
|
]);
|
|
|
|
assert.match(base, /\.primary-button,\s*\.secondary-button,\s*\.ghost-button\s*\{[^}]*display:\s*flex[^}]*align-items:\s*center[^}]*justify-content:\s*center/);
|
|
centeredButtonRule(list, 'scope-tab');
|
|
centeredButtonRule(list, 'load-more');
|
|
centeredButtonRule(detail, 'ask-message-button');
|
|
centeredButtonRule(ask, 'broadcast-context-action');
|
|
});
|