gnome-extension-wifi-signal.../src/wifiGeneration.test.ts

284 lines
11 KiB
TypeScript
Raw Normal View History

import { describe, it, expect } from 'vitest';
import {
parseIwLinkOutput,
createEmptyIwLinkInfo,
WIFI_GENERATIONS,
IEEE_STANDARDS,
GENERATION_CSS_CLASSES,
getGenerationLabel,
getGenerationDescription,
isKnownGeneration,
} from './wifiGeneration';
import { GUARD_INTERVALS } from './types';
describe('createEmptyIwLinkInfo', () => {
it('should create an object with all null values and UNKNOWN generation', () => {
const info = createEmptyIwLinkInfo();
expect(info.generation).toBe(WIFI_GENERATIONS.UNKNOWN);
expect(info.standard).toBeNull();
expect(info.mcs).toBeNull();
expect(info.nss).toBeNull();
expect(info.guardInterval).toBeNull();
expect(info.channelWidth).toBeNull();
expect(info.txBitrate).toBeNull();
expect(info.rxBitrate).toBeNull();
expect(info.signal).toBeNull();
expect(info.frequency).toBeNull();
expect(info.ssid).toBeNull();
expect(info.bssid).toBeNull();
});
it('should return a frozen object', () => {
const info = createEmptyIwLinkInfo();
expect(Object.isFrozen(info)).toBe(true);
});
});
describe('isKnownGeneration', () => {
it('should return true for known generations', () => {
expect(isKnownGeneration(WIFI_GENERATIONS.WIFI_4)).toBe(true);
expect(isKnownGeneration(WIFI_GENERATIONS.WIFI_5)).toBe(true);
expect(isKnownGeneration(WIFI_GENERATIONS.WIFI_6)).toBe(true);
expect(isKnownGeneration(WIFI_GENERATIONS.WIFI_7)).toBe(true);
});
it('should return false for UNKNOWN', () => {
expect(isKnownGeneration(WIFI_GENERATIONS.UNKNOWN)).toBe(false);
});
});
describe('parseIwLinkOutput', () => {
it('should return empty info for empty input', () => {
const result = parseIwLinkOutput('');
expect(result.generation).toBe(WIFI_GENERATIONS.UNKNOWN);
expect(result.ssid).toBeNull();
});
it('should return empty info for "Not connected"', () => {
const result = parseIwLinkOutput('Not connected.');
expect(result.generation).toBe(WIFI_GENERATIONS.UNKNOWN);
});
it('should return a frozen result', () => {
const result = parseIwLinkOutput('Connected to 00:00:00:00:00:00 (on wlan0)');
expect(Object.isFrozen(result)).toBe(true);
});
describe('WiFi 6 (HE) detection', () => {
it('should detect WiFi 6 from real iw output', () => {
const iwOutput = `Connected to ae:8b:a9:51:30:23 (on wlp192s0)
SSID: LaccordeonCoworking
freq: 5220.0
RX: 1533905496 bytes (1321800 packets)
TX: 220138288 bytes (525917 packets)
signal: -39 dBm
rx bitrate: 573.5 MBit/s 40MHz HE-MCS 11 HE-NSS 2 HE-GI 0 HE-DCM 0
tx bitrate: 573.5 MBit/s 40MHz HE-MCS 11 HE-NSS 2 HE-GI 0 HE-DCM 0
bss flags: short-slot-time
dtim period: 3
beacon int: 100`;
const result = parseIwLinkOutput(iwOutput);
expect(result.generation).toBe(WIFI_GENERATIONS.WIFI_6);
expect(result.standard).toBe('802.11ax');
expect(result.ssid).toBe('LaccordeonCoworking');
expect(result.bssid).toBe('ae:8b:a9:51:30:23');
expect(result.frequency).toBe(5220.0);
expect(result.signal).toBe(-39);
expect(result.mcs).toBe(11);
expect(result.nss).toBe(2);
expect(result.guardInterval).toBe(GUARD_INTERVALS.NORMAL);
expect(result.channelWidth).toBe(40);
expect(result.txBitrate).toBe(573.5);
expect(result.rxBitrate).toBe(573.5);
});
it('should parse all HE guard interval values correctly', () => {
const testCases = [
{ gi: '0', expected: GUARD_INTERVALS.NORMAL },
{ gi: '1', expected: GUARD_INTERVALS.LONG_1 },
{ gi: '2', expected: GUARD_INTERVALS.LONG_2 },
] as const;
for (const { gi, expected } of testCases) {
const iwOutput = `Connected to 00:00:00:00:00:00 (on wlan0)
tx bitrate: 100 MBit/s HE-MCS 5 HE-NSS 1 HE-GI ${gi}`;
const result = parseIwLinkOutput(iwOutput);
expect(result.guardInterval).toBe(expected);
}
});
});
describe('WiFi 5 (VHT) detection', () => {
it('should detect WiFi 5 connection', () => {
const iwOutput = `Connected to 00:11:22:33:44:55 (on wlan0)
SSID: MyNetwork
freq: 5180
signal: -55 dBm
tx bitrate: 866.7 MBit/s VHT-MCS 9 80MHz VHT-NSS 2
rx bitrate: 650.0 MBit/s VHT-MCS 7 80MHz short GI VHT-NSS 2`;
const result = parseIwLinkOutput(iwOutput);
expect(result.generation).toBe(WIFI_GENERATIONS.WIFI_5);
expect(result.standard).toBe('802.11ac');
expect(result.mcs).toBe(9);
expect(result.nss).toBe(2);
expect(result.channelWidth).toBe(80);
});
it('should detect short GI for VHT', () => {
const iwOutput = `Connected to 00:00:00:00:00:00 (on wlan0)
tx bitrate: 100 MBit/s VHT-MCS 5 20MHz short GI VHT-NSS 1`;
const result = parseIwLinkOutput(iwOutput);
expect(result.guardInterval).toBe(GUARD_INTERVALS.SHORT);
});
it('should use normal GI when short GI not present', () => {
const iwOutput = `Connected to 00:00:00:00:00:00 (on wlan0)
tx bitrate: 100 MBit/s VHT-MCS 5 20MHz VHT-NSS 1`;
const result = parseIwLinkOutput(iwOutput);
expect(result.guardInterval).toBe(GUARD_INTERVALS.NORMAL);
});
});
describe('WiFi 4 (HT) detection', () => {
it('should detect WiFi 4 connection', () => {
const iwOutput = `Connected to aa:bb:cc:dd:ee:ff (on wlan0)
SSID: OldRouter
freq: 2437
signal: -65 dBm
tx bitrate: 72.2 MBit/s MCS 7 20MHz short GI
rx bitrate: 65.0 MBit/s MCS 6 20MHz`;
const result = parseIwLinkOutput(iwOutput);
expect(result.generation).toBe(WIFI_GENERATIONS.WIFI_4);
expect(result.standard).toBe('802.11n');
expect(result.mcs).toBe(7);
expect(result.nss).toBe(1);
expect(result.channelWidth).toBe(20);
expect(result.guardInterval).toBe(GUARD_INTERVALS.SHORT);
});
it('should derive NSS from MCS index', () => {
const testCases = [
{ mcs: 0, expectedNss: 1 },
{ mcs: 7, expectedNss: 1 },
{ mcs: 8, expectedNss: 2 },
{ mcs: 15, expectedNss: 2 },
{ mcs: 16, expectedNss: 3 },
{ mcs: 23, expectedNss: 3 },
];
for (const { mcs, expectedNss } of testCases) {
const iwOutput = `Connected to 00:00:00:00:00:00 (on wlan0)
tx bitrate: 100 MBit/s MCS ${mcs} 20MHz`;
const result = parseIwLinkOutput(iwOutput);
expect(result.nss).toBe(expectedNss);
}
});
});
describe('WiFi 7 (EHT) detection', () => {
it('should detect WiFi 7 connection', () => {
const iwOutput = `Connected to 11:22:33:44:55:66 (on wlan0)
SSID: WiFi7Network
freq: 6115
signal: -45 dBm
tx bitrate: 2882.4 MBit/s 160MHz EHT-MCS 13 EHT-NSS 2 EHT-GI 0
rx bitrate: 2882.4 MBit/s 160MHz EHT-MCS 13 EHT-NSS 2 EHT-GI 0`;
const result = parseIwLinkOutput(iwOutput);
expect(result.generation).toBe(WIFI_GENERATIONS.WIFI_7);
expect(result.standard).toBe('802.11be');
expect(result.mcs).toBe(13);
expect(result.nss).toBe(2);
expect(result.channelWidth).toBe(160);
});
});
describe('fallback to RX bitrate', () => {
it('should use RX bitrate when TX has no generation info', () => {
const iwOutput = `Connected to 00:00:00:00:00:00 (on wlan0)
tx bitrate: 100 MBit/s
rx bitrate: 200 MBit/s HE-MCS 9 HE-NSS 2 HE-GI 1 40MHz`;
const result = parseIwLinkOutput(iwOutput);
expect(result.generation).toBe(WIFI_GENERATIONS.WIFI_6);
expect(result.txBitrate).toBe(100);
expect(result.rxBitrate).toBe(200);
});
});
});
describe('getGenerationLabel', () => {
it('should return "WiFi X" for known generations', () => {
expect(getGenerationLabel(WIFI_GENERATIONS.WIFI_4)).toBe('WiFi 4');
expect(getGenerationLabel(WIFI_GENERATIONS.WIFI_5)).toBe('WiFi 5');
expect(getGenerationLabel(WIFI_GENERATIONS.WIFI_6)).toBe('WiFi 6');
expect(getGenerationLabel(WIFI_GENERATIONS.WIFI_7)).toBe('WiFi 7');
});
it('should return "WiFi" for UNKNOWN', () => {
expect(getGenerationLabel(WIFI_GENERATIONS.UNKNOWN)).toBe('WiFi');
});
});
describe('getGenerationDescription', () => {
it('should return full description with IEEE standard', () => {
expect(getGenerationDescription(WIFI_GENERATIONS.WIFI_4)).toBe('WiFi 4 (802.11n)');
expect(getGenerationDescription(WIFI_GENERATIONS.WIFI_5)).toBe('WiFi 5 (802.11ac)');
expect(getGenerationDescription(WIFI_GENERATIONS.WIFI_6)).toBe('WiFi 6 (802.11ax)');
expect(getGenerationDescription(WIFI_GENERATIONS.WIFI_7)).toBe('WiFi 7 (802.11be)');
});
it('should return "WiFi" for UNKNOWN', () => {
expect(getGenerationDescription(WIFI_GENERATIONS.UNKNOWN)).toBe('WiFi');
});
});
describe('IEEE_STANDARDS', () => {
it('should map all generations to their IEEE standards', () => {
expect(IEEE_STANDARDS[WIFI_GENERATIONS.WIFI_4]).toBe('802.11n');
expect(IEEE_STANDARDS[WIFI_GENERATIONS.WIFI_5]).toBe('802.11ac');
expect(IEEE_STANDARDS[WIFI_GENERATIONS.WIFI_6]).toBe('802.11ax');
expect(IEEE_STANDARDS[WIFI_GENERATIONS.WIFI_7]).toBe('802.11be');
expect(IEEE_STANDARDS[WIFI_GENERATIONS.UNKNOWN]).toBe('Unknown');
});
});
describe('GENERATION_CSS_CLASSES', () => {
it('should map all generations to CSS classes', () => {
expect(GENERATION_CSS_CLASSES[WIFI_GENERATIONS.WIFI_4]).toBe('wifi-gen-4');
expect(GENERATION_CSS_CLASSES[WIFI_GENERATIONS.WIFI_5]).toBe('wifi-gen-5');
expect(GENERATION_CSS_CLASSES[WIFI_GENERATIONS.WIFI_6]).toBe('wifi-gen-6');
expect(GENERATION_CSS_CLASSES[WIFI_GENERATIONS.WIFI_7]).toBe('wifi-gen-7');
expect(GENERATION_CSS_CLASSES[WIFI_GENERATIONS.UNKNOWN]).toBe('wifi-disconnected');
});
it('should use template literal type pattern', () => {
// Type check: all values should match the GenerationCssClass type
const classes = Object.values(GENERATION_CSS_CLASSES);
expect(classes).toContain('wifi-gen-4');
expect(classes).toContain('wifi-gen-5');
expect(classes).toContain('wifi-gen-6');
expect(classes).toContain('wifi-gen-7');
expect(classes).toContain('wifi-disconnected');
});
});