2024-05-29 11:51:04 -04:00

392 lines
12 KiB
JavaScript

'use strict'
const chai = require('chai')
const runServerless = require('../../../../utils/run-serverless')
const {
getConfigurationValidationResult,
} = require('../../../../../lib/classes/config-schema-handler')
chai.use(require('chai-as-promised'))
const expect = chai.expect
const FUNCTION_NAME_PATTERN = '^[a-zA-Z0-9-_]+$'
describe('test/unit/lib/classes/ConfigSchemaHandler/index.test.js', () => {
describe('#constructor', () => {
it('should freeze parts of schema for service', async () => {
return runServerless({
fixture: 'config-schema-extensions',
command: 'info',
}).then((serverless) => {
expect(() => {
serverless.configSchemaHandler.schema.properties.service.name =
'changed'
}).to.throw(Error)
})
})
it('should freeze parts of schema for plugins', async () => {
return runServerless({
fixture: 'config-schema-extensions',
command: 'info',
}).then((serverless) => {
expect(() => {
serverless.configSchemaHandler.schema.properties.plugins.properties =
'changed'
}).to.throw(Error)
})
})
it('should freeze parts of schema for resources', async () => {
return runServerless({
fixture: 'config-schema-extensions',
command: 'info',
}).then((serverless) => {
expect(() => {
serverless.configSchemaHandler.schema.properties.resources.something =
'changed'
}).to.throw(Error)
})
})
it('should freeze parts of schema for package', async () => {
return runServerless({
fixture: 'config-schema-extensions',
command: 'info',
}).then((serverless) => {
expect(() => {
serverless.configSchemaHandler.schema.properties.package.properties.oneMore =
{
type: 'string',
}
}).to.throw(Error)
})
})
it('should freeze parts of schema for layers', async () => {
return runServerless({
fixture: 'config-schema-extensions',
command: 'info',
}).then((serverless) => {
expect(() => {
serverless.configSchemaHandler.schema.properties.layers.properties =
'changed'
}).to.throw(Error)
})
})
})
describe('#validateConfig', () => {
it('should run without errors for valid config', async () => {
const { serverless } = await runServerless({
fixture: 'config-schema-extensions',
command: 'info',
})
expect(getConfigurationValidationResult(serverless.configurationInput)).to
.be.true
})
})
describe('#defineFunctionEvent', () => {
it('should extend schema with defineFunctionEvent method', async () => {
return runServerless({
fixture: 'config-schema-extensions',
command: 'info',
}).then((serverless) => {
const expectedPieceOfSchema = {
type: 'object',
properties: {
someEvent: {
type: 'object',
properties: {
someRequiredStringProp: { type: 'string' },
someNumberProp: { type: 'number' },
},
required: ['someRequiredStringProp'],
additionalProperties: false,
},
},
required: ['someEvent'],
additionalProperties: false,
}
expect(
serverless.serverless.configSchemaHandler.schema.properties.functions.patternProperties[
FUNCTION_NAME_PATTERN
].properties.events.items.anyOf.find(
(definition) => definition.required[0] === 'someEvent',
),
).to.deep.equal(expectedPieceOfSchema)
return
})
})
it('should throw when defineFunctionEvent is used with an already defined event', async () => {
await expect(
runServerless({
fixture: 'config-schema-extensions-error',
command: 'info',
configExt: {
plugins: ['./test-plugin-with-colliding-function-event'],
},
}),
).to.eventually.be.rejected.and.have.property('code', 'SCHEMA_COLLISION')
})
})
describe('#defineFunctionEventProperties', () => {
it('should extend schema with defineFunctionEventProperties method', async () => {
const serverless = await runServerless({
fixture: 'config-schema-extensions',
command: 'info',
})
const existingEventDefinition =
serverless.serverless.configSchemaHandler.schema.properties.functions.patternProperties[
FUNCTION_NAME_PATTERN
].properties.events.items.anyOf.find(
(definition) => definition.required[0] === 'existingEvent',
).properties.existingEvent
expect(existingEventDefinition.properties).to.have.deep.property(
'somePluginAdditionalEventProp',
{
type: 'string',
},
)
expect(existingEventDefinition.required).to.include(
'somePluginAdditionalEventProp',
)
})
it('should extend schema with defineFunctionEventProperties method on complex event schema', async () => {
const serverless = await runServerless({
fixture: 'config-schema-extensions',
command: 'info',
})
const existingEventDefinition =
serverless.serverless.configSchemaHandler.schema.properties.functions.patternProperties[
FUNCTION_NAME_PATTERN
].properties.events.items.anyOf.find(
(definition) => definition.required[0] === 'existingComplexEvent',
).properties.existingComplexEvent
expect(existingEventDefinition).to.deep.equal({
anyOf: [
{ type: 'string' },
{
type: 'object',
properties: {
existingPropForObjectEventDefinition: { type: 'string' },
somePluginAdditionalComplexEventProp: { type: 'string' },
},
required: ['somePluginAdditionalComplexEventProp'],
},
],
})
})
it('should throw when defineFunctionEventProperties is used on non existing event name', async () => {
await expect(
runServerless({
fixture: 'config-schema-extensions-error',
command: 'info',
configExt: {
plugins: ['./test-plugin-with-non-existing-event-error'],
},
}),
).to.eventually.be.rejected.and.have.property(
'code',
'UNRECOGNIZED_FUNCTION_EVENT_SCHEMA',
)
})
it('should throw when defineFunctionEventProperties is used on event without object definition', async () => {
await expect(
runServerless({
fixture: 'config-schema-extensions-error',
command: 'info',
configExt: {
plugins: [
'./test-plugin-with-complex-event-without-object-definition',
],
},
}),
).to.eventually.be.rejected.and.have.property(
'code',
'FUNCTION_EVENT_SCHEMA_NOT_OBJECT',
)
})
it('should throw when defineFunctionEventProperties is used with an already defined property', async () => {
await expect(
runServerless({
fixture: 'config-schema-extensions-error',
command: 'info',
configExt: {
plugins: ['./test-plugin-with-colliding-function-event-property'],
},
}),
).to.eventually.be.rejected.and.have.property('code', 'SCHEMA_COLLISION')
})
})
describe('#defineFunctionProperties', () => {
it('should extend schema with defineFunctionProperties method', async () => {
return runServerless({
fixture: 'config-schema-extensions',
command: 'info',
}).then((serverless) => {
const actualFunctionProperties =
serverless.serverless.configSchemaHandler.schema.properties.functions
.patternProperties[FUNCTION_NAME_PATTERN].properties
expect(actualFunctionProperties).to.have.deep.property(
'someFunctionStringProp',
{
type: 'string',
},
)
expect(actualFunctionProperties).to.have.deep.property(
'someRequiredFunctionNumberProp',
{
type: 'number',
},
)
return
})
})
it('should throw when defineFunctionProperties is used with an already defined property', async () => {
await expect(
runServerless({
fixture: 'config-schema-extensions-error',
command: 'info',
configExt: {
plugins: ['./test-plugin-with-colliding-function-property'],
},
}),
).to.eventually.be.rejected.and.have.property('code', 'SCHEMA_COLLISION')
})
})
describe('#defineCustomProperties', () => {
it('should extend schema with defineCustomProperties method', async () => {
return runServerless({
fixture: 'config-schema-extensions',
command: 'info',
}).then((serverless) => {
const someCustomStringProp = {
type: 'string',
}
expect(
serverless.serverless.configSchemaHandler.schema.properties.custom
.properties.someCustomStringProp,
).to.deep.equal(someCustomStringProp)
return
})
})
it('should throw when defineCustomProperties is used with an already defined property', async () => {
await expect(
runServerless({
fixture: 'config-schema-extensions-error',
command: 'info',
configExt: {
plugins: ['./test-plugin-with-colliding-custom-property'],
},
}),
).to.eventually.be.rejected.and.have.property('code', 'SCHEMA_COLLISION')
})
})
describe('#defineTopLevelProperty', () => {
it('should extend schema with defineTopLevelProperty method', async () => {
return runServerless({
fixture: 'config-schema-extensions',
command: 'info',
}).then((serverless) => {
const expectedAppPropSchema = {
type: 'string',
}
expect(
serverless.serverless.configSchemaHandler.schema.properties.top,
).to.deep.equal(expectedAppPropSchema)
return
})
})
it('should throw when defineTopLevelProperty is used with an already defined property', async () => {
await expect(
runServerless({
fixture: 'config-schema-extensions-error',
command: 'info',
configExt: {
plugins: ['./test-plugin-with-colliding-top-level-property'],
},
}),
).to.eventually.be.rejected.and.have.property('code', 'SCHEMA_COLLISION')
})
})
describe('#defineProvider', () => {
it('should extend schema with defineProvider method', async () => {
return runServerless({
fixture: 'config-schema-extensions',
command: 'info',
}).then((serverless) => {
const providerPieceOfSchema = {
type: 'object',
properties: {
name: { const: 'someProvider' },
stage: { type: 'string' },
},
required: ['name'],
additionalProperties: false,
}
expect(
serverless.serverless.configSchemaHandler.schema.properties.provider,
).to.deep.equal(providerPieceOfSchema)
const expectedHandlerPieceOfSchema = { type: 'string' }
expect(
serverless.serverless.configSchemaHandler.schema.properties.functions
.patternProperties[FUNCTION_NAME_PATTERN].properties.handler,
).to.deep.equal(expectedHandlerPieceOfSchema)
return
})
})
it('should throw when defineProvider is used with an already defined property in provider', async () => {
await expect(
runServerless({
fixture: 'config-schema-extensions-error',
command: 'info',
configExt: {
plugins: [
'./test-plugin-with-colliding-provider-property-in-provider',
],
},
}),
).to.eventually.be.rejected.and.have.property('code', 'SCHEMA_COLLISION')
})
it('should throw when defineProvider is used with an already defined property in function', async () => {
await expect(
runServerless({
fixture: 'config-schema-extensions-error',
command: 'info',
configExt: {
plugins: [
'./test-plugin-with-colliding-provider-property-in-function',
],
},
}),
).to.eventually.be.rejected.and.have.property('code', 'SCHEMA_COLLISION')
})
})
})