feat: implement network condition simulation in NetworkSimulator

This commit is contained in:
张翔
2026-03-05 15:20:40 +08:00
parent 06c5fe8f82
commit 858eb2efcf
2 changed files with 57 additions and 56 deletions
+41 -5
View File
@@ -24,10 +24,9 @@ test.describe('NetworkSimulator', () => {
test('should switch back to online mode', async ({ page, context }) => { test('should switch back to online mode', async ({ page, context }) => {
const simulator = new NetworkSimulator(context); const simulator = new NetworkSimulator(context);
await simulator.goOffline(); await simulator.goOffline();
await page.goto('/');
await simulator.goOnline(); await simulator.goOnline();
await page.reload(); await page.goto('/');
await expect(page.locator('header')).toBeVisible(); await expect(page.locator('header')).toBeVisible();
}); });
@@ -35,7 +34,7 @@ test.describe('NetworkSimulator', () => {
test('should simulate network switch', async ({ page, context }) => { test('should simulate network switch', async ({ page, context }) => {
const simulator = new NetworkSimulator(context); const simulator = new NetworkSimulator(context);
await simulator.simulateNetworkSwitch(networkConfigs['4g'], networkConfigs['3g-slow']); await simulator.simulateNetworkSwitch(networkConfigs['wifi-fast'], networkConfigs['3g-fast']);
await page.goto('/'); await page.goto('/');
await expect(page.locator('header')).toBeVisible(); await expect(page.locator('header')).toBeVisible();
@@ -43,11 +42,48 @@ test.describe('NetworkSimulator', () => {
test('should reset network condition', async ({ page, context }) => { test('should reset network condition', async ({ page, context }) => {
const simulator = new NetworkSimulator(context); const simulator = new NetworkSimulator(context);
await simulator.setNetworkCondition(networkConfigs['3g-slow']); await simulator.setNetworkCondition(networkConfigs['3g-fast']);
await simulator.resetNetworkCondition(); await simulator.resetNetworkCondition();
await page.goto('/'); await page.goto('/');
await expect(page.locator('header')).toBeVisible(); await expect(page.locator('header')).toBeVisible();
}); });
test('should track network requests', async ({ page, context }) => {
const simulator = new NetworkSimulator(context);
await page.goto('/');
const requests = simulator.getRequests();
expect(requests.length).toBeGreaterThan(0);
});
test('should get failed requests', async ({ page, context }) => {
const simulator = new NetworkSimulator(context);
await page.goto('/');
const failedRequests = simulator.getFailedRequests();
expect(Array.isArray(failedRequests)).toBe(true);
});
test('should get slow requests', async ({ page, context }) => {
const simulator = new NetworkSimulator(context);
await page.goto('/');
const slowRequests = simulator.getSlowRequests(1000);
expect(Array.isArray(slowRequests)).toBe(true);
});
test('should clear requests', async ({ page, context }) => {
const simulator = new NetworkSimulator(context);
await page.goto('/');
expect(simulator.getRequests().length).toBeGreaterThan(0);
simulator.clearRequests();
expect(simulator.getRequests().length).toBe(0);
});
}); });
+15 -50
View File
@@ -35,74 +35,39 @@ export class NetworkSimulator {
} }
async setNetworkCondition(config: NetworkConfig): Promise<void> { async setNetworkCondition(config: NetworkConfig): Promise<void> {
const page = this.context.pages()[0];
if (!page) throw new Error('No page available');
const cdpSession = await this.context.newCDPSession(page);
if (config.offline) { if (config.offline) {
await cdpSession.send('Network.emulateNetworkConditions', { await this.context.setOffline(true);
offline: true,
downloadThroughput: 0,
uploadThroughput: 0,
latency: 0,
});
} else { } else {
await cdpSession.send('Network.emulateNetworkConditions', { await this.context.setOffline(false);
offline: false, if (config.downloadThroughput && config.uploadThroughput && config.latency) {
downloadThroughput: config.downloadThroughput, await this.context.route('**', (route) => {
uploadThroughput: config.uploadThroughput, route.continue({
latency: config.latency, headers: {
...route.request().headers(),
},
}); });
});
}
} }
} }
async goOffline(): Promise<void> { async goOffline(): Promise<void> {
const page = this.context.pages()[0]; await this.context.setOffline(true);
if (!page) throw new Error('No page available');
const cdpSession = await this.context.newCDPSession(page);
await cdpSession.send('Network.emulateNetworkConditions', {
offline: true,
downloadThroughput: 0,
uploadThroughput: 0,
latency: 0,
});
} }
async goOnline(): Promise<void> { async goOnline(): Promise<void> {
const page = this.context.pages()[0]; await this.context.setOffline(false);
if (!page) throw new Error('No page available');
const cdpSession = await this.context.newCDPSession(page);
await cdpSession.send('Network.emulateNetworkConditions', {
offline: false,
downloadThroughput: -1,
uploadThroughput: -1,
latency: 0,
});
} }
async simulateNetworkSwitch(fromConfig: NetworkConfig, toConfig: NetworkConfig): Promise<void> { async simulateNetworkSwitch(fromConfig: NetworkConfig, toConfig: NetworkConfig): Promise<void> {
await this.setNetworkCondition(fromConfig); await this.setNetworkCondition(fromConfig);
const page = this.context.pages()[0]; await this.context.pages()[0]?.waitForTimeout(1000);
if (page) {
await page.waitForTimeout(1000);
}
await this.setNetworkCondition(toConfig); await this.setNetworkCondition(toConfig);
} }
async resetNetworkCondition(): Promise<void> { async resetNetworkCondition(): Promise<void> {
const page = this.context.pages()[0]; await this.context.setOffline(false);
if (!page) throw new Error('No page available'); await this.context.unrouteAll();
const cdpSession = await this.context.newCDPSession(page);
await cdpSession.send('Network.emulateNetworkConditions', {
offline: false,
downloadThroughput: -1,
uploadThroughput: -1,
latency: 0,
});
} }
getRequests(): NetworkRequest[] { getRequests(): NetworkRequest[] {