Skip to content

Commit

Permalink
feature: improve error handling when starting server fails (#261)
Browse files Browse the repository at this point in the history
* feature: improve error handling when starting server fails

* update code

* feature: add getFirstEvent function

* lint

* lint

* fix

* fix

* test

* test

* test

* lint

* lint
  • Loading branch information
levivilet authored Dec 27, 2024
1 parent 7b69383 commit fb4d123
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import type { WebViewServer } from '../WebViewServerTypes/WebViewServerTypes.ts'
import * as GetFirstEvent from '../GetFirstEvent/GetFirstEvent.ts'

export const waitForServerToBeReady = async (server: WebViewServer, port: string): Promise<void> => {
const { resolve, promise } = Promise.withResolvers<void>()
server.listen(port, resolve)
await promise
const responsePromise = GetFirstEvent.getFirstEvent(server as any, {
error: 1,
listening: 2,
})
server.listen(port, () => {})
const { type, event } = await responsePromise
if (type === 1) {
throw new Error(`Server error: ${event}`)
}
}
53 changes: 43 additions & 10 deletions packages/preview-process/test/WaitForServerToBeReady.test.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,49 @@
import { expect, jest, test } from '@jest/globals'
import { expect, test } from '@jest/globals'
import { EventEmitter } from 'node:events'
import type { WebViewServer } from '../src/parts/WebViewServerTypes/WebViewServerTypes.ts'
import * as WaitForServerToBeReady from '../src/parts/WaitForServerToBeReady/WaitForServerToBeReady.ts'

test('waitForServerToBeReady', async () => {
const mockServer = {
listen: jest.fn((port, callback) => {
// @ts-ignore
class MockServer extends EventEmitter implements WebViewServer {
handler = undefined
listening = false

setHandler(handler: any): void {
this.handler = handler
}

listen(port: string, callback: () => void): void {
process.nextTick(() => {
this.listening = true
this.emit('listening')
callback()
}),
})
}
isListening(): boolean {
return this.listening
}
}

test('waitForServerToBeReady - success', async () => {
const server = new MockServer()
const port = '3000'
await WaitForServerToBeReady.waitForServerToBeReady(server, port)
expect(server.listening).toBe(true)
})

test('waitForServerToBeReady - handles EADDRINUSE error', async () => {
const server = new MockServer()
const port = '3000'
process.nextTick(() => {
server.emit('error', new Error('EADDRINUSE'))
})
await expect(WaitForServerToBeReady.waitForServerToBeReady(server, port)).rejects.toThrow('EADDRINUSE')
})

test('waitForServerToBeReady - handles other errors', async () => {
const server = new MockServer()
const port = '3000'
// @ts-ignore
await WaitForServerToBeReady.waitForServerToBeReady(mockServer, port)
expect(mockServer.listen).toHaveBeenCalledTimes(1)
expect(mockServer.listen).toHaveBeenCalledWith(port, expect.any(Function))
process.nextTick(() => {
server.emit('error', new Error('Some other error'))
})
await expect(WaitForServerToBeReady.waitForServerToBeReady(server, port)).rejects.toThrow('Some other error')
})
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { expect, test } from '@jest/globals'
import getPort from 'get-port'
import { createPreviewProcess } from '../src/parts/CreatePreviewProcess/CreatePreviewProcess.js'

test.skip('preview process - handles port already in use', async () => {
test('preview process - handles port already in use', async () => {
const previewProcess1 = createPreviewProcess()
const previewProcess2 = createPreviewProcess()
const id1 = 1
Expand All @@ -13,9 +13,8 @@ test.skip('preview process - handles port already in use', async () => {
await previewProcess1.invoke('WebViewServer.start', id1, port)

await previewProcess2.invoke('WebViewServer.create', id2)
// TODO improve error message
await expect(previewProcess2.invoke('WebViewServer.start', id2, port)).rejects.toThrow(
"Failed to start webview server: TypeError: Cannot read properties of undefined (reading 'server')",
`Failed to start webview server: Server error: Error: listen EADDRINUSE: address already in use :::${port}`,
)

previewProcess1[Symbol.dispose]()
Expand Down

0 comments on commit fb4d123

Please sign in to comment.