feat: add bilingual release notes
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
import { mkdtemp, rm, writeFile } from 'node:fs/promises'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { afterEach, describe, expect, it } from 'vitest'
|
||||
import { ApplicationSettingsStore } from './application-settings-store'
|
||||
import { ReleaseNotesService } from './release-notes-service'
|
||||
|
||||
const temporaryDirectories: string[] = []
|
||||
|
||||
const localizedNotes = (label: string) => ({
|
||||
'zh-CN': {
|
||||
features: [`${label} 功能`],
|
||||
fixes: [`${label} 修复`]
|
||||
},
|
||||
'en-US': {
|
||||
features: [`${label} feature`],
|
||||
fixes: [`${label} fix`]
|
||||
}
|
||||
})
|
||||
|
||||
async function createService(
|
||||
currentVersion: string
|
||||
): Promise<{
|
||||
filePath: string
|
||||
service: ReleaseNotesService
|
||||
settingsStore: ApplicationSettingsStore
|
||||
}> {
|
||||
const directory = await mkdtemp(join(tmpdir(), 'goodbuddy-release-notes-'))
|
||||
temporaryDirectories.push(directory)
|
||||
const filePath = join(directory, 'release-notes.json')
|
||||
await writeFile(
|
||||
filePath,
|
||||
JSON.stringify({
|
||||
formatVersion: 1,
|
||||
releases: [
|
||||
{
|
||||
version: '0.8.12',
|
||||
releasedAt: '2026-08-04',
|
||||
notes: localizedNotes('0.8.12')
|
||||
},
|
||||
{
|
||||
version: '0.8.18',
|
||||
releasedAt: '2026-08-11',
|
||||
notes: localizedNotes('0.8.18')
|
||||
}
|
||||
]
|
||||
}),
|
||||
'utf8'
|
||||
)
|
||||
const settingsStore = new ApplicationSettingsStore(
|
||||
join(directory, 'application-settings.json')
|
||||
)
|
||||
return {
|
||||
filePath,
|
||||
settingsStore,
|
||||
service: new ReleaseNotesService({
|
||||
currentVersion,
|
||||
filePath,
|
||||
settingsStore
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
afterEach(async () => {
|
||||
await Promise.all(
|
||||
temporaryDirectories.splice(0).map((directory) =>
|
||||
rm(directory, { recursive: true, force: true })
|
||||
)
|
||||
)
|
||||
})
|
||||
|
||||
describe('ReleaseNotesService', () => {
|
||||
it('shows only the current release on a fresh installation', async () => {
|
||||
const { service } = await createService('0.8.18')
|
||||
|
||||
await expect(service.getPending()).resolves.toMatchObject({
|
||||
currentVersion: '0.8.18',
|
||||
releases: [{ version: '0.8.18' }]
|
||||
})
|
||||
})
|
||||
|
||||
it('shows every unseen release through the current version', async () => {
|
||||
const { service, settingsStore } = await createService('0.8.18')
|
||||
await settingsStore.setLastSeenReleaseNotesVersion('0.8.11')
|
||||
|
||||
await expect(service.getPending()).resolves.toMatchObject({
|
||||
releases: [{ version: '0.8.12' }, { version: '0.8.18' }]
|
||||
})
|
||||
})
|
||||
|
||||
it('persists acknowledgement and does not show the release again', async () => {
|
||||
const { service, settingsStore } = await createService('0.8.18')
|
||||
|
||||
await service.acknowledge({ version: '0.8.18' })
|
||||
|
||||
await expect(service.getPending()).resolves.toEqual({
|
||||
currentVersion: '0.8.18',
|
||||
releases: []
|
||||
})
|
||||
await expect(
|
||||
settingsStore.getLastSeenReleaseNotesVersion()
|
||||
).resolves.toBe('0.8.18')
|
||||
})
|
||||
|
||||
it('rejects acknowledgement for another or unknown version', async () => {
|
||||
const { service } = await createService('0.8.18')
|
||||
|
||||
await expect(
|
||||
service.acknowledge({ version: '0.8.12' })
|
||||
).rejects.toThrow('Only the current release notes can be acknowledged')
|
||||
await expect(
|
||||
service.acknowledge({ version: '0.8.19' })
|
||||
).rejects.toThrow('Only the current release notes can be acknowledged')
|
||||
})
|
||||
|
||||
it('does not reopen release notes after an application downgrade', async () => {
|
||||
const { service, settingsStore } = await createService('0.8.12')
|
||||
await settingsStore.setLastSeenReleaseNotesVersion('0.8.18')
|
||||
|
||||
await expect(service.getPending()).resolves.toEqual({
|
||||
currentVersion: '0.8.12',
|
||||
releases: []
|
||||
})
|
||||
})
|
||||
|
||||
it('rejects an oversized release-notes resource with a bounded read', async () => {
|
||||
const { filePath, service } = await createService('0.8.18')
|
||||
await writeFile(filePath, ' '.repeat(128 * 1024 + 1), 'utf8')
|
||||
|
||||
await expect(service.getPending()).rejects.toThrow(
|
||||
'Release notes exceed the size limit'
|
||||
)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user