mirror of
https://github.com/BeamMP/BeamMP-Website.git
synced 2026-10-26 05:50:33 +00:00
Add Vitest tests for the languages, router, footer and pages, and a lint:check script
This commit is contained in:
1 parent
9f20c38abe
commit
77c1d01025
11 files changed
+2095
-6
No files matched your search
@@ -0,0 +1,90 @@
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { flushPromises, mount } from '@vue/test-utils'
|
||||
import { setupI18n } from '@/i18n'
|
||||
import en from '@/locales/en.json'
|
||||
import router from '@/routes'
|
||||
import App from '@/App.vue'
|
||||
|
||||
export const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
|
||||
export const publicFile = (name) => fs.readFileSync(path.join(root, 'public', name), 'utf8')
|
||||
|
||||
// The same i18n the app builds in main.js, with English loaded. The router's
|
||||
// guard reads window.i18n to switch language, so it is set here too.
|
||||
export function installI18n(locale = 'en') {
|
||||
const i18n = setupI18n({ legacy: false, locale, fallbackLocale: 'en', messages: { en } })
|
||||
window.i18n = i18n
|
||||
return i18n
|
||||
}
|
||||
|
||||
const reply = (body, ok = true, status = ok ? 200 : 503) => ({
|
||||
ok,
|
||||
status,
|
||||
json: async () => (typeof body === 'string' ? JSON.parse(body) : body),
|
||||
text: async () => (typeof body === 'string' ? body : JSON.stringify(body)),
|
||||
})
|
||||
|
||||
/**
|
||||
* Stands in for fetch. Local files come from the repo's public folder; the
|
||||
* backend feeds can be given as data, or left to answer 503 ("backend down").
|
||||
* Nothing reaches the network, and a URL nobody planned for fails the test.
|
||||
*/
|
||||
export function stubFetch({ servers, metrics } = {}) {
|
||||
const calls = []
|
||||
const stub = async (url) => {
|
||||
const address = String(url)
|
||||
calls.push(address)
|
||||
if (
|
||||
address.startsWith('/docs/') ||
|
||||
address === '/partners.json' ||
|
||||
address === '/servers.json'
|
||||
) {
|
||||
return reply(publicFile(address.slice(1)))
|
||||
}
|
||||
if (address === 'https://backend.beammp.com/servers-info')
|
||||
return servers ? reply(servers) : reply('', false)
|
||||
if (address === 'https://api.beammp.com/metrics')
|
||||
return metrics ? reply(metrics) : reply('', false)
|
||||
// The statistics page's release and stats feeds: down unless a test says otherwise.
|
||||
if (
|
||||
/^https:\/\/(api|backend)\.beammp\.com\//.test(address) ||
|
||||
address.startsWith('https://api.github.com/')
|
||||
)
|
||||
return reply('', false)
|
||||
throw new Error(`Unplanned fetch to ${address}`)
|
||||
}
|
||||
stub.calls = calls
|
||||
vi.stubGlobal('fetch', stub)
|
||||
return stub
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs `action` (a navigation) and fails it if the router's language guard
|
||||
* keeps redirecting. A runaway redirect would otherwise freeze the test run
|
||||
* the way it freezes the page. The guard reads the saved language on every
|
||||
* redirect, which is what is counted.
|
||||
*/
|
||||
export async function withRedirectLimit(action, limit = 5) {
|
||||
const real = localStorage.getItem.bind(localStorage)
|
||||
let passes = 0
|
||||
localStorage.getItem = (key) => {
|
||||
if (key === 'lang' && ++passes > limit) throw new Error('still redirecting')
|
||||
return real(key)
|
||||
}
|
||||
try {
|
||||
return await action()
|
||||
} finally {
|
||||
localStorage.getItem = real
|
||||
}
|
||||
}
|
||||
|
||||
/** Opens a page of the real app (router, layout, nav and footer) and lets it finish loading. */
|
||||
export async function openPage(pathname) {
|
||||
const i18n = installI18n('en')
|
||||
await withRedirectLimit(() => router.push(pathname))
|
||||
await router.isReady()
|
||||
const wrapper = mount(App, { attachTo: document.body, global: { plugins: [i18n, router] } })
|
||||
await flushPromises()
|
||||
return wrapper
|
||||
}
|
||||
Reference in new issue
Block a user