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

428 lines
16 KiB
TypeScript
Raw Normal View History

import { describe, it, expect } from 'vitest';
import {
parseIwLinkOutput,
createEmptyIwLinkInfo,
WIFI_GENERATIONS,
IEEE_STANDARDS,
GENERATION_CSS_CLASSES,
getGenerationLabel,
getGenerationDescription,
getGenerationIconFilename,
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_1)).toBe(true);
expect(isKnownGeneration(WIFI_GENERATIONS.WIFI_2)).toBe(true);
expect(isKnownGeneration(WIFI_GENERATIONS.WIFI_3)).toBe(true);
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('legacy WiFi detection', () => {
describe('WiFi 2 (802.11a) - 5 GHz legacy', () => {
it('should detect WiFi 2 for 5 GHz without generation markers', () => {
const iwOutput = `Connected to aa:bb:cc:dd:ee:ff (on wlan0)
SSID: LegacyNetwork
freq: 5180
signal: -60 dBm
tx bitrate: 54.0 MBit/s
rx bitrate: 48.0 MBit/s`;
const result = parseIwLinkOutput(iwOutput);
expect(result.generation).toBe(WIFI_GENERATIONS.WIFI_2);
expect(result.standard).toBe('802.11a');
});
});
describe('WiFi 1 (802.11b) - 2.4 GHz low bitrate', () => {
it('should detect WiFi 1 for 2.4 GHz with bitrate <= 11 Mbps', () => {
const iwOutput = `Connected to aa:bb:cc:dd:ee:ff (on wlan0)
SSID: VeryOldNetwork
freq: 2437
signal: -70 dBm
tx bitrate: 11.0 MBit/s
rx bitrate: 5.5 MBit/s`;
const result = parseIwLinkOutput(iwOutput);
expect(result.generation).toBe(WIFI_GENERATIONS.WIFI_1);
expect(result.standard).toBe('802.11b');
});
it('should detect WiFi 1 for 2.4 GHz with 1 Mbps bitrate', () => {
const iwOutput = `Connected to aa:bb:cc:dd:ee:ff (on wlan0)
freq: 2412
signal: -80 dBm
tx bitrate: 1.0 MBit/s`;
const result = parseIwLinkOutput(iwOutput);
expect(result.generation).toBe(WIFI_GENERATIONS.WIFI_1);
});
});
describe('WiFi 3 (802.11g) - 2.4 GHz high bitrate', () => {
it('should detect WiFi 3 for 2.4 GHz with bitrate > 11 Mbps', () => {
const iwOutput = `Connected to aa:bb:cc:dd:ee:ff (on wlan0)
SSID: OlderNetwork
freq: 2437
signal: -55 dBm
tx bitrate: 54.0 MBit/s
rx bitrate: 36.0 MBit/s`;
const result = parseIwLinkOutput(iwOutput);
expect(result.generation).toBe(WIFI_GENERATIONS.WIFI_3);
expect(result.standard).toBe('802.11g');
});
it('should detect WiFi 3 for 2.4 GHz with 12 Mbps bitrate', () => {
const iwOutput = `Connected to aa:bb:cc:dd:ee:ff (on wlan0)
freq: 2462
signal: -65 dBm
tx bitrate: 12.0 MBit/s`;
const result = parseIwLinkOutput(iwOutput);
expect(result.generation).toBe(WIFI_GENERATIONS.WIFI_3);
});
});
describe('no legacy detection when generation already known', () => {
it('should not override WiFi 4 detection with legacy', () => {
const iwOutput = `Connected to aa:bb:cc:dd:ee:ff (on wlan0)
freq: 2437
signal: -65 dBm
tx bitrate: 72.2 MBit/s MCS 7 20MHz short GI`;
const result = parseIwLinkOutput(iwOutput);
expect(result.generation).toBe(WIFI_GENERATIONS.WIFI_4);
});
});
describe('no legacy detection without enough info', () => {
it('should remain UNKNOWN without frequency', () => {
const iwOutput = `Connected to aa:bb:cc:dd:ee:ff (on wlan0)
signal: -65 dBm
tx bitrate: 54.0 MBit/s`;
const result = parseIwLinkOutput(iwOutput);
expect(result.generation).toBe(WIFI_GENERATIONS.UNKNOWN);
});
it('should remain UNKNOWN without bitrate on 2.4 GHz', () => {
const iwOutput = `Connected to aa:bb:cc:dd:ee:ff (on wlan0)
freq: 2437
signal: -65 dBm`;
const result = parseIwLinkOutput(iwOutput);
expect(result.generation).toBe(WIFI_GENERATIONS.UNKNOWN);
});
});
});
describe('getGenerationLabel', () => {
it('should return "WiFi X" for known generations', () => {
expect(getGenerationLabel(WIFI_GENERATIONS.WIFI_1)).toBe('WiFi 1');
expect(getGenerationLabel(WIFI_GENERATIONS.WIFI_2)).toBe('WiFi 2');
expect(getGenerationLabel(WIFI_GENERATIONS.WIFI_3)).toBe('WiFi 3');
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_1)).toBe('WiFi 1 (802.11b)');
expect(getGenerationDescription(WIFI_GENERATIONS.WIFI_2)).toBe('WiFi 2 (802.11a)');
expect(getGenerationDescription(WIFI_GENERATIONS.WIFI_3)).toBe('WiFi 3 (802.11g)');
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('getGenerationIconFilename', () => {
it('should return PNG filename for WiFi 4-7', () => {
expect(getGenerationIconFilename(WIFI_GENERATIONS.WIFI_4)).toBe('wifi-4.png');
expect(getGenerationIconFilename(WIFI_GENERATIONS.WIFI_5)).toBe('wifi-5.png');
expect(getGenerationIconFilename(WIFI_GENERATIONS.WIFI_6)).toBe('wifi-6.png');
expect(getGenerationIconFilename(WIFI_GENERATIONS.WIFI_7)).toBe('wifi-7.png');
});
it('should return SVG filename for WiFi 1-3', () => {
expect(getGenerationIconFilename(WIFI_GENERATIONS.WIFI_1)).toBe('wifi-1.svg');
expect(getGenerationIconFilename(WIFI_GENERATIONS.WIFI_2)).toBe('wifi-2.svg');
expect(getGenerationIconFilename(WIFI_GENERATIONS.WIFI_3)).toBe('wifi-3.svg');
});
it('should return null for UNKNOWN', () => {
expect(getGenerationIconFilename(WIFI_GENERATIONS.UNKNOWN)).toBeNull();
});
});
describe('IEEE_STANDARDS', () => {
it('should map all generations to their IEEE standards', () => {
expect(IEEE_STANDARDS[WIFI_GENERATIONS.WIFI_1]).toBe('802.11b');
expect(IEEE_STANDARDS[WIFI_GENERATIONS.WIFI_2]).toBe('802.11a');
expect(IEEE_STANDARDS[WIFI_GENERATIONS.WIFI_3]).toBe('802.11g');
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_1]).toBe('wifi-gen-1');
expect(GENERATION_CSS_CLASSES[WIFI_GENERATIONS.WIFI_2]).toBe('wifi-gen-2');
expect(GENERATION_CSS_CLASSES[WIFI_GENERATIONS.WIFI_3]).toBe('wifi-gen-3');
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', () => {
const classes = Object.values(GENERATION_CSS_CLASSES);
expect(classes).toContain('wifi-gen-1');
expect(classes).toContain('wifi-gen-2');
expect(classes).toContain('wifi-gen-3');
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');
});
});