Files
standardnotes-app-web/packages/desktop/test/extServer.spec.ts
2022-06-07 11:52:15 -05:00

131 lines
3.6 KiB
TypeScript

import anyTest, { TestFn } from 'ava'
import { promises as fs } from 'fs'
import http from 'http'
import { AddressInfo } from 'net'
import path from 'path'
import proxyquire from 'proxyquire'
import { ensureDirectoryExists } from '../app/javascripts/Main/Utils/FileUtils'
import { initializeStrings } from '../app/javascripts/Main/strings'
import { createTmpDir } from './testUtils'
import makeFakePaths from './fakePaths'
const test = anyTest as TestFn<{
server: http.Server
host: string
}>
const tmpDir = createTmpDir(__filename)
const FakePaths = makeFakePaths(tmpDir.path)
let server: http.Server
const { createExtensionsServer, normalizeFilePath } = proxyquire('../app/javascripts/Main/ExtensionsServer', {
'./paths': {
Paths: FakePaths,
'@noCallThru': true,
},
electron: {
app: {
getPath() {
return tmpDir.path
},
},
},
http: {
createServer(...args: any) {
server = http.createServer(...args)
return server
},
},
})
const extensionsDir = path.join(tmpDir.path, 'Extensions')
initializeStrings('en')
const log = console.log
const error = console.error
test.before(async (t) => {
/** Prevent the extensions server from outputting anything */
// eslint-disable-next-line @typescript-eslint/no-empty-function
// console.log = () => {}
// eslint-disable-next-line @typescript-eslint/no-empty-function
// console.error = () => {}
await ensureDirectoryExists(extensionsDir)
await new Promise((resolve) => {
createExtensionsServer(resolve)
t.context.server = server
server.once('listening', () => {
const { address, port } = server.address() as AddressInfo
t.context.host = `http://${address}:${port}/`
resolve(null)
})
})
})
test.after((t): Promise<any> => {
/** Restore the console's functionality */
console.log = log
console.error = error
return Promise.all([tmpDir.clean(), new Promise((resolve) => t.context.server.close(resolve))])
})
test('serves the files in the Extensions directory over HTTP', (t) => {
const data = {
name: 'Boxes',
meter: {
4: 4,
},
syncopation: true,
instruments: ['Drums', 'Bass', 'Vocals', { name: 'Piano', type: 'Electric' }],
}
return fs.writeFile(path.join(extensionsDir, 'file.json'), JSON.stringify(data)).then(
() =>
new Promise((resolve) => {
let serverData = ''
http.get(t.context.host + 'Extensions/file.json').on('response', (response) => {
response
.setEncoding('utf-8')
.on('data', (chunk) => {
serverData += chunk
})
.on('end', () => {
t.deepEqual(data, JSON.parse(serverData))
resolve()
})
})
}),
)
})
test('does not serve files outside the Extensions directory', async (t) => {
await new Promise((resolve) => {
http.get(t.context.host + 'Extensions/../../../package.json').on('response', (response) => {
t.is(response.statusCode, 500)
resolve(true)
})
})
})
test('returns a 404 for files that are not present', async (t) => {
await new Promise((resolve) => {
http.get(t.context.host + 'Extensions/nothing').on('response', (response) => {
t.is(response.statusCode, 404)
resolve(true)
})
})
})
test('normalizes file paths to always point somewhere in the Extensions directory', (t) => {
t.is(normalizeFilePath('/Extensions/test/yes', '127.0.0.1'), path.join(tmpDir.path, 'Extensions', 'test', 'yes'))
t.is(
normalizeFilePath('/Extensions/../../data/outside/the/extensions/directory'),
path.join(tmpDir.path, 'Extensions', 'data', 'outside', 'the', 'extensions', 'directory'),
)
})