325 lines
10 KiB
JavaScript

'use strict';
const expect = require('chai').expect;
const fs = require('fs');
const os = require('os');
const path = require('path');
const JsZip = require('jszip');
const _ = require('lodash');
const Package = require('../index');
const Serverless = require('../../../../lib/Serverless');
const testUtils = require('../../../../tests/utils');
describe('#zipService()', () => {
let serverless;
let packageService;
let zip;
let servicePath;
const testDirectory = {
// root
'.': {
'event.json': 'some content',
'handler.js': 'some content',
'file-1': 'some content',
'file-2': 'some content',
},
// bin
bin: {
'binary-777': {
content: 'some content',
permissions: 777,
},
'binary-444': {
content: 'some content',
permissions: 444,
},
},
// lib
lib: {
'file-1.js': 'some content',
},
'lib/directory-1': {
'file-1.js': 'some content',
},
// node_modules
'node_modules/directory-1': {
'file-1': 'some content',
'file-2': 'some content',
},
'node_modules/directory-2': {
'file-1': 'some content',
'file-2': 'some content',
},
};
function getTestArtifactFileName(testName) {
return `test-${testName}-${(new Date()).getTime().toString()}.zip`;
}
beforeEach(() => {
serverless = new Serverless();
zip = new JsZip();
packageService = new Package(serverless);
packageService.serverless.cli = new serverless.classes.CLI();
// create a mock service in a temporary directory
const tmpDirPath = testUtils.getTmpDirPath();
Object.keys(testDirectory).forEach(dirName => {
const dirPath = path.join(tmpDirPath, dirName);
const files = testDirectory[dirName];
Object.keys(files).forEach(fileName => {
const filePath = path.join(dirPath, fileName);
const fileValue = files[fileName];
const file = _.isObject(fileValue) ? fileValue : { content: fileValue };
if (!file.content) {
throw new Error('File content is required');
}
serverless.utils.writeFileSync(filePath, file.content);
if (file.permissions) {
fs.chmodSync(filePath, file.permissions);
}
});
});
// set the service name
serverless.service.service = 'first-service';
// set the servicePath
servicePath = tmpDirPath;
});
it('should zip a whole service (without include / exclude usage)', () => {
const exclude = [];
const include = [];
const zipFileName = getTestArtifactFileName('whole-service');
return packageService
.zipDirectory(servicePath, exclude, include, zipFileName).then((artifact) => {
const data = fs.readFileSync(artifact);
return zip.loadAsync(data);
}).then(unzippedData => {
const unzippedFileData = unzippedData.files;
expect(Object.keys(unzippedFileData)
.filter(file => !unzippedFileData[file].dir).length).to.equal(13);
// root directory
expect(unzippedFileData['event.json'].name)
.to.equal('event.json');
expect(unzippedFileData['handler.js'].name)
.to.equal('handler.js');
expect(unzippedFileData['file-1'].name)
.to.equal('file-1');
expect(unzippedFileData['file-2'].name)
.to.equal('file-2');
// bin directory
expect(unzippedFileData['bin/binary-777'].name)
.to.equal('bin/binary-777');
expect(unzippedFileData['bin/binary-444'].name)
.to.equal('bin/binary-444');
// lib directory
expect(unzippedFileData['lib/file-1.js'].name)
.to.equal('lib/file-1.js');
expect(unzippedFileData['lib/directory-1/file-1.js'].name)
.to.equal('lib/directory-1/file-1.js');
// node_modules directory
expect(unzippedFileData['node_modules/directory-1/file-1'].name)
.to.equal('node_modules/directory-1/file-1');
expect(unzippedFileData['node_modules/directory-1/file-2'].name)
.to.equal('node_modules/directory-1/file-2');
expect(unzippedFileData['node_modules/directory-2/file-1'].name)
.to.equal('node_modules/directory-2/file-1');
expect(unzippedFileData['node_modules/directory-2/file-2'].name)
.to.equal('node_modules/directory-2/file-2');
});
});
it('should keep file permissions', () => {
const exclude = [];
const include = [];
const zipFileName = getTestArtifactFileName('file-permissions');
return packageService.zipDirectory(servicePath, exclude, include, zipFileName)
.then((artifact) => {
const data = fs.readFileSync(artifact);
return zip.loadAsync(data);
}).then(unzippedData => {
const unzippedFileData = unzippedData.files;
if (os.platform() === 'win32') {
// chmod does not work right on windows. this is better than nothing?
expect(unzippedFileData['bin/binary-777'].unixPermissions)
.to.not.equal(unzippedFileData['bin/binary-444'].unixPermissions);
} else {
// binary file is set with chmod of 777
expect(unzippedFileData['bin/binary-777'].unixPermissions)
.to.equal(Math.pow(2, 15) + 777);
// read only file is set with chmod of 444
expect(unzippedFileData['bin/binary-444'].unixPermissions)
.to.equal(Math.pow(2, 15) + 444);
}
});
});
it('should exclude with globs', () => {
const exclude = [
'event.json',
'lib/**',
'node_modules/directory-1/**',
];
const include = [];
const zipFileName = getTestArtifactFileName('exclude-with-globs');
return packageService.zipDirectory(servicePath, exclude, include, zipFileName)
.then((artifact) => {
const data = fs.readFileSync(artifact);
return zip.loadAsync(data);
}).then(unzippedData => {
const unzippedFileData = unzippedData.files;
expect(Object.keys(unzippedFileData)
.filter(file => !unzippedFileData[file].dir).length).to.equal(8);
// root directory
expect(unzippedFileData['handler.js'].name)
.to.equal('handler.js');
expect(unzippedFileData['file-1'].name)
.to.equal('file-1');
expect(unzippedFileData['file-2'].name)
.to.equal('file-2');
// bin directory
expect(unzippedFileData['bin/binary-777'].name)
.to.equal('bin/binary-777');
expect(unzippedFileData['bin/binary-444'].name)
.to.equal('bin/binary-444');
// node_modules directory
expect(unzippedFileData['node_modules/directory-2/file-1'].name)
.to.equal('node_modules/directory-2/file-1');
expect(unzippedFileData['node_modules/directory-2/file-2'].name)
.to.equal('node_modules/directory-2/file-2');
});
});
it('should re-include files using ! glob pattern', () => {
const exclude = [
'event.json',
'lib/**',
'node_modules/directory-1/**',
'!event.json', // re-include
'!lib/**', // re-include
];
const include = [];
const zipFileName = getTestArtifactFileName('re-include-with-globs');
return packageService.zipDirectory(servicePath, exclude, include, zipFileName)
.then((artifact) => {
const data = fs.readFileSync(artifact);
return zip.loadAsync(data);
}).then(unzippedData => {
const unzippedFileData = unzippedData.files;
expect(Object.keys(unzippedFileData)
.filter(file => !unzippedFileData[file].dir).length).to.equal(11);
// root directory
expect(unzippedFileData['event.json'].name)
.to.equal('event.json');
expect(unzippedFileData['handler.js'].name)
.to.equal('handler.js');
expect(unzippedFileData['file-1'].name)
.to.equal('file-1');
expect(unzippedFileData['file-2'].name)
.to.equal('file-2');
// bin directory
expect(unzippedFileData['bin/binary-777'].name)
.to.equal('bin/binary-777');
expect(unzippedFileData['bin/binary-444'].name)
.to.equal('bin/binary-444');
// lib directory
expect(unzippedFileData['lib/file-1.js'].name)
.to.equal('lib/file-1.js');
expect(unzippedFileData['lib/directory-1/file-1.js'].name)
.to.equal('lib/directory-1/file-1.js');
// node_modules directory
expect(unzippedFileData['node_modules/directory-2/file-1'].name)
.to.equal('node_modules/directory-2/file-1');
expect(unzippedFileData['node_modules/directory-2/file-2'].name)
.to.equal('node_modules/directory-2/file-2');
});
});
it('should re-include files using include config', () => {
const exclude = [
'event.json',
'lib/**',
'node_modules/directory-1/**',
];
const include = [
'event.json',
'lib/**',
];
const zipFileName = getTestArtifactFileName('re-include-with-include');
return packageService.zipDirectory(servicePath, exclude, include, zipFileName)
.then((artifact) => {
const data = fs.readFileSync(artifact);
return zip.loadAsync(data);
}).then(unzippedData => {
const unzippedFileData = unzippedData.files;
expect(Object.keys(unzippedFileData)
.filter(file => !unzippedFileData[file].dir).length).to.equal(11);
// root directory
expect(unzippedFileData['event.json'].name)
.to.equal('event.json');
expect(unzippedFileData['handler.js'].name)
.to.equal('handler.js');
expect(unzippedFileData['file-1'].name)
.to.equal('file-1');
expect(unzippedFileData['file-2'].name)
.to.equal('file-2');
// bin directory
expect(unzippedFileData['bin/binary-777'].name)
.to.equal('bin/binary-777');
expect(unzippedFileData['bin/binary-444'].name)
.to.equal('bin/binary-444');
// lib directory
expect(unzippedFileData['lib/file-1.js'].name)
.to.equal('lib/file-1.js');
expect(unzippedFileData['lib/directory-1/file-1.js'].name)
.to.equal('lib/directory-1/file-1.js');
// node_modules directory
expect(unzippedFileData['node_modules/directory-2/file-1'].name)
.to.equal('node_modules/directory-2/file-1');
expect(unzippedFileData['node_modules/directory-2/file-2'].name)
.to.equal('node_modules/directory-2/file-2');
});
});
});