Skip to content
This repository was archived by the owner on Feb 25, 2024. It is now read-only.

Commit 67e24ae

Browse files
Add support for inspecting via websocket (#293)
* Add support for inspecting via websocket * Create URLSearchParams only on client side * Add changeset * Refactor inspector proxy into service config Refactor receiver ref into context * Add todo tests * Draft test for simulation machine * Combine inspecting substates and query params * Update changeset * Remove receiverRef from context * Clean up diff * Update .changeset/brave-shoes-flow.md Co-authored-by: Mateusz Burzyński <mateuszburzynski@gmail.com>
1 parent 632f950 commit 67e24ae

File tree

3 files changed

+61
-8
lines changed

3 files changed

+61
-8
lines changed

.changeset/brave-shoes-flow.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'xstate-viz-app': minor
3+
---
4+
5+
You can now inspect via WebSocket. To do that you can add the WebSocket server url as a query parameter, for example `https://stately.ai/viz?inspect&server=ws://localhost:3000`
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { interpret } from 'xstate';
2+
import { simulationMachine } from '../simulationMachine';
3+
4+
describe('simulationMachine', () => {
5+
const service = interpret(simulationMachine);
6+
afterEach(() => service.stop());
7+
8+
describe('UrlSearchParams', () => {
9+
const paramsGetSpy = jest.spyOn(URLSearchParams.prototype, 'get');
10+
const paramsHasSpy = jest.spyOn(URLSearchParams.prototype, 'has');
11+
12+
describe('with no search params', () => {
13+
it('goes to state "visualizing"', () => {
14+
paramsGetSpy.mockReturnValue(null);
15+
paramsHasSpy.mockReturnValue(false);
16+
17+
service.start();
18+
19+
expect(service.getSnapshot().matches('visualizing')).toBe(true);
20+
});
21+
});
22+
describe('with /viz?inspect', () => {
23+
it.todo('goes to state "inspecting"');
24+
it.todo('creates a window receiver');
25+
});
26+
describe('with /viz?inspect&server=ws://localhost:8080', () => {
27+
it.todo('goes to state "inspecting"');
28+
it.todo('creates a websocket receiver');
29+
});
30+
});
31+
});

src/simulationMachine.tsx

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ import {
77
SCXML,
88
} from 'xstate';
99
import { AnyEventObject, assign, interpret, send, spawn } from 'xstate';
10-
import { createWindowReceiver } from '@xstate/inspect';
10+
import {
11+
createWebSocketReceiver,
12+
createWindowReceiver,
13+
InspectReceiver,
14+
} from '@xstate/inspect';
1115

1216
import { createModel } from 'xstate/lib/model';
1317
import { devTools } from './devInterface';
@@ -77,13 +81,26 @@ export const simulationMachine = simModel.createMachine(
7781
invoke: {
7882
id: 'proxy',
7983
src: () => (sendBack, onReceive) => {
80-
const receiver = createWindowReceiver({
81-
// for some random reason the `window.top` is being rewritten to `window.self`
82-
// looks like maybe some webpack replacement plugin (or similar) plays tricks on us
83-
// this breaks the auto-detection of the correct `targetWindow` in the `createWindowReceiver`
84-
// so we pass it explicitly here
85-
targetWindow: window.opener || window.parent,
86-
});
84+
const serverUrl = new URLSearchParams(window.location.search).get(
85+
'server',
86+
);
87+
88+
let receiver: InspectReceiver;
89+
if (serverUrl) {
90+
const [protocol, ...server] = serverUrl.split('://');
91+
receiver = createWebSocketReceiver({
92+
protocol: protocol as 'ws' | 'wss',
93+
server: server.join('://'),
94+
});
95+
} else {
96+
receiver = createWindowReceiver({
97+
// for some random reason the `window.top` is being rewritten to `window.self`
98+
// looks like maybe some webpack replacement plugin (or similar) plays tricks on us
99+
// this breaks the auto-detection of the correct `targetWindow` in the `createWindowReceiver`
100+
// so we pass it explicitly here
101+
targetWindow: window.opener || window.parent,
102+
});
103+
}
87104

88105
onReceive((event) => {
89106
if (event.type === 'xstate.event') {

0 commit comments

Comments
 (0)