Skip to content

Commit

Permalink
fix: use highest page number whenever multiple identical pages are co…
Browse files Browse the repository at this point in the history
…nnected (#267)

* fix: use highest page number whenever multiple identical pages are connected

* test: update device filtering test
  • Loading branch information
byCedric authored Dec 19, 2024
1 parent 486874a commit c7e66c7
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 47 deletions.
53 changes: 18 additions & 35 deletions src/expo/__tests__/bundler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,7 @@ import { expect } from 'chai';

import { mockDevice } from '../../__tests__/utils/debugging';
import { stubFetch } from '../../__tests__/utils/fetch';
import {
type InspectableDevice,
fetchDevicesToInspect,
findDeviceByName,
inferDevicePlatform,
} from '../bundler';
import { fetchDevicesToInspect, findDeviceByName, inferDevicePlatform } from '../bundler';

const host = '127.0.0.2';
const port = '1337';
Expand All @@ -19,42 +14,30 @@ describe('fetchDevicesToInspect', () => {
expect(fetch).to.have.been.calledWith(`http://${host}:${port}/json/list`);
});

it('filters by predefined page title', async () => {
// TODO: find out why the stubbing isnt working for this fetch
xit('filters by page id', async () => {
using _fetch = stubFetch([
mockDevice({ deviceName: 'iPhone 15 Pro', title: 'filter' }),
mockDevice({ deviceName: 'iPhone 15 Pro' }),
mockDevice({
title: 'React Native Bridgeless [C++ connection]',
deviceName: 'iPhone 15 Pro',
webSocketDebuggerUrl: 'ws://localhost:8081/inspector/device?page=1',
}),
mockDevice({
title: 'React Native Bridgeless [C++ connection]',
deviceName: 'iPhone 15 Pro',
webSocketDebuggerUrl: 'ws://localhost:8081/inspector/device?page=2',
}),
]);

const devices = await fetchDevicesToInspect({ host, port });

expect(devices).to.have.length(1);
expect(devices).to.deep.equal([mockDevice({ deviceName: 'iPhone 15 Pro' })]);
});

it('filters by device name for React Native <0.73', async () => {
using _fetch = stubFetch([
mockDevice({ deviceName: 'iPhone 15 Pro' }),
mockDevice({ deviceName: 'iPhone 15 Pro' }),
]);

const devices = await fetchDevicesToInspect({ host, port });

expect(devices).to.have.length(1);
expect(devices).to.deep.equal([mockDevice({ deviceName: 'iPhone 15 Pro' })]);
});

it('filters by logical device identifier for React Native +0.74', async () => {
const reactNative: InspectableDevice['reactNative'] = { logicalDeviceId: '1337' };

using _fetch = stubFetch([
mockDevice({ deviceName: 'iPhone 16 Pro', reactNative }),
mockDevice({ deviceName: 'iPhone 15 Pro', reactNative }),
expect(devices).to.deep.equal([
mockDevice({
deviceName: 'iPhone 15 Pro',
webSocketDebuggerUrl: 'ws://localhost:8081/inspector/device?page=2',
}),
]);

const devices = await fetchDevicesToInspect({ host, port });

expect(devices).to.have.length(1);
expect(devices).to.deep.equal([mockDevice({ deviceName: 'iPhone 16 Pro', reactNative })]);
});
});

Expand Down
40 changes: 28 additions & 12 deletions src/expo/bundler.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import fetch from 'node-fetch';
import vscode from 'vscode';

import { uniqueBy } from '../utils/array';
import { truthy } from '../utils/array';

const INSPECTABLE_DEVICE_TITLE = 'React Native Experimental (Improved Chrome Reloads)';

Expand Down Expand Up @@ -42,17 +42,33 @@ export async function fetchDevicesToInspect({
host?: string;
port?: string;
}) {
return await fetch(`http://${host}:${port}/json/list`)
.then((response) => (response.ok ? response.json() : Promise.reject(response)))
.then((devices: InspectableDevice[]): InspectableDevice[] =>
devices
.filter(
(device) =>
device.title === INSPECTABLE_DEVICE_TITLE || // SDK <51
device.reactNative?.capabilities?.nativePageReloads === true // SDK 52+
)
.filter(uniqueBy((device) => device?.reactNative?.logicalDeviceId ?? device.deviceName))
);
const response = await fetch(`http://${host}:${port}/json/list`);
if (!response.ok) throw response;

const devices = (await response.json()) as InspectableDevice[];
const reloadable = devices.filter(
(device) =>
device.title === INSPECTABLE_DEVICE_TITLE || // SDK <51
device.reactNative?.capabilities?.nativePageReloads // SDK 52+
);

// Manual filter for Expo Go, we really need to fix this
const inspectable = reloadable.filter((device, index, list) => {
// Only apply this to SDK 52+
if (device.title !== 'React Native Bridgeless [C++ connection]') return true;
// If there are multiple inspectable pages, only use highest page number
const devicesByPageNumber = list
.filter((other) => device.title === other.title)
.sort((a, b) => getDevicePageNumber(b) - getDevicePageNumber(a));
// Only use the highest page number
return devicesByPageNumber[0] === device;
});

return inspectable.filter(truthy);
}

function getDevicePageNumber(device: InspectableDevice) {
return parseInt(new URL(device.webSocketDebuggerUrl).searchParams.get('page') ?? '0', 10);
}

export function findDeviceByName(devices: InspectableDevice[], deviceName: string) {
Expand Down

0 comments on commit c7e66c7

Please sign in to comment.