fix(netflow): пропустить загрузку флага неизвестной страны
This commit is contained in:
1 parent
cf211f7418
commit
5d181e7cb0
2 files changed
+28
-7
No files matched your search
+11
-5
@@ -59,10 +59,17 @@ function nearestCdnSize(px: number): number {
|
|||||||
return CDN_SIZES.find(s => s >= px) ?? CDN_SIZES[CDN_SIZES.length - 1]
|
return CDN_SIZES.find(s => s >= px) ?? CDN_SIZES[CDN_SIZES.length - 1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function flagCode(code: string): string | null {
|
||||||
|
if (!code) return null
|
||||||
|
const lower = code.toLowerCase()
|
||||||
|
// The server catalogue uses UN when the country is unknown.
|
||||||
|
return lower !== "un" && /^[a-z]{2}$/.test(lower) ? lower : null
|
||||||
|
}
|
||||||
|
|
||||||
/** CDN URL for SVG `<image href>` (flagcdn widths only). */
|
/** CDN URL for SVG `<image href>` (flagcdn widths only). */
|
||||||
export function flagCdnUrl(code: string, size = 40): string | null {
|
export function flagCdnUrl(code: string, size = 40): string | null {
|
||||||
const lower = code.toLowerCase()
|
const lower = flagCode(code)
|
||||||
if (!/^[a-z]{2}$/.test(lower)) return null
|
if (!lower) return null
|
||||||
return `https://flagcdn.com/w${nearestCdnSize(size)}/${lower}.png`
|
return `https://flagcdn.com/w${nearestCdnSize(size)}/${lower}.png`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,9 +78,8 @@ export function flagCdnUrl(code: string, size = 40): string | null {
|
|||||||
* Source: https://flagcdn.com — free CDN, no API key needed.
|
* Source: https://flagcdn.com — free CDN, no API key needed.
|
||||||
*/
|
*/
|
||||||
export function Flag({ code, size = 20, className }: FlagProps) {
|
export function Flag({ code, size = 20, className }: FlagProps) {
|
||||||
if (!code) return null
|
const lower = flagCode(code)
|
||||||
const lower = code.toLowerCase()
|
if (!lower) return null
|
||||||
if (!/^[a-z]{2}$/.test(lower)) return null
|
|
||||||
const name = countryName(code.toUpperCase())
|
const name = countryName(code.toUpperCase())
|
||||||
const cdnSrc = nearestCdnSize(size)
|
const cdnSrc = nearestCdnSize(size)
|
||||||
const cdnSrc2x = nearestCdnSize(size * 2)
|
const cdnSrc2x = nearestCdnSize(size * 2)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { installOpenLiveStream, resumeLiveStream, sendLiveHeartbeat } from "./live-stream-fixture"
|
import { installOpenLiveStream, resumeLiveStream, sendLiveHeartbeat } from "./live-stream-fixture"
|
||||||
import { test, expect, type Page } from '@playwright/test'
|
import { test, expect, type Page } from '@playwright/test'
|
||||||
|
|
||||||
async function setup(page: Page, liveRefusals = 0) {
|
async function setup(page: Page, liveRefusals = 0, unknownServer = false) {
|
||||||
const control = { emptyExporters: false, failCatalog: false, hold: '', holdIface: '', fail: false, failList: false, invalidSample: undefined as unknown, mergeSample: false, metrics: {} as Record<string, unknown>, release: () => {}, liveCalls: 0 }
|
const control = { emptyExporters: false, failCatalog: false, hold: '', holdIface: '', fail: false, failList: false, invalidSample: undefined as unknown, mergeSample: false, metrics: {} as Record<string, unknown>, release: () => {}, liveCalls: 0 }
|
||||||
const gate = new Promise<void>(resolve => { control.release = resolve })
|
const gate = new Promise<void>(resolve => { control.release = resolve })
|
||||||
const card = { id: '1', name: 'Экспортёр тест', subtitle: '', site: 'TEST', country: 'RU', status: 'online', rxNow: 2, txNow: 3, sessions: 1, rxSeries: [1, 2], txSeries: [2, 3], bytes: 200 }
|
const card = { id: '1', name: 'Экспортёр тест', subtitle: '', site: 'TEST', country: 'RU', status: 'online', rxNow: 2, txNow: 3, sessions: 1, rxSeries: [1, 2], txSeries: [2, 3], bytes: 200 }
|
||||||
@@ -27,13 +27,18 @@ async function setup(page: Page, liveRefusals = 0) {
|
|||||||
: path === '/api/traffic/flow/exporters' ? { exporters: control.emptyExporters ? [] : [card, { ...card, id: '2', name: 'Экспортёр второй' }] }
|
: path === '/api/traffic/flow/exporters' ? { exporters: control.emptyExporters ? [] : [card, { ...card, id: '2', name: 'Экспортёр второй' }] }
|
||||||
: path === '/api/traffic/flow/clients' ? { clients: [{ ...card, id: 'client1', name: 'Клиент тест' }] }
|
: path === '/api/traffic/flow/clients' ? { clients: [{ ...card, id: 'client1', name: 'Клиент тест' }] }
|
||||||
: path === '/api/traffic/flows' ? { exportersOnline: 1, bytesPerMin: 1, uniqueSrc: 1, uniqueDst: 1, topProto: 'TCP', talkers: [], listenerBound: true }
|
: path === '/api/traffic/flows' ? { exportersOnline: 1, bytesPerMin: 1, uniqueSrc: 1, uniqueDst: 1, topProto: 'TCP', talkers: [], listenerBound: true }
|
||||||
: path === '/api/traffic/servers' ? { servers: [] }
|
: path === '/api/traffic/servers' ? { servers: unknownServer ? [{ ...card, name: 'Маршрутизатор без страны', country: '', rxPeak: null, txPeak: null, rxTotal: null, txTotal: null }] : [] }
|
||||||
: path.endsWith('/interfaces') || path.endsWith('/bound-interfaces') ? { interfaces: [] }
|
: path.endsWith('/interfaces') || path.endsWith('/bound-interfaces') ? { interfaces: [] }
|
||||||
: path === '/api/traffic/users' ? { users: [] }
|
: path === '/api/traffic/users' ? { users: [] }
|
||||||
: path === '/api/servers' ? [] : {}
|
: path === '/api/servers' ? [] : {}
|
||||||
return route.fulfill({ json })
|
return route.fulfill({ json })
|
||||||
})
|
})
|
||||||
await page.goto('/traffic')
|
await page.goto('/traffic')
|
||||||
|
if (unknownServer) {
|
||||||
|
const server = page.getByRole('button').filter({ hasText: 'Маршрутизатор без страны' })
|
||||||
|
await expect(server).toBeVisible()
|
||||||
|
await expect(server.locator('img[src$="/un.png"]')).toHaveCount(0)
|
||||||
|
}
|
||||||
await page.getByRole('button', { name: 'Потоки', exact: true }).click()
|
await page.getByRole('button', { name: 'Потоки', exact: true }).click()
|
||||||
await expect(page.getByLabel('Скорость потоков')).toBeVisible()
|
await expect(page.getByLabel('Скорость потоков')).toBeVisible()
|
||||||
return control
|
return control
|
||||||
@@ -51,6 +56,16 @@ test('Flow: начальный HTTP 429 сменяется фактически
|
|||||||
expect(control.liveCalls).toBe(2)
|
expect(control.liveCalls).toBe(2)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('Flow: переход с сервера без страны в потоки не загружает флаг UN', async ({ page }) => {
|
||||||
|
let placeholderRequests = 0
|
||||||
|
await page.route('https://flagcdn.com/**', async route => {
|
||||||
|
if (new URL(route.request().url()).pathname.endsWith('/un.png')) placeholderRequests++
|
||||||
|
await route.abort()
|
||||||
|
})
|
||||||
|
await setup(page, 0, true)
|
||||||
|
expect(placeholderRequests).toBe(0)
|
||||||
|
})
|
||||||
|
|
||||||
test('Flow: поздний ответ периода не заменяет текущую аналитику', async ({ page }) => {
|
test('Flow: поздний ответ периода не заменяет текущую аналитику', async ({ page }) => {
|
||||||
const control = await setup(page)
|
const control = await setup(page)
|
||||||
control.hold = '24h'
|
control.hold = '24h'
|
||||||
|
|||||||
Reference in new issue
Block a user