You've already forked serverless-webpack
mirror of
https://github.com/encounter/serverless-webpack.git
synced 2026-03-30 11:37:58 -07:00
5c9f14d53f
* Make serverless-webpack more extensible Use PluginManager to make serverless-webpack more extensible Following the advice from serverless blog on Advanced Plugin Development. https://serverless.com/blog/advanced-plugin-development-extending-the-core-lifecycle/ * use sublifecycle with webpack command * Use new lifecycles and adapt unit tests * Fixed unit test after merge * Use new events everywhere * Added section to README
399 lines
13 KiB
JavaScript
399 lines
13 KiB
JavaScript
'use strict';
|
|
|
|
const BbPromise = require('bluebird');
|
|
const _ = require('lodash');
|
|
const chai = require('chai');
|
|
const path = require('path');
|
|
const sinon = require('sinon');
|
|
const mockery = require('mockery');
|
|
const Serverless = require('serverless');
|
|
|
|
// Mocks
|
|
const fsMockFactory = require('./mocks/fs.mock');
|
|
const globMockFactory = require('./mocks/glob.mock');
|
|
const archiverMockFactory = require('./mocks/archiver.mock');
|
|
|
|
chai.use(require('chai-as-promised'));
|
|
chai.use(require('sinon-chai'));
|
|
|
|
const expect = chai.expect;
|
|
|
|
describe('packageModules', () => {
|
|
let sandbox;
|
|
let baseModule;
|
|
let serverless;
|
|
let module;
|
|
|
|
// Mocks
|
|
let fsMock;
|
|
let globMock;
|
|
let archiverMock;
|
|
// Serverless stubs
|
|
let writeFileDirStub;
|
|
let getAllFunctionsStub;
|
|
let getFunctionStub;
|
|
let getServiceObjectStub;
|
|
let getVersionStub;
|
|
|
|
before(() => {
|
|
sandbox = sinon.sandbox.create();
|
|
sandbox.usingPromise(BbPromise);
|
|
|
|
fsMock = fsMockFactory.create(sandbox);
|
|
archiverMock = archiverMockFactory.create(sandbox);
|
|
globMock = globMockFactory.create(sandbox);
|
|
|
|
mockery.enable({ warnOnUnregistered: false });
|
|
mockery.registerMock('archiver', archiverMock);
|
|
mockery.registerMock('fs', fsMock);
|
|
mockery.registerMock('glob', globMock);
|
|
baseModule = require('../lib/packageModules');
|
|
Object.freeze(baseModule);
|
|
});
|
|
|
|
after(() => {
|
|
mockery.disable();
|
|
mockery.deregisterAll();
|
|
});
|
|
|
|
beforeEach(() => {
|
|
serverless = new Serverless();
|
|
serverless.cli = {
|
|
log: sandbox.stub(),
|
|
consoleLog: sandbox.stub()
|
|
};
|
|
|
|
writeFileDirStub = sandbox.stub(serverless.utils, 'writeFileDir');
|
|
getAllFunctionsStub = sandbox.stub(serverless.service, 'getAllFunctions');
|
|
getFunctionStub = sandbox.stub(serverless.service, 'getFunction');
|
|
getServiceObjectStub = sandbox.stub(serverless.service, 'getServiceObject');
|
|
getVersionStub = sandbox.stub(serverless, 'getVersion');
|
|
|
|
module = _.assign({
|
|
serverless,
|
|
options: {},
|
|
}, baseModule);
|
|
});
|
|
|
|
afterEach(() => {
|
|
// Reset all counters and restore all stubbed functions
|
|
sandbox.reset();
|
|
sandbox.restore();
|
|
});
|
|
|
|
describe('packageModules()', () => {
|
|
it('should do nothing if no compile stats are available', () => {
|
|
module.compileStats = { stats: [] };
|
|
return expect(module.packageModules()).to.be.fulfilled
|
|
.then(() => BbPromise.all([
|
|
expect(archiverMock.create).to.not.have.been.called,
|
|
expect(writeFileDirStub).to.not.have.been.called,
|
|
expect(fsMock.createWriteStream).to.not.have.been.called,
|
|
expect(globMock.sync).to.not.have.been.called
|
|
]));
|
|
});
|
|
|
|
describe('with service packaging', () => {
|
|
beforeEach(() => {
|
|
// Setup behavior for service packaging
|
|
_.unset(module, 'entryFunctions');
|
|
_.set(serverless.service, 'package.individually', false);
|
|
});
|
|
|
|
it('should package', () => {
|
|
// Test data
|
|
const stats = {
|
|
stats: [
|
|
{
|
|
compilation: {
|
|
compiler: {
|
|
outputPath: '/my/Service/Path/.webpack/service'
|
|
}
|
|
}
|
|
}
|
|
]
|
|
};
|
|
const files = [
|
|
'README.md', 'src/handler1.js', 'src/handler1.js.map', 'src/handler2.js', 'src/handler2.js.map'
|
|
];
|
|
const allFunctions = [ 'func1', 'func2' ];
|
|
const func1 = {
|
|
handler: 'src/handler1',
|
|
events: []
|
|
};
|
|
const func2 = {
|
|
handler: 'src/handler2',
|
|
events: []
|
|
};
|
|
// Serverless behavior
|
|
sandbox.stub(serverless.config, 'servicePath').value('/my/Service/Path');
|
|
getVersionStub.returns('1.18.0');
|
|
getServiceObjectStub.returns({
|
|
name: 'test-service'
|
|
});
|
|
getAllFunctionsStub.returns(allFunctions);
|
|
getFunctionStub.withArgs('func1').returns(func1);
|
|
getFunctionStub.withArgs('func2').returns(func2);
|
|
// Mock behavior
|
|
globMock.sync.returns(files);
|
|
fsMock._streamMock.on.withArgs('open').yields();
|
|
fsMock._streamMock.on.withArgs('close').yields();
|
|
fsMock._statMock.isDirectory.returns(false);
|
|
|
|
const expectedArtifactPath = path.join('.serverless', 'test-service.zip');
|
|
|
|
module.compileStats = stats;
|
|
return expect(module.packageModules()).to.be.fulfilled
|
|
.then(() => BbPromise.all([
|
|
expect(func1).to.have.a.nested.property('package.artifact').that.equals(expectedArtifactPath),
|
|
expect(func2).to.have.a.nested.property('package.artifact').that.equals(expectedArtifactPath),
|
|
]));
|
|
});
|
|
|
|
describe('with the Google provider', () => {
|
|
let oldProviderName;
|
|
|
|
beforeEach(() => {
|
|
oldProviderName = serverless.service.provider.name;
|
|
// Imitate Google provider
|
|
serverless.service.provider.name = 'google';
|
|
});
|
|
|
|
afterEach(() => {
|
|
if (oldProviderName) {
|
|
serverless.service.provider.name = oldProviderName;
|
|
} else {
|
|
_.unset(serverless.service.provider, 'name');
|
|
}
|
|
});
|
|
|
|
it('should set the service artifact path', () => {
|
|
// Test data
|
|
const stats = {
|
|
stats: [
|
|
{
|
|
compilation: {
|
|
compiler: {
|
|
outputPath: '/my/Service/Path/.webpack/service'
|
|
}
|
|
}
|
|
}
|
|
]
|
|
};
|
|
const files = [
|
|
'README.md', 'index.js'
|
|
];
|
|
const allFunctions = [ 'func1', 'func2' ];
|
|
const func1 = {
|
|
handler: 'handler1',
|
|
events: []
|
|
};
|
|
const func2 = {
|
|
handler: 'handler2',
|
|
events: []
|
|
};
|
|
sandbox.stub(serverless.config, 'servicePath').value('/my/Service/Path');
|
|
getVersionStub.returns('1.18.0');
|
|
getServiceObjectStub.returns({
|
|
name: 'test-service'
|
|
});
|
|
getAllFunctionsStub.returns(allFunctions);
|
|
getFunctionStub.withArgs('func1').returns(func1);
|
|
getFunctionStub.withArgs('func2').returns(func2);
|
|
// Mock behavior
|
|
globMock.sync.returns(files);
|
|
fsMock._streamMock.on.withArgs('open').yields();
|
|
fsMock._streamMock.on.withArgs('close').yields();
|
|
fsMock._statMock.isDirectory.returns(false);
|
|
|
|
const expectedArtifactPath = path.join('.serverless', 'test-service.zip');
|
|
|
|
module.compileStats = stats;
|
|
return expect(module.packageModules()).to.be.fulfilled
|
|
.then(() => expect(serverless.service).to.have.a.nested.property('package.artifact').that.equals(expectedArtifactPath));
|
|
});
|
|
});
|
|
|
|
it('should set the function artifact depending on the serverless version', () => {
|
|
// Test data
|
|
const stats = {
|
|
stats: [
|
|
{
|
|
compilation: {
|
|
compiler: {
|
|
outputPath: '/my/Service/Path/.webpack/service'
|
|
}
|
|
}
|
|
}
|
|
]
|
|
};
|
|
const files = [
|
|
'README.md', 'src/handler1.js', 'src/handler1.js.map', 'src/handler2.js', 'src/handler2.js.map'
|
|
];
|
|
const allFunctions = [ 'func1', 'func2' ];
|
|
const func1 = {
|
|
handler: 'src/handler1',
|
|
events: []
|
|
};
|
|
const func2 = {
|
|
handler: 'src/handler2',
|
|
events: []
|
|
};
|
|
// Serverless behavior
|
|
sandbox.stub(serverless.config, 'servicePath').value('/my/Service/Path');
|
|
getServiceObjectStub.returns({
|
|
name: 'test-service'
|
|
});
|
|
getAllFunctionsStub.returns(allFunctions);
|
|
getFunctionStub.withArgs('func1').returns(func1);
|
|
getFunctionStub.withArgs('func2').returns(func2);
|
|
// Mock behavior
|
|
globMock.sync.returns(files);
|
|
fsMock._streamMock.on.withArgs('open').yields();
|
|
fsMock._streamMock.on.withArgs('close').yields();
|
|
fsMock._statMock.isDirectory.returns(false);
|
|
|
|
const expectedArtifactPath = path.join('.serverless', 'test-service.zip');
|
|
|
|
module.compileStats = stats;
|
|
return BbPromise.each([ '1.18.1', '2.17.0', '10.15.3', ], version => {
|
|
getVersionStub.returns(version);
|
|
return expect(module.packageModules()).to.be.fulfilled
|
|
.then(() => BbPromise.all([
|
|
expect(func1).to.have.a.nested.property('package.artifact').that.equals(expectedArtifactPath),
|
|
expect(func2).to.have.a.nested.property('package.artifact').that.equals(expectedArtifactPath),
|
|
]));
|
|
})
|
|
.then(() => BbPromise.each([ '1.17.0', '1.16.0-alpha', '1.15.3', ], version => {
|
|
getVersionStub.returns(version);
|
|
return expect(module.packageModules()).to.be.fulfilled
|
|
.then(() => BbPromise.all([
|
|
expect(func1).to.have.a.nested.property('artifact').that.equals(expectedArtifactPath),
|
|
expect(func2).to.have.a.nested.property('artifact').that.equals(expectedArtifactPath),
|
|
expect(func1).to.have.a.nested.property('package.disable').that.is.true,
|
|
expect(func2).to.have.a.nested.property('package.disable').that.is.true,
|
|
]));
|
|
}));
|
|
});
|
|
|
|
it('should reject if no files are found', () => {
|
|
// Test data
|
|
const stats = {
|
|
stats: [
|
|
{
|
|
compilation: {
|
|
compiler: {
|
|
outputPath: '/my/Service/Path/.webpack/service'
|
|
}
|
|
}
|
|
}
|
|
]
|
|
};
|
|
const files = [];
|
|
const allFunctions = [ 'func1', 'func2' ];
|
|
const func1 = {
|
|
handler: 'src/handler1',
|
|
events: []
|
|
};
|
|
const func2 = {
|
|
handler: 'src/handler2',
|
|
events: []
|
|
};
|
|
// Serverless behavior
|
|
sandbox.stub(serverless.config, 'servicePath').value('/my/Service/Path');
|
|
getVersionStub.returns('1.18.0');
|
|
getServiceObjectStub.returns({
|
|
name: 'test-service'
|
|
});
|
|
getAllFunctionsStub.returns(allFunctions);
|
|
getFunctionStub.withArgs('func1').returns(func1);
|
|
getFunctionStub.withArgs('func2').returns(func2);
|
|
// Mock behavior
|
|
globMock.sync.returns(files);
|
|
fsMock._streamMock.on.withArgs('open').yields();
|
|
fsMock._streamMock.on.withArgs('close').yields();
|
|
fsMock._statMock.isDirectory.returns(false);
|
|
|
|
module.compileStats = stats;
|
|
return expect(module.packageModules()).to.be.rejectedWith('Packaging: No files found');
|
|
});
|
|
});
|
|
|
|
describe('with individual packaging', () => {
|
|
// Test data
|
|
const stats = {
|
|
stats: [
|
|
{
|
|
compilation: {
|
|
compiler: {
|
|
outputPath: '/my/Service/Path/.webpack/func1'
|
|
}
|
|
}
|
|
},
|
|
{
|
|
compilation: {
|
|
compiler: {
|
|
outputPath: '/my/Service/Path/.webpack/func2'
|
|
}
|
|
}
|
|
}
|
|
]
|
|
};
|
|
const files = [
|
|
'README.md', 'src/handler1.js', 'src/handler1.js.map', 'src/handler2.js', 'src/handler2.js.map'
|
|
];
|
|
const allFunctions = [ 'func1', 'func2' ];
|
|
const func1 = {
|
|
handler: 'src/handler1',
|
|
events: []
|
|
};
|
|
const func2 = {
|
|
handler: 'src/handler2',
|
|
events: []
|
|
};
|
|
const entryFunctions = [
|
|
{
|
|
handlerFile: 'src/handler1.js',
|
|
funcName: 'func1',
|
|
func: func1
|
|
},
|
|
{
|
|
handlerFile: 'src/handler2.js',
|
|
funcName: 'func2',
|
|
func: func2
|
|
},
|
|
];
|
|
|
|
beforeEach(() => {
|
|
// Setup sandbox and behavior for individual packaging
|
|
_.set(module, 'entryFunctions', entryFunctions);
|
|
_.set(serverless.service.package, 'individually', true);
|
|
});
|
|
|
|
it('should package', () => {
|
|
// Serverless behavior
|
|
sandbox.stub(serverless.config, 'servicePath').value('/my/Service/Path');
|
|
getVersionStub.returns('1.18.0');
|
|
getServiceObjectStub.returns({
|
|
name: 'test-service'
|
|
});
|
|
getAllFunctionsStub.returns(allFunctions);
|
|
getFunctionStub.withArgs('func1').returns(func1);
|
|
getFunctionStub.withArgs('func2').returns(func2);
|
|
// Mock behavior
|
|
globMock.sync.returns(files);
|
|
fsMock._streamMock.on.withArgs('open').yields();
|
|
fsMock._streamMock.on.withArgs('close').yields();
|
|
fsMock._statMock.isDirectory.returns(false);
|
|
|
|
module.compileStats = stats;
|
|
return expect(module.packageModules()).to.be.fulfilled
|
|
.then(() => BbPromise.all([
|
|
expect(func1).to.have.a.nested.property('package.artifact').that.equals(path.join('.serverless', 'func1.zip')),
|
|
expect(func2).to.have.a.nested.property('package.artifact').that.equals(path.join('.serverless', 'func2.zip')),
|
|
]));
|
|
});
|
|
});
|
|
});
|
|
});
|