Skip to content

Instantly share code, notes, and snippets.

@sibelius
Created October 19, 2020 17:24
Show Gist options
  • Save sibelius/ffa492c5b08eb11d1d818374150a3295 to your computer and use it in GitHub Desktop.
Save sibelius/ffa492c5b08eb11d1d818374150a3295 to your computer and use it in GitHub Desktop.
Using deferred promise to test websockets
const createDeferred = () => {
let d = {};
const promise = new Promise((resolve, reject) => {
d = { resolve, reject };
});
return { ...d, promise } as {
resolve: () => void;
reject: (err: unknown) => void;
promise: Promise<void>;
};
};
await makeServer();
const d = createDeferred()
let client = new WebSocket(url);
client.onclose = (event) => {
expect(event.code).toBe(1002);
expect(event.reason).toBe('Protocol Error');
expect(event.wasClean).toBeTruthy();
d.resolve()
};
await d.promise
@gtkatakura
Copy link

another options:

await new Promise(resolve => {
  client.onclose = (event) => {
    expect(event.code).toBe(1002);
    expect(event.reason).toBe('Protocol Error');
    expect(event.wasClean).toBeTruthy();
    resolve()
  }
})
const onClose = (client: WebSocket, handle: WebSocket['onclose']) => {
  return new Promise(resolve => {
    client.onclose = function handleClose(...args) {
      handle.call(this, ...args)
      resolve()
    }
  })
}

await onClose(client, (event) => {
  expect(event.code).toBe(1002);
  expect(event.reason).toBe('Protocol Error');
  expect(event.wasClean).toBeTruthy();
})
type FunctionPropertyNames<T> = {
    [K in keyof T]: NonNullable<T[K]> extends Function ? K : never;
  }[keyof T]

const onEvent = <EventName extends FunctionPropertyNames<WebSocket>>(client: WebSocket, eventName: EventName, handle: NonNullable<WebSocket[EventName]>) => {
  return new Promise(resolve => {
    client[eventName] = function handleEvent(...args: unknown[]) {
      const result = handle.apply(this, args)

      resolve()

      return result
    }
  })
}

await onEvent(client, 'onclose', (event) => {
  expect(event.code).toBe(1002);
  expect(event.reason).toBe('Protocol Error');
  expect(event.wasClean).toBeTruthy();
})

// better infer eventName using template literal types:
// type CastEventName<T extends string> = T extends `on${infer _}` ? T : never
// type FunctionEventNames<T> = CastEventName<FunctionPropertyNames<T> & string>
// const onEvent = <EventName extends FunctionEventNames<WebSocket>>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment