You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
214 lines
4.9 KiB
214 lines
4.9 KiB
'use strict'
|
|
|
|
const fs = require('fs')
|
|
const path = require('path')
|
|
const t = require('tap')
|
|
const fastify = require('fastify')
|
|
const sanitize = require('sanitize-filename')
|
|
|
|
const { StandaloneSerializer: FjsStandaloneCompiler } = require('../')
|
|
|
|
function generateFileName (routeOpts) {
|
|
return `/fjs-generated-${sanitize(routeOpts.schema.$id)}-${routeOpts.method}-${routeOpts.httpPart}-${sanitize(routeOpts.url)}.js`
|
|
}
|
|
|
|
t.test('errors', t => {
|
|
t.plan(2)
|
|
t.throws(() => {
|
|
FjsStandaloneCompiler()
|
|
}, 'missing restoreFunction')
|
|
t.throws(() => {
|
|
FjsStandaloneCompiler({ readMode: false })
|
|
}, 'missing storeFunction')
|
|
})
|
|
|
|
t.test('generate standalone code', t => {
|
|
t.plan(5)
|
|
|
|
const base = {
|
|
$id: 'urn:schema:base',
|
|
definitions: {
|
|
hello: { type: 'string' }
|
|
},
|
|
type: 'object',
|
|
properties: {
|
|
hello: { $ref: '#/definitions/hello' }
|
|
}
|
|
}
|
|
|
|
const refSchema = {
|
|
$id: 'urn:schema:ref',
|
|
type: 'object',
|
|
properties: {
|
|
hello: { $ref: 'urn:schema:base#/definitions/hello' }
|
|
}
|
|
}
|
|
|
|
const endpointSchema = {
|
|
schema: {
|
|
$id: 'urn:schema:endpoint',
|
|
$ref: 'urn:schema:ref'
|
|
}
|
|
}
|
|
|
|
const schemaMap = {
|
|
[base.$id]: base,
|
|
[refSchema.$id]: refSchema
|
|
}
|
|
|
|
const factory = FjsStandaloneCompiler({
|
|
readMode: false,
|
|
storeFunction (routeOpts, schemaSerializerCode) {
|
|
t.same(routeOpts, endpointSchema)
|
|
t.type(schemaSerializerCode, 'string')
|
|
fs.writeFileSync(path.join(__dirname, '/fjs-generated.js'), schemaSerializerCode)
|
|
t.pass('stored the serializer function')
|
|
}
|
|
})
|
|
|
|
const compiler = factory(schemaMap)
|
|
compiler(endpointSchema)
|
|
t.pass('compiled the endpoint schema')
|
|
|
|
t.test('usage standalone code', t => {
|
|
t.plan(3)
|
|
const standaloneSerializer = require('./fjs-generated')
|
|
t.ok(standaloneSerializer)
|
|
|
|
const valid = standaloneSerializer({ hello: 'world' })
|
|
t.same(valid, JSON.stringify({ hello: 'world' }))
|
|
|
|
const invalid = standaloneSerializer({ hello: [] })
|
|
t.same(invalid, '{"hello":""}')
|
|
})
|
|
})
|
|
|
|
t.test('fastify integration - writeMode', async t => {
|
|
t.plan(4)
|
|
|
|
const factory = FjsStandaloneCompiler({
|
|
readMode: false,
|
|
storeFunction (routeOpts, schemaSerializationCode) {
|
|
const fileName = generateFileName(routeOpts)
|
|
t.ok(routeOpts)
|
|
fs.writeFileSync(path.join(__dirname, fileName), schemaSerializationCode)
|
|
t.pass(`stored the serializer function ${fileName}`)
|
|
},
|
|
restoreFunction () {
|
|
t.fail('write mode ON')
|
|
}
|
|
})
|
|
|
|
const app = buildApp(factory)
|
|
await app.ready()
|
|
})
|
|
|
|
t.test('fastify integration - writeMode forces standalone', async t => {
|
|
t.plan(4)
|
|
|
|
const factory = FjsStandaloneCompiler({
|
|
readMode: false,
|
|
storeFunction (routeOpts, schemaSerializationCode) {
|
|
const fileName = generateFileName(routeOpts)
|
|
t.ok(routeOpts)
|
|
fs.writeFileSync(path.join(__dirname, fileName), schemaSerializationCode)
|
|
t.pass(`stored the serializer function ${fileName}`)
|
|
},
|
|
restoreFunction () {
|
|
t.fail('write mode ON')
|
|
}
|
|
})
|
|
|
|
const app = buildApp(factory, {
|
|
mode: 'not-standalone',
|
|
rounding: 'ceil'
|
|
})
|
|
|
|
await app.ready()
|
|
})
|
|
|
|
t.test('fastify integration - readMode', async t => {
|
|
t.plan(6)
|
|
|
|
const factory = FjsStandaloneCompiler({
|
|
readMode: true,
|
|
storeFunction () {
|
|
t.fail('read mode ON')
|
|
},
|
|
restoreFunction (routeOpts) {
|
|
const fileName = generateFileName(routeOpts)
|
|
t.pass(`restore the serializer function ${fileName}}`)
|
|
return require(path.join(__dirname, fileName))
|
|
}
|
|
})
|
|
|
|
const app = buildApp(factory)
|
|
await app.ready()
|
|
|
|
let res = await app.inject({
|
|
url: '/foo',
|
|
method: 'POST'
|
|
})
|
|
t.equal(res.statusCode, 200)
|
|
t.equal(res.payload, JSON.stringify({ hello: 'world' }))
|
|
|
|
res = await app.inject({
|
|
url: '/bar?lang=it',
|
|
method: 'GET'
|
|
})
|
|
t.equal(res.statusCode, 200)
|
|
t.equal(res.payload, JSON.stringify({ lang: 'en' }))
|
|
})
|
|
|
|
function buildApp (factory, serializerOpts) {
|
|
const app = fastify({
|
|
exposeHeadRoutes: false,
|
|
jsonShorthand: false,
|
|
schemaController: {
|
|
compilersFactory: {
|
|
buildSerializer: factory
|
|
}
|
|
},
|
|
serializerOpts
|
|
})
|
|
|
|
app.addSchema({
|
|
$id: 'urn:schema:foo',
|
|
type: 'object',
|
|
properties: {
|
|
name: { type: 'string' },
|
|
id: { type: 'integer' }
|
|
}
|
|
})
|
|
|
|
app.post('/foo', {
|
|
schema: {
|
|
response: {
|
|
200: {
|
|
$id: 'urn:schema:response',
|
|
type: 'object',
|
|
properties: {
|
|
hello: { $ref: 'urn:schema:foo#/properties/name' }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}, () => { return { hello: 'world' } })
|
|
|
|
app.get('/bar', {
|
|
schema: {
|
|
response: {
|
|
200: {
|
|
$id: 'urn:schema:response:bar',
|
|
type: 'object',
|
|
properties: {
|
|
lang: { type: 'string', enum: ['it', 'en'] }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}, () => { return { lang: 'en' } })
|
|
|
|
return app
|
|
}
|