111
This commit is contained in:
@@ -5,7 +5,7 @@ import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import vm from 'node:vm'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { parse, compileScript } from 'vue/compiler-sfc'
|
||||
import { parse, compileScript, compileStyle } from 'vue/compiler-sfc'
|
||||
import { createSSRApp, h, isRef } from 'vue'
|
||||
import { renderToString } from 'vue/server-renderer'
|
||||
import { createMemoryHistory, createRouter } from 'vue-router'
|
||||
@@ -183,3 +183,47 @@ test('auth and both questionnaires render safely; loading records never show an
|
||||
assert.ok(!html.includes('type="number"')); assert.ok(!html.includes('<textarea'))
|
||||
}
|
||||
})
|
||||
|
||||
test('reduced-motion stops all loading animations rather than making infinite loops faster', () => {
|
||||
const readStylesheet = relative => {
|
||||
const filename = path.join(root, relative)
|
||||
const result = compileStyle({ source: fs.readFileSync(filename, 'utf8'), filename, id: 'test-motion' })
|
||||
assert.deepEqual(result.errors, [], relative)
|
||||
return result.rawResult.root
|
||||
}
|
||||
const stylesheet = readStylesheet('styles/page-polish.css')
|
||||
const reducedMotion = stylesheet.nodes.find(node => node.type === 'atrule'
|
||||
&& node.name === 'media' && node.params === '(prefers-reduced-motion: reduce)')
|
||||
assert.ok(reducedMotion, 'keep the reduced-motion preference supported')
|
||||
const rule = reducedMotion.nodes.find(node => node.type === 'rule'
|
||||
&& ['*', '*::before', '*::after'].every(selector => node.selectors.includes(selector)))
|
||||
assert.ok(rule, 'cover page indicators, device indicators and Vant loading animations')
|
||||
const declarations = Object.fromEntries(rule.nodes.filter(node => node.type === 'decl')
|
||||
.map(node => [node.prop, node]))
|
||||
assert.equal(declarations.animation?.value, 'none')
|
||||
assert.equal(declarations.animation?.important, true)
|
||||
assert.equal(declarations['transition-duration']?.value, '0s')
|
||||
assert.equal(declarations['transition-duration']?.important, true)
|
||||
reducedMotion.walkDecls('animation-duration', declaration => {
|
||||
assert.notEqual(declaration.value, '.01ms', 'never accelerate an infinite loading animation')
|
||||
})
|
||||
|
||||
const loadingRule = stylesheet.nodes.find(node => node.type === 'rule' && node.selector === '.page-loading-mark')
|
||||
assert.ok(loadingRule.nodes.some(node => node.prop === 'animation' && node.value === 'page-spin .9s linear infinite'),
|
||||
'normal motion keeps the existing loading speed')
|
||||
const deviceStyles = readStylesheet('styles/device-control.css')
|
||||
const deviceLoadingRule = deviceStyles.nodes.find(node => node.type === 'rule' && node.selector === '.control-page .operation-spinner')
|
||||
assert.ok(deviceLoadingRule.nodes.some(node => node.prop === 'animation' && node.value === 'operation-spin 0.75s linear infinite'))
|
||||
})
|
||||
|
||||
test('loading indicators keep visible status text even when their animation is stopped', async () => {
|
||||
for (const [name, routePath, message] of [
|
||||
['DashboardView', '/dashboard', '正在读取健康档案与舒睡设备…'],
|
||||
['ProfileView', '/profile', '正在读取您的健康档案…'],
|
||||
]) {
|
||||
const html = await render(name, { loading: true }, routePath)
|
||||
assert.ok(html.includes('page-loading-mark'), name)
|
||||
assert.ok(html.includes(message), name)
|
||||
assert.ok(html.includes('role="status"'), name)
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user