I’ve been writing some UI automation tests with Playwright and was trying to parse a SignalR event. Like so:
const imageEvent = JSON.parse(event.payload.toString()) as ImageEvent;
And I got this error:
1) tests/memealyzer.spec.ts:15:1 › Add Meme Test =================================================
webSocket.waitForEvent: Unexpected token in JSON at position 658
49 | expect(afterCardCount).toEqual(beforeCardCount + 1);
50 |
> 51 | await webSocket.waitForEvent("framereceived", (event) => {
| ^
52 | if (event.payload.indexOf("ReceiveImage") > 0) {
53 | const imageEvent = JSON.parse(event.payload.toString()) as ImageEvent;
As you can see from this screenshot:
It looks like a christmas tree is in my JSON. I assumed it was an invalid char added by my code or playwright’s code, etc.
Here’s what it looks like in the debugger:
So, I removed it like so:
const payload = event.payload.toString().replace("", ""); // Remove hidden char
Little did I know that character is a record separator! After I tweeted my code, David Fowler pointed me to this:
You want to split based on that character instead of removing it. A single websocket payload can contain multiple messages https://t.co/3sHUdjCpoB
— David Fowler 🇧🇧💉💉 (@davidfowl) September 1, 2021
Here’s the code that SignalR uses to parse and iterate through the results:
https://github.com/dotnet/aspnetcore/blob/e18394c8a933a5e03c0f5e4d614b622c2cb0a4b7/src/SignalR/clients/ts/signalr/src/TextMessageFormat.ts#L6-L22
So, instead of removing the char, I now split on it and loop through the results.
await webSocket.waitForEvent("framereceived", (event) => {
if (event.payload.indexOf("ReceiveImage") > 0) {
const imageEvents = TextMessageFormat.parse(event.payload.toString());
for (let imageEventRaw of imageEvents) {
const imageEvent = JSON.parse(imageEventRaw) as ImageEvent;
actualId = imageEvent.arguments[0].Id;
return true;
}
}
});
Jon