合并 Web Tools 0.1.0 #1
+1
-1
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
### Verification
|
### Verification
|
||||||
|
|
||||||
- 86 条 Vitest 测试通过,页面元数据测试覆盖标准 description、`og:description`、Manifest 描述、favicon 回退入口以及无自定义分享图约束。
|
- 87 条 Vitest 测试通过,页面元数据测试覆盖标准 description、唯一允许的 `og:description`、Manifest 描述、favicon 回退入口和无自定义分享图约束,并增加发布版本跨文件一致性检查。
|
||||||
- Vue/TypeScript 类型检查和生产构建通过。
|
- Vue/TypeScript 类型检查和生产构建通过。
|
||||||
|
|
||||||
## 0.0.6 - 2026-08-08
|
## 0.0.6 - 2026-08-08
|
||||||
|
|||||||
@@ -154,13 +154,15 @@ describe('application branding assets', () => {
|
|||||||
|
|
||||||
it('declares one product description for standard and Open Graph consumers without a custom image', async () => {
|
it('declares one product description for standard and Open Graph consumers without a custom image', async () => {
|
||||||
const html = (await readProjectFile('index.html')).toString('utf8')
|
const html = (await readProjectFile('index.html')).toString('utf8')
|
||||||
|
const socialMetadata = [...html.matchAll(/<meta\s+(?:name|property)="((?:og|twitter):[^"]+)"/gi)]
|
||||||
|
.map((match) => match[1].toLowerCase())
|
||||||
|
|
||||||
expect(html).toContain('<meta name="description" content="一个匿名访问、自托管的浏览器本地工具箱" />')
|
expect(html).toContain('<meta name="description" content="一个匿名访问、自托管的浏览器本地工具箱" />')
|
||||||
expect(html).toContain('<meta property="og:description" content="一个匿名访问、自托管的浏览器本地工具箱" />')
|
expect(html).toContain('<meta property="og:description" content="一个匿名访问、自托管的浏览器本地工具箱" />')
|
||||||
expect(html.match(/一个匿名访问、自托管的浏览器本地工具箱/g)).toHaveLength(2)
|
expect(html.match(/一个匿名访问、自托管的浏览器本地工具箱/g)).toHaveLength(2)
|
||||||
|
expect(socialMetadata).toEqual(['og:description'])
|
||||||
expect(html).not.toContain('share-preview.png')
|
expect(html).not.toContain('share-preview.png')
|
||||||
expect(html).not.toMatch(/(?:name|property)="(?:og|twitter):[^\"]*image/i)
|
await expect(access(path.join(publicRoot, 'share-preview.png'))).rejects.toMatchObject({ code: 'ENOENT' })
|
||||||
expect(html).not.toMatch(/(?:name|property)="twitter:/i)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('includes public assets in container builds', async () => {
|
it('includes public assets in container builds', async () => {
|
||||||
|
|||||||
@@ -11,6 +11,27 @@ async function readProjectFile(relativePath) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe('deployment configuration', () => {
|
describe('deployment configuration', () => {
|
||||||
|
it('keeps the release version synchronized across project and deployment metadata', async () => {
|
||||||
|
const [packageText, lockText, compose, readme, changelog] = await Promise.all([
|
||||||
|
readProjectFile('package.json'),
|
||||||
|
readProjectFile('package-lock.json'),
|
||||||
|
readProjectFile('docker-compose.yml'),
|
||||||
|
readProjectFile('README.zh-CN.md'),
|
||||||
|
readProjectFile('CHANGELOG.md'),
|
||||||
|
])
|
||||||
|
const packageJson = JSON.parse(packageText)
|
||||||
|
const packageLock = JSON.parse(lockText)
|
||||||
|
const version = packageJson.version
|
||||||
|
|
||||||
|
expect(version).toMatch(/^\d+\.\d+\.\d+$/)
|
||||||
|
expect(packageLock.version).toBe(version)
|
||||||
|
expect(packageLock.packages[''].version).toBe(version)
|
||||||
|
expect(compose.match(/^\s*image:\s*personal-web-tools:(\S+)$/m)?.[1]).toBe(version)
|
||||||
|
expect(readme).toContain(`当前应用版本:\`${version}\`。`)
|
||||||
|
expect(readme).toContain(`personal-web-tools-${version}-amd64.tar`)
|
||||||
|
expect(changelog.match(/^## (\d+\.\d+\.\d+) - /m)?.[1]).toBe(version)
|
||||||
|
})
|
||||||
|
|
||||||
it('keeps the default production port synchronized', async () => {
|
it('keeps the default production port synchronized', async () => {
|
||||||
const [dockerfile, compose, environment, script, readme] = await Promise.all([
|
const [dockerfile, compose, environment, script, readme] = await Promise.all([
|
||||||
readProjectFile('Dockerfile'),
|
readProjectFile('Dockerfile'),
|
||||||
|
|||||||
Reference in New Issue
Block a user