test-openapi
Version:
Automated client requests
123 lines (102 loc) • 3.06 kB
JavaScript
const { addErrorHandler, TestOpenApiError, BugError } = require('../errors')
const { checkSchema } = require('../validation')
// A module is either a plugin or a reporter
const getModule = function(name, info) {
// Can pass the module object directly
if (typeof name !== 'string') {
return name
}
const moduleObj = eLoadModule({ name, info })
validateModule({ moduleObj, info })
return moduleObj
}
// Load module
// TODO: `require(`${modulePrefix}${name}`)` instead
// Can only done once we moved core plugins/reporters to separate repositories
const loadModule = function({ name, info: { corePath } }) {
// eslint-disable-next-line import/no-dynamic-require
const moduleObj = require(`${corePath}${name}`)
return { ...moduleObj, name }
}
const loadModuleHandler = function(
{ code, message },
{ name, info, info: { title } },
) {
checkModuleNotFound({ code, name, info })
const props = getProps({ info, name })
throw new BugError(
`The ${title} '${name}' could not be loaded: ${message}`,
props,
)
}
// Error when loading a plugin that is not installed.
// This will also be triggered when loading a plugin that tries to `require()`
// a non-existing file. Unfortunately we cannot distinguish without parsing
// `error.message` which is brittle.
const checkModuleNotFound = function({
code,
name,
info,
info: { title, modulePrefix },
}) {
if (code !== 'MODULE_NOT_FOUND') {
return
}
const props = getProps({ info, name, addModule: false })
throw new TestOpenApiError(
`The ${title} '${name}' is used in the configuration but is not installed. Please run 'npm install ${modulePrefix}${name}.`,
props,
)
}
const eLoadModule = addErrorHandler(loadModule, loadModuleHandler)
// Validate export value
const validateModule = function({
moduleObj,
moduleObj: { name },
info,
info: { title, schema },
}) {
const schemaA = addNameSchema({ schema })
const props = getProps({ info, name })
checkSchema({
schema: schemaA,
value: moduleObj,
valueProp: title,
message: `the ${title} '${name}' is invalid`,
props,
bug: true,
})
}
// We restrict module names to make sure they can appear in dot notations
// in `error.property` without escaping.
// And also to make sure they are simple to read and write.
const addNameSchema = function({ schema, schema: { properties } }) {
return { ...schema, properties: { ...properties, name: NAME_SCHEMA } }
}
const NAME_SCHEMA = {
type: 'string',
pattern: '^[a-zA-Z_$][\\w_$-]*$',
}
// Retrieve error.* properties
const getProps = function({
info: { props: getErrorProps, title },
name,
addModule = true,
}) {
const props = getModuleProp({ title, name, addModule })
if (getErrorProps === undefined) {
return props
}
const propsA = getErrorProps({ name })
return { ...props, ...propsA }
}
const getModuleProp = function({ title, name, addModule }) {
if (!addModule) {
return
}
return { module: `${title}-${name}` }
}
module.exports = {
getModule,
}