OverviewFilesCommitsIssuesDocsReleasesPeers

cthuloid / webui / test / app.test.js

71 lines · javascript ref:
// createApp: the one entry both stortron (index.js) and the phone's worklet use.
import test from 'brittle'
import http from 'bare-http1'
import fs from 'bare-fs'
import os from 'bare-os'
import path from 'bare-path'
import EventEmitter from 'bare-events'
import { createApp } from '../lib/app.js'
import { buildAssets } from '../scripts/gen-assets.js'
import { ASSET_FILES } from '../lib/asset-files.js'

class FakeDiscovery extends EventEmitter {
  constructor () { super(); this.available = true; this.reason = '' }
  start () {}
  stop () {}
}

function get (port, p) {
  return new Promise((resolve, reject) => {
    http.request({ host: '127.0.0.1', port, path: p }, (res) => {
      const chunks = []
      res.on('data', (d) => chunks.push(d))
      res.on('end', () => resolve({ status: res.statusCode, type: res.headers['content-type'], body: Buffer.concat(chunks) }))
    }).on('error', reject).end()
  })
}

const tmp = () => path.join(os.tmpdir(), 'cthuloid-app-test-' + Date.now() + '-' + Math.random().toString(36).slice(2))

test('createApp starts, serves state, stops', async (t) => {
  const app = createApp({ configDir: tmp(), port: 0, discovery: new FakeDiscovery() })
  const { port } = await app.listen()
  const r = await get(port, '/api/state')
  t.is(r.status, 200)
  t.is(JSON.parse(r.body).connected, false)
  await app.close()
})

test('createApp works with no discovery at all (units added by hand)', async (t) => {
  const app = createApp({ configDir: tmp(), port: 0 })
  const { port } = await app.listen()
  const st = JSON.parse((await get(port, '/api/state')).body)
  t.is(st.discovery.available, true, 'no "discovery broken" banner')
  await app.close()
})

test('generated assets are exactly the files in static/', (t) => {
  const assets = buildAssets()
  const dir = path.join(path.dirname(new URL(import.meta.url).pathname), '..', 'static')
  for (const [url, [file, type]] of Object.entries(ASSET_FILES)) {
    t.is(assets[url].type, type, url + ' type')
    t.is(assets[url].body, fs.readFileSync(path.join(dir, file), 'utf8'), url + ' body')
  }
})

test('embedded assets are served byte-identical to the disk ones', async (t) => {
  const disk = createApp({ configDir: tmp(), port: 0 })
  const packed = createApp({ configDir: tmp(), port: 0, assets: buildAssets() })
  const a = (await disk.listen()).port
  const b = (await packed.listen()).port
  for (const url of Object.keys(ASSET_FILES)) {
    const x = await get(a, url)
    const y = await get(b, url)
    t.is(y.status, 200, url)
    t.is(y.type, x.type, url + ' type')
    t.ok(Buffer.compare(x.body, y.body) === 0, url + ' bytes')
  }
  await disk.close()
  await packed.close()
})