FaC: Das alte Flag von Terminen, die in die Zeiterfassung übernommen worden sind, wird ebenfalls berücksichtigt.
165 lines
6.3 KiB
JavaScript
165 lines
6.3 KiB
JavaScript
(async () => {
|
|
const puppeteer = require('puppeteer')
|
|
, browser = await puppeteer.launch({ headless: process.env.HEADLESS !== 'false' })
|
|
, { emitterify, file, keys, delay, za } = require('utilise/pure')
|
|
, { stringify } = require('cryonic')
|
|
, { Readable } = require('stream')
|
|
, { test } = require('tap')
|
|
|
|
await test('respond via return', async ({ plan, same }) => {
|
|
plan(5)
|
|
const { server, page } = await startup(req => 'ack')
|
|
|
|
same(1, server.ws.sockets.length, 'socket added')
|
|
same('ack', await page.evaluate(() => xclient.send('create')), 'response')
|
|
same(1, await page.evaluate(() => xclient.subscriptions.length), 'subscription destroyed (client)') // TODO: This should be 0 - force unsubscribe
|
|
same(0, keys(server.ws.sockets[0].subscriptions).length, 'subscription cleared (server)')
|
|
|
|
await page.close()
|
|
await Promise.race([delay(100), server.once('disconnected')])
|
|
same(server.ws.sockets.length, 0, 'socket removed')
|
|
})
|
|
|
|
await test('respond via function', async ({ plan, same }) => {
|
|
plan(3)
|
|
const { server, page } = await startup((req, res) => { res('foo'), res('bar') })
|
|
|
|
same(['foo', 'bar'], await page.evaluate(() => (collect(2, $ = xclient.send('create')))), 'response')
|
|
await page.evaluate(() => Promise.all($.source.emit('stop')))
|
|
same(0, keys(server.ws.sockets[0].subscriptions).length, 'subscription cleared (server)')
|
|
same(0, await page.evaluate(() => xclient.subscriptions.length), 'subscription destroyed (client)')
|
|
page.close()
|
|
})
|
|
|
|
await test('respond via stream', async ({ plan, same }) => {
|
|
plan(3)
|
|
const { server, page } = await startup(req => req.on('data').map(d => d * 2))
|
|
|
|
same([2, 4], await page.evaluate(() => {
|
|
const input = emitterify().on('foo').on('start', () => {
|
|
input.next(1)
|
|
input.next(2)
|
|
})
|
|
return collect(2, $ = xclient.send(input))
|
|
}), 'response')
|
|
await page.evaluate(() => Promise.all($.source.emit('stop')))
|
|
same(0, keys(server.ws.sockets[0].subscriptions).length, 'subscription cleared (server)')
|
|
same(0, await page.evaluate(() => xclient.subscriptions.length), 'subscription destroyed (client)')
|
|
page.close()
|
|
})
|
|
|
|
await test('respond to binary', { timeout: 9999 }, async ({ plan, same, ok }) => {
|
|
plan(6)
|
|
const { server, page } = await startup(req => {
|
|
same(req.data.meta, { foo: 'bar' })
|
|
ok(req.binary instanceof Readable)
|
|
same(req.chunks.join('').length, 2000)
|
|
return 'ack'
|
|
})
|
|
|
|
const results = [
|
|
{ type: 'sent' , value: { id: '1' } }
|
|
, { type: 'progress', value: { received: 1024, total: 2000 } }
|
|
, { type: 'progress', value: { received: 2000, total: 2000 } }
|
|
, { type: 'complete', value: 'ack' }
|
|
]
|
|
|
|
same((await page.evaluate(() => {
|
|
const binary = new Blob([Array(2000).fill(1).join('')])
|
|
, results = []
|
|
|
|
return $ = xclient.send(binary, { foo: 'bar' })
|
|
.on('sent', d => results.push({ type: 'sent', value: d }))
|
|
.on('progress', d => results.push({ type: 'progress', value: d }))
|
|
.map(d => results.push({ type: 'complete', value: d }))
|
|
.filter(d => results.length === 4)
|
|
.map(d => results)
|
|
})).sort(za('type')), results, 'response')
|
|
|
|
await page.evaluate(() => Promise.all($.source.emit('stop')))
|
|
same(0, keys(server.ws.sockets[0].subscriptions).length, 'subscription cleared (server)')
|
|
same(0, await page.evaluate(() => xclient.subscriptions.length), 'subscription destroyed (client)')
|
|
page.close()
|
|
})
|
|
|
|
await test('should continue subscriptions over reconnection', async ({ plan, same }) => {
|
|
plan(1)
|
|
const { server, page } = await startup({ processor: d => 'ack1', port: 7000 })
|
|
|
|
await page.evaluate(() => {
|
|
raw = xclient.send('something')
|
|
all = raw.reduce((acc = [], d) => acc.concat(d)).filter(d => d.length == 2)
|
|
return raw
|
|
})
|
|
|
|
// close first server, start another one
|
|
server.http.close()
|
|
server.ws.close()
|
|
const server2 = (await startup({ processor: d => 'ack2', port: 7000 }, 0)).server
|
|
|
|
same(['ack1', 'ack2'], await page.evaluate(() => all), 'all responses')
|
|
|
|
page.close()
|
|
})
|
|
|
|
await test('should allow response without request', async ({ plan, same }) => {
|
|
plan(1)
|
|
const exec = (o, d) => { $.next(typeof o === 'undefined' && d === 42) }
|
|
, { server, page } = await startup()
|
|
|
|
await page.evaluate(() => {
|
|
$ = emitterify().once('foo')
|
|
result = $.filter(result => result === true)
|
|
})
|
|
|
|
server.ws.sockets.map(socket => socket.send('{"data":{"exec":(o, v) => { $.next(typeof o == \'undefined\' && v === 42) },"value":42 }}'))
|
|
same(await page.evaluate(() => result), true)
|
|
|
|
page.close()
|
|
})
|
|
|
|
await test('server-side push/subscribe', async ({ plan, same }) => {
|
|
plan(2)
|
|
const { server, page } = await startup(req => 'ack')
|
|
|
|
await page.evaluate(() => { $ = xclient.once('recv') })
|
|
server.recv(server.ws.sockets[0], { detail: 'FOO' })
|
|
same('ack', await page.evaluate(() => $))
|
|
|
|
// TODO: for both client/server initatied, this should be 0 for single value, and 1 for streams
|
|
// same(0, await page.evaluate(() => xclient.subscriptions.length), 'subscription created (client)')
|
|
// same(1, keys(server.ws.sockets[0].subscriptions).length, 'subscription created (server)')
|
|
|
|
await page.close()
|
|
await Promise.race([delay(100), server.once('disconnected')])
|
|
same(server.ws.sockets.length, 0, 'socket removed')
|
|
})
|
|
|
|
process.exit(0)
|
|
|
|
async function startup(opts, pages = 1){
|
|
const server = await require('./server')(opts).once('listening')
|
|
|
|
server.express.use((req, res) => res.send(`
|
|
<script>${file(require.resolve('utilise.emitterify/client'))}</script>
|
|
<script>${file('./client.bundle.js')}</script>
|
|
<script>
|
|
collect = (count, stream) => stream
|
|
.reduce((acc = [], d) => (acc.push(d), acc))
|
|
.filter(d => d.length === count)
|
|
xclient = xrs()
|
|
</script>
|
|
`))
|
|
|
|
|
|
pages = await Promise.all(Array(pages).fill().map(async (d, i) => {
|
|
const page = await browser.newPage()
|
|
if (process.env.DEBUG == 'true')
|
|
page.on('console', (...args) => console.log(`(CLIENT ${i}):`, ...args))
|
|
await page.goto(`http://localhost:${server.port}`)
|
|
return page
|
|
}))
|
|
return { server, pages, page: pages[0] }
|
|
}
|
|
})()
|