Merge pull request #6148 from serverless/integration-tests

Thorough integration testing
This commit is contained in:
Philipp Muens 2019-05-30 15:36:19 +02:00 committed by GitHub
commit 5f0fdae08e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
185 changed files with 1326 additions and 3590 deletions

View File

@ -3,6 +3,7 @@ module.exports = {
"extends": "airbnb",
"plugins": [],
"rules": {
"arrow-body-style": "off",
"func-names": "off",
"global-require": "off", // Interfers with optional and eventual circular references
"import/no-extraneous-dependencies": ["error", {"devDependencies": ["**/*.test.js", "**/scripts/**", "**/tests/**"]}],

5
.gitignore vendored
View File

@ -12,7 +12,7 @@ dist
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
# Coverage directory used by tools like nyc
coverage
/.nyc_output
@ -59,3 +59,6 @@ jest
# DotNet
obj/
[Oo]bj/
# Tests
!tests/**/*.zip

View File

@ -21,7 +21,6 @@ matrix:
node_js: "10.7"
env:
- INTEGRATION_TEST=true
- INTEGRATION_TEST_SUITE=simple
- SLS_IGNORE_WARNING=*
- secure: Ia2nYzOeYvTE6qOP7DBKX3BO7s/U7TXdsvB2nlc3kOPFi//IbTVD0/cLKCAE5XqTzrrliHINSVsFcJNSfjCwmDSRmgoIGrHj5CJkWpkI6FEPageo3mdqFQYEc8CZeAjsPBNaHe6Ewzg0Ev/sjTByLSJYVqokzDCF1QostSxx1Ss6SGt1zjxeP/Hp4yOJn52VAm9IHAKYn7Y62nMAFTaaTPUQHvW0mJj6m2Z8TWyPU+2Bx6mliO65gTPFGs+PdHGwHtmSF/4IcUO504x+HjDuwzW2itomLXZmIOFfGDcFYadKWzVMAfJzoRWOcVKF4jXdMoSCOviWpHGtK35E7K956MTXkroVoWCS7V0knQDovbRZj8c8td8mS4tdprUA+TzgZoHet2atWNtMuTh79rdmwoAO+IAWJegYj62Tdfy3ycESzY+KxSaV8kysG9sR3PRFoWjZerA7MhLZEzQMORXDGjJlgwLaZfYVqjlsGe5p5etFBUTd0WbFgSwOKLoA2U/fm7WzqItkjs3UWaHuvFVvwYixGxjEVmVczS6wa2cdGpHtVD9H7km4fPEzljHqQ26v0P5e8eylgqLF2IB6mL7UqGFrAtrMvAgN/M3gnq4dTs/wq1AJIOxEP7YW7kc0NAldk8vUz6t5GzCPNcuukxAku91Awnh0twxgUywatgJLZPY=
- secure: Dgaa5XIsA5Vbw/CYQLUAuVVsDX26C8+f1XYGwsbNmFQKbKvM8iy9lGrHlfrT3jftJkJH6re8tP1RjyZjjzLe25KPk4Tps7grNteCyiIIEDsC2aHhiXHD6zNHsItpxYusaFfyQinFWnK4CAYKWb9ZNIwHIDUIB4vq807QGAhYsnoj1Lg/ajWvtEKBwYjEzDz9OjB91lw7lpCnHtmKKw5A+TNIVGpDDZ/jRBqETsPaePtiXC9UTHZQyM3gFoeVXiJw9KSU/gjIx9REihCaWWPbnuQSeIONGGlVWY9V4DTZIsJr9/uwDcbioeXDD3G1ezGtNPPRSNTtq08QlUtE4mEtKea/+ObpllKZCeZGn6AJhMn+uqMIP95FFlqBB55YzRcLZY+Igi/qm/9LJ9RinAhxRVXiwzeQ+BdVA6jshAAzr+7wklux6lZAa0xGw9pgTv7MI4RP2LJ/LMP1ppFsnv9n/qt93Ax1VEwEu3xHZe3VTYL9tbXOPTZutf6fKjUrW7wSSuy637queESjYnnPKSb1vZcPxjSFlyh+GJvxu/3PurF9aqfiBdiorIBre+pQS4lakLtoft5nsbA+4iYUwrXR58qUPVUqQ7a0A0hedOWlp6g9ixLa6nugUP5aobJzR71T8l/IjqpnY2EEd/iINEb0XfUiZtB5zHaqFWejBtmWwCI=
@ -44,8 +43,11 @@ script:
- if [[ -z "$INTEGRATION_TEST" && -z "$DISABLE_TESTS" ]]; then npm test; fi
- if [[ ! -z "$DISABLE_TESTS" && ! -z "$LINTING" && -z "$INTEGRATION_TEST" ]]; then
npm run lint; fi
- if [[ ! -z "$INTEGRATION_TEST" && ! -z ${AWS_ACCESS_KEY_ID+x} && "$INTEGRATION_TEST_SUITE"
== "simple" ]]; then npm run simple-integration-test; fi
- if [[ ! -z "$INTEGRATION_TEST" ]]; then npm run integration-test-run-package; fi
- if [[ ! -z "$INTEGRATION_TEST" && ! -z ${AWS_ACCESS_KEY_ID+x} ]]; then npm run integration-test-run-basic; fi
- if [[ ! -z "$INTEGRATION_TEST" && ! -z ${AWS_ACCESS_KEY_ID+x} && "$TRAVIS_BRANCH"
== "master" && "$TRAVIS_PULL_REQUEST" == "false" ]]; then npm run integration-test-run-all; fi
- if [[ ! -z "$INTEGRATION_TEST" && ! -z ${AWS_ACCESS_KEY_ID+x} ]]; then npm run integration-test-cleanup; fi
after_success:
- cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage
deploy:

View File

@ -65,7 +65,7 @@ If you add a new template or want to test a template after changing it you can r
To run all integration tests run:
```
./tests/templates/test_all_templates
./tests/templates/test-all-templates
```
To run only a specific integration test run:
@ -80,7 +80,7 @@ so for example:
tests/templates/integration-test-template aws-java-maven mvn package
```
If you add a new template make sure to add it to the `test_all_templates` file and configure the `docker-compose.yml` file for your template.
If you add a new template make sure to add it to the `test-all-templates` file and configure the `docker-compose.yml` file for your template.
# Our Code of Conduct

View File

@ -13,8 +13,8 @@ const PluginManager = require('../lib/classes/PluginManager');
const Utils = require('../lib/classes/Utils');
const Service = require('../lib/classes/Service');
const CLI = require('../lib/classes/CLI');
const ServerlessError = require('../lib/classes/Error').ServerlessError;
const testUtils = require('../tests/utils');
const { ServerlessError } = require('../lib/classes/Error');
const { getTmpDirPath } = require('../tests/utils/fs');
describe('Serverless', () => {
let serverless;
@ -157,7 +157,7 @@ describe('Serverless', () => {
it('should resolve after loading the service', () => {
const SUtils = new Utils();
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
const serverlessYml = {
service: 'new-service',
provider: 'aws',

View File

@ -9,7 +9,7 @@ const exec = require('child_process').exec;
const path = require('path');
const stripAnsi = require('strip-ansi');
const Serverless = require('../../lib/Serverless');
const testUtils = require('../../tests/utils');
const { getTmpDirPath } = require('../../tests/utils/fs');
describe('CLI', () => {
let cli;
@ -613,7 +613,7 @@ describe('CLI', () => {
const that = this;
before(() => {
const tmpDir = testUtils.getTmpDirPath();
const tmpDir = getTmpDirPath();
that.cwd = process.cwd();

View File

@ -12,14 +12,15 @@ const _ = require('lodash');
const path = require('path');
const fs = require('fs');
const fse = require('fs-extra');
const execSync = require('child_process').execSync;
const mockRequire = require('mock-require');
const testUtils = require('../../tests/utils');
const os = require('os');
const sinon = require('sinon');
const proxyquire = require('proxyquire');
const BbPromise = require('bluebird');
const getCacheFilePath = require('../utils/getCacheFilePath');
const { execSync } = require('child_process');
const { installPlugin } = require('../../tests/utils/plugins');
const { getTmpDirPath } = require('../../tests/utils/fs');
chai.use(require('chai-as-promised'));
chai.use(require('sinon-chai'));
@ -1879,7 +1880,7 @@ describe('PluginManager', () => {
let serviceDir;
let tmpDir;
beforeEach(function () { // eslint-disable-line prefer-arrow-callback
tmpDir = testUtils.getTmpDirPath();
tmpDir = getTmpDirPath();
serviceDir = path.join(tmpDir, 'service');
fse.mkdirsSync(serviceDir);
process.chdir(serviceDir);
@ -1888,7 +1889,7 @@ describe('PluginManager', () => {
it('should load plugins from .serverless_plugins', () => {
const localPluginDir = path.join(serviceDir, '.serverless_plugins', 'local-plugin');
testUtils.installPlugin(localPluginDir, SynchronousPluginMock);
installPlugin(localPluginDir, SynchronousPluginMock);
pluginManager.loadServicePlugins(['local-plugin']);
expect(pluginManager.plugins).to.satisfy(plugins =>
@ -1897,7 +1898,7 @@ describe('PluginManager', () => {
it('should load plugins from custom folder', () => {
const localPluginDir = path.join(serviceDir, 'serverless-plugins-custom', 'local-plugin');
testUtils.installPlugin(localPluginDir, SynchronousPluginMock);
installPlugin(localPluginDir, SynchronousPluginMock);
pluginManager.loadServicePlugins({
localPath: path.join(serviceDir, 'serverless-plugins-custom'),
@ -1912,7 +1913,7 @@ describe('PluginManager', () => {
it('should load plugins from custom folder outside of serviceDir', () => {
serviceDir = path.join(tmpDir, 'serverless-plugins-custom');
const localPluginDir = path.join(serviceDir, 'local-plugin');
testUtils.installPlugin(localPluginDir, SynchronousPluginMock);
installPlugin(localPluginDir, SynchronousPluginMock);
pluginManager.loadServicePlugins({
localPath: serviceDir,
@ -1949,7 +1950,7 @@ describe('PluginManager', () => {
const execPrefix = os.platform() === 'win32' ? 'node ' : '';
serverlessExec = execPrefix + path.join(serverlessInstance.config.serverlessPath,
'..', 'bin', 'serverless');
const tmpDir = testUtils.getTmpDirPath();
const tmpDir = getTmpDirPath();
serviceDir = path.join(tmpDir, 'service');
fse.mkdirsSync(serviceDir);
process.chdir(serviceDir);
@ -1968,8 +1969,8 @@ describe('PluginManager', () => {
it('should load plugins relatively to the working directory', () => {
const localPluginDir = path.join(serviceDir, 'node_modules', 'local-plugin');
const parentPluginDir = path.join(serviceDir, '..', 'node_modules', 'parent-plugin');
testUtils.installPlugin(localPluginDir, SynchronousPluginMock);
testUtils.installPlugin(parentPluginDir, PromisePluginMock);
installPlugin(localPluginDir, SynchronousPluginMock);
installPlugin(parentPluginDir, PromisePluginMock);
fs.appendFileSync(path.join(serviceDir, 'serverless.yml'),
'plugins:\n - local-plugin\n - parent-plugin');

View File

@ -8,7 +8,7 @@ const sinon = require('sinon');
const Service = require('../../lib/classes/Service');
const Utils = require('../../lib/classes/Utils');
const Serverless = require('../../lib/Serverless');
const testUtils = require('../../tests/utils');
const { getTmpDirPath } = require('../../tests/utils/fs');
// Configure chai
chai.use(require('chai-as-promised'));
@ -113,7 +113,7 @@ describe('Service', () => {
let tmpDirPath;
beforeEach(() => {
tmpDirPath = testUtils.getTmpDirPath();
tmpDirPath = getTmpDirPath();
});
it('should resolve if no servicePath is found', () => {
@ -696,7 +696,7 @@ describe('Service', () => {
let tmpDirPath;
beforeEach(() => {
tmpDirPath = testUtils.getTmpDirPath();
tmpDirPath = getTmpDirPath();
});
it('should throw if a function\'s event is not an array or a variable', () => {
@ -972,7 +972,7 @@ describe('Service', () => {
let tmpDirPath;
beforeEach(() => {
tmpDirPath = testUtils.getTmpDirPath();
tmpDirPath = getTmpDirPath();
});
it('should make sure function name contains the default stage', () => {

View File

@ -6,13 +6,14 @@ const uuid = require('uuid');
const chai = require('chai');
const sinon = require('sinon');
const Serverless = require('../../lib/Serverless');
const testUtils = require('../../tests/utils');
const configUtils = require('../utils/config');
const serverlessVersion = require('../../package.json').version;
const segment = require('../utils/segment');
chai.use(require('chai-as-promised'));
const expect = require('chai').expect;
const Utils = require('../../lib/classes/Utils');
const { expect } = require('chai');
const { getTmpFilePath, getTmpDirPath } = require('../../tests/utils/fs');
const serverlessVersion = require('../../package.json').version;
chai.use(require('chai-as-promised'));
describe('Utils', () => {
let utils;
@ -53,7 +54,7 @@ describe('Utils', () => {
describe('#writeFileDir()', () => {
it('should create a directory for the path of the given file', () => {
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
const rootDir = serverless.utils
.writeFileDir(path.join(tmpDirPath, 'foo', 'bar', 'somefile.js'));
@ -66,7 +67,7 @@ describe('Utils', () => {
describe('#writeFileSync()', () => {
it('should write a .json file synchronously', () => {
const tmpFilePath = testUtils.getTmpFilePath('anything.json');
const tmpFilePath = getTmpFilePath('anything.json');
serverless.utils.writeFileSync(tmpFilePath, { foo: 'bar' });
const obj = serverless.utils.readFileSync(tmpFilePath);
@ -75,7 +76,7 @@ describe('Utils', () => {
});
it('should write a .yml file synchronously', () => {
const tmpFilePath = testUtils.getTmpFilePath('anything.yml');
const tmpFilePath = getTmpFilePath('anything.yml');
serverless.utils.writeFileSync(tmpFilePath, { foo: 'bar' });
@ -85,7 +86,7 @@ describe('Utils', () => {
});
it('should write a .yaml file synchronously', () => {
const tmpFilePath = testUtils.getTmpFilePath('anything.yaml');
const tmpFilePath = getTmpFilePath('anything.yaml');
serverless.utils.writeFileSync(tmpFilePath, { foo: 'bar' });
@ -101,7 +102,7 @@ describe('Utils', () => {
describe('#writeFile()', () => {
it('should write a file asynchronously', () => {
const tmpFilePath = testUtils.getTmpFilePath('anything.json');
const tmpFilePath = getTmpFilePath('anything.json');
// note: use return when testing promises otherwise you'll have unhandled rejection errors
return expect(serverless.utils.writeFile(tmpFilePath, { foo: 'bar' }))
@ -115,7 +116,7 @@ describe('Utils', () => {
describe('#appendFileSync()', () => {
it('should append a line to a text file', () => {
const tmpFilePath = testUtils.getTmpFilePath('appendedfile.txt');
const tmpFilePath = getTmpFilePath('appendedfile.txt');
serverless.utils.writeFileSync(tmpFilePath, `line 1 ${os.EOL}`);
serverless.utils.appendFileSync(tmpFilePath, 'line 2');
@ -131,7 +132,7 @@ describe('Utils', () => {
describe('#readFileSync()', () => {
it('should read a file synchronously', () => {
const tmpFilePath = testUtils.getTmpFilePath('anything.json');
const tmpFilePath = getTmpFilePath('anything.json');
serverless.utils.writeFileSync(tmpFilePath, { foo: 'bar' });
const obj = serverless.utils.readFileSync(tmpFilePath);
@ -140,7 +141,7 @@ describe('Utils', () => {
});
it('should read a filename extension .yml', () => {
const tmpFilePath = testUtils.getTmpFilePath('anything.yml');
const tmpFilePath = getTmpFilePath('anything.yml');
serverless.utils.writeFileSync(tmpFilePath, { foo: 'bar' });
const obj = serverless.utils.readFileSync(tmpFilePath);
@ -149,7 +150,7 @@ describe('Utils', () => {
});
it('should read a filename extension .yaml', () => {
const tmpFilePath = testUtils.getTmpFilePath('anything.yaml');
const tmpFilePath = getTmpFilePath('anything.yaml');
serverless.utils.writeFileSync(tmpFilePath, { foo: 'bar' });
const obj = serverless.utils.readFileSync(tmpFilePath);
@ -158,7 +159,7 @@ describe('Utils', () => {
});
it('should throw YAMLException with filename if yml file is invalid format', () => {
const tmpFilePath = testUtils.getTmpFilePath('invalid.yml');
const tmpFilePath = getTmpFilePath('invalid.yml');
serverless.utils.writeFileSync(tmpFilePath, ': a');
@ -170,7 +171,7 @@ describe('Utils', () => {
describe('#readFile()', () => {
it('should read a file asynchronously', () => {
const tmpFilePath = testUtils.getTmpFilePath('anything.json');
const tmpFilePath = getTmpFilePath('anything.json');
serverless.utils.writeFileSync(tmpFilePath, { foo: 'bar' });
@ -183,7 +184,7 @@ describe('Utils', () => {
describe('#walkDirSync()', () => {
it('should return an array with corresponding paths to the found files', () => {
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
const nestedDir1 = path.join(tmpDirPath, 'foo');
const nestedDir2 = path.join(tmpDirPath, 'foo', 'bar');
@ -246,7 +247,7 @@ describe('Utils', () => {
const testDir = process.cwd();
it('should detect if the CWD is a service directory when using Serverless .yaml files', () => {
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
const tmpFilePath = path.join(tmpDirPath, 'serverless.yaml');
serverless.utils.writeFileSync(tmpFilePath, 'foo');
@ -258,7 +259,7 @@ describe('Utils', () => {
});
it('should detect if the CWD is a service directory when using Serverless .yml files', () => {
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
const tmpFilePath = path.join(tmpDirPath, 'serverless.yml');
serverless.utils.writeFileSync(tmpFilePath, 'foo');
@ -270,7 +271,7 @@ describe('Utils', () => {
});
it('should detect if the CWD is a service directory when using Serverless .json files', () => {
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
const tmpFilePath = path.join(tmpDirPath, 'serverless.json');
serverless.utils.writeFileSync(tmpFilePath, 'foo');
@ -282,7 +283,7 @@ describe('Utils', () => {
});
it('should detect if the CWD is a service directory when using Serverless .js files', () => {
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
const tmpFilePath = path.join(tmpDirPath, 'serverless.js');
serverless.utils.writeFileSync(tmpFilePath, 'foo');

View File

@ -16,9 +16,9 @@ const AwsProvider = require('../plugins/aws/provider/awsProvider');
const fse = require('../utils/fs/fse');
const Serverless = require('../../lib/Serverless');
const slsError = require('./Error');
const testUtils = require('../../tests/utils');
const Utils = require('../../lib/classes/Utils');
const Variables = require('../../lib/classes/Variables');
const { getTmpDirPath } = require('../../tests/utils/fs');
BbPromise.longStackTraces(true);
@ -932,7 +932,7 @@ describe('Variables', () => {
describe('file reading cases', () => {
let tmpDirPath;
beforeEach(() => {
tmpDirPath = testUtils.getTmpDirPath();
tmpDirPath = getTmpDirPath();
fse.mkdirsSync(tmpDirPath);
serverless.config.update({ servicePath: tmpDirPath });
});
@ -1622,7 +1622,7 @@ module.exports = {
it('should populate an entire variable file', () => {
const SUtils = new Utils();
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
const configYml = {
test: 1,
test2: 'test2',
@ -1638,7 +1638,7 @@ module.exports = {
});
it('should get undefined if non existing file and the second argument is true', () => {
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
serverless.config.update({ servicePath: tmpDirPath });
const realpathSync = sinon.spy(fse, 'realpathSync');
const existsSync = sinon.spy(fse, 'existsSync');
@ -1656,7 +1656,7 @@ module.exports = {
it('should populate non json/yml files', () => {
const SUtils = new Utils();
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
SUtils.writeFileSync(path.join(tmpDirPath, 'someFile'), 'hello world');
serverless.config.update({ servicePath: tmpDirPath });
return serverless.variables.getValueFromFile('file(./someFile)')
@ -1665,7 +1665,7 @@ module.exports = {
it('should populate symlinks', () => {
const SUtils = new Utils();
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
const realFilePath = path.join(tmpDirPath, 'someFile');
const symlinkPath = path.join(tmpDirPath, 'refSomeFile');
SUtils.writeFileSync(realFilePath, 'hello world');
@ -1681,7 +1681,7 @@ module.exports = {
it('should trim trailing whitespace and new line character', () => {
const SUtils = new Utils();
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
SUtils.writeFileSync(path.join(tmpDirPath, 'someFile'), 'hello world \n');
serverless.config.update({ servicePath: tmpDirPath });
return serverless.variables.getValueFromFile('file(./someFile)')
@ -1690,7 +1690,7 @@ module.exports = {
it('should populate from another file when variable is of any type', () => {
const SUtils = new Utils();
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
const configYml = {
test0: 0,
test1: 'test1',
@ -1707,7 +1707,7 @@ module.exports = {
it('should populate from a javascript file', () => {
const SUtils = new Utils();
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
const jsData = 'module.exports.hello=function(){return "hello world";};';
SUtils.writeFileSync(path.join(tmpDirPath, 'hello.js'), jsData);
serverless.config.update({ servicePath: tmpDirPath });
@ -1717,7 +1717,7 @@ module.exports = {
it('should populate an entire variable exported by a javascript file', () => {
const SUtils = new Utils();
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
const jsData = 'module.exports=function(){return { hello: "hello world" };};';
SUtils.writeFileSync(path.join(tmpDirPath, 'hello.js'), jsData);
serverless.config.update({ servicePath: tmpDirPath });
@ -1727,7 +1727,7 @@ module.exports = {
it('should throw if property exported by a javascript file is not a function', () => {
const SUtils = new Utils();
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
const jsData = 'module.exports={ hello: "hello world" };';
SUtils.writeFileSync(path.join(tmpDirPath, 'hello.js'), jsData);
serverless.config.update({ servicePath: tmpDirPath });
@ -1737,7 +1737,7 @@ module.exports = {
it('should populate deep object from a javascript file', () => {
const SUtils = new Utils();
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
const jsData = `module.exports.hello=function(){
return {one:{two:{three: 'hello world'}}}
};`;
@ -1750,7 +1750,7 @@ module.exports = {
it('should preserve the exported function context when executing', () => {
const SUtils = new Utils();
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
const jsData = `
module.exports.one = {two: {three: 'hello world'}}
module.exports.hello=function(){ return this; };`;
@ -1763,7 +1763,7 @@ module.exports = {
it('should file variable not using ":" syntax', () => {
const SUtils = new Utils();
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
const configYml = {
test: 1,
test2: 'test2',

View File

@ -8,7 +8,7 @@ const chai = require('chai');
const YAML = require('js-yaml');
const path = require('path');
const Serverless = require('../../lib/Serverless');
const testUtils = require('../../tests/utils');
const { getTmpFilePath, getTmpDirPath } = require('../../tests/utils/fs');
// Configure chai
chai.use(require('chai-as-promised'));
@ -19,7 +19,7 @@ const serverless = new Serverless();
describe('YamlParser', () => {
describe('#parse()', () => {
it('should parse a simple .yaml file', () => {
const tmpFilePath = testUtils.getTmpFilePath('simple.yaml');
const tmpFilePath = getTmpFilePath('simple.yaml');
serverless.utils.writeFileSync(tmpFilePath, YAML.dump({ foo: 'bar' }));
@ -28,7 +28,7 @@ describe('YamlParser', () => {
});
it('should parse a simple .yml file', () => {
const tmpFilePath = testUtils.getTmpFilePath('simple.yml');
const tmpFilePath = getTmpFilePath('simple.yml');
serverless.utils.writeFileSync(tmpFilePath, YAML.dump({ foo: 'bar' }));
@ -37,7 +37,7 @@ describe('YamlParser', () => {
});
it('should parse a .yml file with JSON-REF to YAML', () => {
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
serverless.utils.writeFileSync(path.join(tmpDirPath, 'ref.yml'), { foo: 'bar' });
@ -54,7 +54,7 @@ describe('YamlParser', () => {
});
it('should parse a .yml file with JSON-REF to JSON', () => {
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
serverless.utils.writeFileSync(path.join(tmpDirPath, 'ref.json'), { foo: 'bar' });
@ -71,7 +71,7 @@ describe('YamlParser', () => {
});
it('should parse a .yml file with recursive JSON-REF', () => {
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
serverless.utils.writeFileSync(path.join(tmpDirPath, 'three.yml'), { foo: 'bar' });

View File

@ -5,12 +5,12 @@ const path = require('path');
const fse = require('fs-extra');
const AWSCommon = require('../index');
const Serverless = require('../../../../../lib/Serverless');
const testUtils = require('../../../../../tests/utils');
const { getTmpDirPath } = require('../../../../../tests/utils/fs');
describe('#moveArtifactsToPackage()', () => {
let serverless;
let awsCommon;
const moveBasePath = path.join(testUtils.getTmpDirPath(), 'move');
const moveBasePath = path.join(getTmpDirPath(), 'move');
const moveServerlessPath = path.join(moveBasePath, '.serverless');
beforeEach(() => {
@ -99,7 +99,7 @@ describe('#moveArtifactsToPackage()', () => {
describe('#moveArtifactsToTemp()', () => {
let serverless;
let awsCommon;
const moveBasePath = path.join(testUtils.getTmpDirPath(), 'move');
const moveBasePath = path.join(getTmpDirPath(), 'move');
const moveServerlessPath = path.join(moveBasePath, '.serverless');
const moveTargetPath = path.join(moveBasePath, 'target');

View File

@ -4,7 +4,7 @@ const expect = require('chai').expect;
const path = require('path');
const Package = require('../index');
const Serverless = require('../../../../../lib/Serverless');
const testUtils = require('../../../../../tests/utils');
const { getTmpDirPath } = require('../../../../../tests/utils/fs');
describe('#cleanupTempDir()', () => {
let serverless;
@ -14,7 +14,7 @@ describe('#cleanupTempDir()', () => {
serverless = new Serverless();
packageService = new Package(serverless);
serverless.config.servicePath = testUtils.getTmpDirPath();
serverless.config.servicePath = getTmpDirPath();
});
it('should remove .serverless in the service directory', () => {

View File

@ -7,9 +7,9 @@ const fs = require('fs');
const fse = require('fs-extra');
const os = require('os');
const path = require('path');
const testUtils = require('../../../../tests/utils');
const AwsConfigCredentials = require('./awsConfigCredentials');
const Serverless = require('../../../Serverless');
const { getTmpDirPath } = require('../../../../tests/utils/fs');
describe('AwsConfigCredentials', () => {
let awsConfigCredentials;
@ -22,7 +22,7 @@ describe('AwsConfigCredentials', () => {
beforeEach(() => {
sandbox = sinon.sandbox.create();
tmpDirPath = testUtils.getTmpDirPath();
tmpDirPath = getTmpDirPath();
credentialsFilePath = path.join(tmpDirPath, '.aws', 'credentials');
credentialsFileContent = '[my-profile]\n';
credentialsFileContent += 'aws_access_key_id = my-old-profile-key\n';

View File

@ -6,12 +6,12 @@ const path = require('path');
const AwsProvider = require('../../provider/awsProvider');
const AwsDeploy = require('../index');
const Serverless = require('../../../../Serverless');
const testUtils = require('../../../../../tests/utils');
const { getTmpDirPath } = require('../../../../../tests/utils/fs');
describe('createStack', () => {
let awsDeploy;
let sandbox;
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
const serverlessYmlPath = path.join(tmpDirPath, 'serverless.yml');
const serverlessYml = {

View File

@ -6,7 +6,7 @@ const path = require('path');
const AwsProvider = require('../../provider/awsProvider');
const AwsDeploy = require('../index');
const Serverless = require('../../../../Serverless');
const testUtils = require('../../../../../tests/utils');
const { getTmpDirPath } = require('../../../../../tests/utils/fs');
chai.use(require('sinon-chai'));
@ -14,7 +14,7 @@ const expect = chai.expect;
describe('extendedValidate', () => {
let awsDeploy;
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
const serverlessYmlPath = path.join(tmpDirPath, 'serverless.yml');
const serverlessYml = {

View File

@ -11,7 +11,7 @@ const normalizeFiles = require('../../lib/normalizeFiles');
const AwsProvider = require('../../provider/awsProvider');
const AwsDeploy = require('../index');
const Serverless = require('../../../../Serverless');
const testUtils = require('../../../../../tests/utils');
const { getTmpDirPath } = require('../../../../../tests/utils/fs');
chai.use(require('chai-as-promised'));
chai.use(require('sinon-chai'));
@ -171,7 +171,7 @@ describe('uploadArtifacts', () => {
it('should upload the .zip file to the S3 bucket', () => {
cryptoStub.createHash().update().digest.onCall(0).returns('local-hash-zip-file');
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
const artifactFilePath = path.join(tmpDirPath, 'artifact.zip');
serverless.utils.writeFileSync(artifactFilePath, 'artifact.zip file content');
@ -197,7 +197,7 @@ describe('uploadArtifacts', () => {
it('should upload the .zip file to a bucket with SSE bucket policy', () => {
cryptoStub.createHash().update().digest.onCall(0).returns('local-hash-zip-file');
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
const artifactFilePath = path.join(tmpDirPath, 'artifact.zip');
serverless.utils.writeFileSync(artifactFilePath, 'artifact.zip file content');
awsDeploy.serverless.service.provider.deploymentBucketObject = {

View File

@ -7,7 +7,7 @@ const fs = require('fs');
const proxyquire = require('proxyquire');
const AwsProvider = require('../provider/awsProvider');
const Serverless = require('../../../Serverless');
const testUtils = require('../../../../tests/utils');
const { getTmpDirPath } = require('../../../../tests/utils/fs');
chai.use(require('chai-as-promised'));
chai.use(require('sinon-chai'));
@ -442,7 +442,7 @@ describe('AwsDeployFunction', () => {
beforeEach(() => {
// write a file to disc to simulate that the deployment artifact exists
awsDeployFunction.packagePath = testUtils.getTmpDirPath();
awsDeployFunction.packagePath = getTmpDirPath();
artifactFilePath = path.join(awsDeployFunction.packagePath, 'first.zip');
serverless.utils.writeFileSync(artifactFilePath, 'first.zip file content');
updateFunctionCodeStub = sinon

View File

@ -6,7 +6,7 @@ const path = require('path');
const proxyquire = require('proxyquire');
const AwsProvider = require('../provider/awsProvider');
const Serverless = require('../../../Serverless');
const testUtils = require('../../../../tests/utils');
const { getTmpDirPath } = require('../../../../tests/utils/fs');
chai.use(require('chai-as-promised'));
@ -143,7 +143,7 @@ describe('AwsInvoke', () => {
});
it('it should parse file if relative file path is provided', () => {
serverless.config.servicePath = testUtils.getTmpDirPath();
serverless.config.servicePath = getTmpDirPath();
const data = {
testProp: 'testValue',
};
@ -158,7 +158,7 @@ describe('AwsInvoke', () => {
});
it('it should parse file if absolute file path is provided', () => {
serverless.config.servicePath = testUtils.getTmpDirPath();
serverless.config.servicePath = getTmpDirPath();
const data = {
testProp: 'testValue',
};
@ -173,7 +173,7 @@ describe('AwsInvoke', () => {
});
it('it should parse a yaml file if file path is provided', () => {
serverless.config.servicePath = testUtils.getTmpDirPath();
serverless.config.servicePath = getTmpDirPath();
const yamlContent = 'testProp: testValue';
serverless.utils.writeFileSync(path
@ -194,7 +194,7 @@ describe('AwsInvoke', () => {
});
it('it should throw error if file path does not exist', () => {
serverless.config.servicePath = testUtils.getTmpDirPath();
serverless.config.servicePath = getTmpDirPath();
awsInvoke.options.path = 'some/path';
return expect(awsInvoke.extendedValidate())

View File

@ -12,7 +12,7 @@ const stripAnsi = require('strip-ansi');
const AwsProvider = require('../provider/awsProvider');
const Serverless = require('../../../Serverless');
const CLI = require('../../../classes/CLI');
const testUtils = require('../../../../tests/utils');
const { getTmpDirPath } = require('../../../../tests/utils/fs');
chai.use(require('chai-as-promised'));
@ -185,7 +185,7 @@ describe('AwsInvokeLocal', () => {
});
it('it should parse file if relative file path is provided', () => {
serverless.config.servicePath = testUtils.getTmpDirPath();
serverless.config.servicePath = getTmpDirPath();
const data = {
testProp: 'testValue',
};
@ -200,7 +200,7 @@ describe('AwsInvokeLocal', () => {
});
it('it should parse file if absolute file path is provided', () => {
serverless.config.servicePath = testUtils.getTmpDirPath();
serverless.config.servicePath = getTmpDirPath();
const data = {
event: {
testProp: 'testValue',
@ -218,7 +218,7 @@ describe('AwsInvokeLocal', () => {
});
it('it should parse a yaml file if file path is provided', () => {
serverless.config.servicePath = testUtils.getTmpDirPath();
serverless.config.servicePath = getTmpDirPath();
const yamlContent = 'event: data';
serverless.utils.writeFileSync(path
@ -232,7 +232,7 @@ describe('AwsInvokeLocal', () => {
});
it('it should require a js file if file path is provided', () => {
serverless.config.servicePath = testUtils.getTmpDirPath();
serverless.config.servicePath = getTmpDirPath();
const jsContent = [
'module.exports = {',
' headers: { "Content-Type" : "application/json" },',
@ -260,7 +260,7 @@ describe('AwsInvokeLocal', () => {
});
it('it should reject error if file path does not exist', () => {
serverless.config.servicePath = testUtils.getTmpDirPath();
serverless.config.servicePath = getTmpDirPath();
awsInvokeLocal.options.path = 'some/path';
return expect(awsInvokeLocal.extendedValidate()).to.be.rejected;

View File

@ -5,12 +5,12 @@ const sinon = require('sinon');
const AwsProvider = require('../provider/awsProvider');
const AwsDeploy = require('../deploy');
const Serverless = require('../../../Serverless');
const testUtils = require('../../../../tests/utils');
const { getTmpDirPath } = require('../../../../tests/utils/fs');
describe('updateStack', () => {
let serverless;
let awsDeploy;
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
beforeEach(() => {
const options = {

View File

@ -5,8 +5,8 @@ const path = require('path');
const chai = require('chai');
const AwsProvider = require('../../../provider/awsProvider');
const AwsCompileFunctions = require('./index');
const testUtils = require('../../../../../../tests/utils');
const Serverless = require('../../../../../Serverless');
const { getTmpDirPath } = require('../../../../../../tests/utils/fs');
chai.use(require('chai-as-promised'));
@ -34,7 +34,7 @@ describe('AwsCompileFunctions', () => {
const serviceArtifact = 'new-service.zip';
const individualArtifact = 'test.zip';
awsCompileFunctions.packagePath = testUtils.getTmpDirPath();
awsCompileFunctions.packagePath = getTmpDirPath();
// The contents of the test artifacts need to be predictable so the hashes stay the same
serverless.utils.writeFileSync(path.join(awsCompileFunctions.packagePath,
serviceArtifact), 'foobar');

View File

@ -5,8 +5,8 @@ const path = require('path');
const chai = require('chai');
const AwsProvider = require('../../../provider/awsProvider');
const AwsCompileLayers = require('./index');
const testUtils = require('../../../../../../tests/utils');
const Serverless = require('../../../../../Serverless');
const { getTmpDirPath } = require('../../../../../../tests/utils/fs');
chai.use(require('chai-as-promised'));
@ -35,7 +35,7 @@ describe('AwsCompileLayers', () => {
const serviceArtifact = 'new-service.zip';
const individualArtifact = 'test.zip';
awsCompileLayers.packagePath = testUtils.getTmpDirPath();
awsCompileLayers.packagePath = getTmpDirPath();
// The contents of the test artifacts need to be predictable so the hashes stay the same
serverless.utils.writeFileSync(path.join(awsCompileLayers.packagePath,
serviceArtifact), 'foobar');

View File

@ -7,8 +7,8 @@ const AwsProvider = require('../../provider/awsProvider');
const Serverless = require('../../../../Serverless');
const validate = require('../../lib/validate');
const generateCoreTemplate = require('./generateCoreTemplate');
const testUtils = require('../../../../../tests/utils');
const expect = require('chai').expect;
const { getTmpDirPath } = require('../../../../../tests/utils/fs');
chai.use(require('chai-as-promised'));
@ -29,7 +29,7 @@ describe('#generateCoreTemplate()', () => {
Object.assign(awsPlugin, generateCoreTemplate, validate);
awsPlugin.serverless.cli = new serverless.classes.CLI();
awsPlugin.serverless.config.servicePath = testUtils.getTmpDirPath();
awsPlugin.serverless.config.servicePath = getTmpDirPath();
awsPlugin.serverless.service.provider.compiledCloudFormationTemplate = {
Resources: {},

View File

@ -13,7 +13,8 @@ const path = require('path');
const AwsProvider = require('./awsProvider');
const Serverless = require('../../../Serverless');
const testUtils = require('../../../../tests/utils');
const { replaceEnv } = require('../../../../tests/utils/misc');
const { getTmpFilePath } = require('../../../../tests/utils/fs');
chai.use(require('chai-as-promised'));
chai.use(require('sinon-chai'));
@ -813,7 +814,7 @@ describe('AwsProvider', () => {
let originalProviderProfile;
let originalEnvironmentVariables;
const relevantEnvironment = {
AWS_SHARED_CREDENTIALS_FILE: testUtils.getTmpFilePath('credentials'),
AWS_SHARED_CREDENTIALS_FILE: getTmpFilePath('credentials'),
};
let BK_AWS_PROFILE;
@ -821,7 +822,7 @@ describe('AwsProvider', () => {
BK_AWS_PROFILE = process.env.AWS_PROFILE;
delete process.env.AWS_PROFILE;
originalProviderProfile = serverless.service.provider.profile;
originalEnvironmentVariables = testUtils.replaceEnv(relevantEnvironment);
originalEnvironmentVariables = replaceEnv(relevantEnvironment);
serverless.utils.writeFileSync(
relevantEnvironment.AWS_SHARED_CREDENTIALS_FILE,
'[default]\n' +
@ -838,7 +839,7 @@ describe('AwsProvider', () => {
afterEach(() => {
if (BK_AWS_PROFILE) process.env.AWS_PROFILE = BK_AWS_PROFILE;
else delete process.env.AWS_PROFILE;
testUtils.replaceEnv(originalEnvironmentVariables);
replaceEnv(originalEnvironmentVariables);
serverless.service.provider.profile = originalProviderProfile;
});
@ -899,7 +900,7 @@ describe('AwsProvider', () => {
AWS_TESTSTAGE_ACCESS_KEY_ID: 'undefined',
AWS_TESTSTAGE_SECRET_ACCESS_KEY: 'undefined',
AWS_TESTSTAGE_SESSION_TOKEN: 'undefined',
AWS_SHARED_CREDENTIALS_FILE: testUtils.getTmpFilePath('credentials'),
AWS_SHARED_CREDENTIALS_FILE: getTmpFilePath('credentials'),
AWS_PROFILE: 'undefined',
AWS_TESTSTAGE_PROFILE: 'undefined',
};
@ -924,7 +925,7 @@ describe('AwsProvider', () => {
beforeEach(() => {
originalProviderCredentials = serverless.service.provider.credentials;
originalProviderProfile = serverless.service.provider.profile;
originalEnvironmentVariables = testUtils.replaceEnv(relevantEnvironment);
originalEnvironmentVariables = replaceEnv(relevantEnvironment);
// make temporary credentials file
serverless.utils.writeFileSync(
relevantEnvironment.AWS_SHARED_CREDENTIALS_FILE,
@ -945,7 +946,7 @@ describe('AwsProvider', () => {
});
afterEach(() => {
testUtils.replaceEnv(originalEnvironmentVariables);
replaceEnv(originalEnvironmentVariables);
serverless.service.provider.profile = originalProviderProfile;
serverless.service.provider.credentials = originalProviderCredentials;
});

View File

@ -7,10 +7,10 @@ const fse = require('fs-extra');
const Create = require('./create');
const Serverless = require('../../Serverless');
const sinon = require('sinon');
const testUtils = require('../../../tests/utils');
const walkDirSync = require('../../utils/fs/walkDirSync');
const download = require('../../utils/downloadTemplateFromRepo');
const userStats = require('../../utils/userStats');
const { getTmpDirPath } = require('../../../tests/utils/fs');
describe('Create', () => {
let create;
@ -51,7 +51,7 @@ describe('Create', () => {
let cwd;
beforeEach(() => {
tmpDir = testUtils.getTmpDirPath();
tmpDir = getTmpDirPath();
fse.mkdirsSync(tmpDir);
cwd = process.cwd();
});

View File

@ -4,11 +4,11 @@ const expect = require('chai').expect;
const Serverless = require('../../Serverless');
const Install = require('./install.js');
const sinon = require('sinon');
const testUtils = require('../../../tests/utils');
const download = require('../../utils/downloadTemplateFromRepo');
const userStats = require('../../utils/userStats');
const fse = require('fs-extra');
const path = require('path');
const { getTmpDirPath } = require('../../../tests/utils/fs');
describe('Install', () => {
let install;
@ -19,7 +19,7 @@ describe('Install', () => {
let servicePath;
beforeEach(() => {
const tmpDir = testUtils.getTmpDirPath();
const tmpDir = getTmpDirPath();
cwd = process.cwd();
fse.mkdirsSync(tmpDir);

View File

@ -14,7 +14,7 @@ const childProcess = BbPromise.promisifyAll(require('child_process'));
const sinon = require('sinon');
const Package = require('../package');
const Serverless = require('../../../Serverless');
const testUtils = require('../../../../tests/utils');
const { getTmpDirPath } = require('../../../../tests/utils/fs');
// Configure chai
chai.use(require('chai-as-promised'));
@ -28,7 +28,7 @@ describe('zipService', () => {
let params;
beforeEach(() => {
tmpDirPath = testUtils.getTmpDirPath();
tmpDirPath = getTmpDirPath();
serverless = new Serverless();
serverless.service.service = 'first-service';
serverless.config.servicePath = tmpDirPath;

View File

@ -11,11 +11,12 @@ const fse = require('fs-extra');
const PluginInstall = require('./install');
const Serverless = require('../../../Serverless');
const CLI = require('../../../classes/CLI');
const testUtils = require('../../../../tests/utils');
const userStats = require('../../../utils/userStats');
chai.use(require('chai-as-promised'));
const expect = require('chai').expect;
const _ = require('lodash');
const userStats = require('../../../utils/userStats');
const { expect } = require('chai');
const { getTmpDirPath } = require('../../../../tests/utils/fs');
chai.use(require('chai-as-promised'));
describe('PluginInstall', () => {
let pluginInstall;
@ -110,7 +111,7 @@ describe('PluginInstall', () => {
let installPeerDependenciesStub;
beforeEach(() => {
servicePath = testUtils.getTmpDirPath();
servicePath = getTmpDirPath();
pluginInstall.serverless.config.servicePath = servicePath;
fse.ensureDirSync(servicePath);
serverlessYmlFilePath = path.join(servicePath, 'serverless.yml');
@ -261,7 +262,7 @@ describe('PluginInstall', () => {
beforeEach(() => {
pluginInstall.options.pluginName = 'serverless-plugin-1';
pluginInstall.options.pluginVersion = 'latest';
servicePath = testUtils.getTmpDirPath();
servicePath = getTmpDirPath();
pluginInstall.serverless.config.servicePath = servicePath;
fse.ensureDirSync(servicePath);
packageJsonFilePath = path.join(servicePath, 'package.json');
@ -327,7 +328,7 @@ describe('PluginInstall', () => {
let serverlessYmlFilePath;
beforeEach(() => {
servicePath = testUtils.getTmpDirPath();
servicePath = getTmpDirPath();
pluginInstall.serverless.config.servicePath = servicePath;
serverlessYmlFilePath = path.join(servicePath, 'serverless.yml');
});
@ -507,7 +508,7 @@ describe('PluginInstall', () => {
beforeEach(() => {
pluginName = 'some-plugin';
pluginInstall.options.pluginName = pluginName;
servicePath = testUtils.getTmpDirPath();
servicePath = getTmpDirPath();
fse.ensureDirSync(servicePath);
pluginInstall.serverless.config.servicePath = servicePath;
servicePackageJsonFilePath = path.join(servicePath, 'package.json');

View File

@ -10,9 +10,10 @@ const chalk = require('chalk');
const PluginInstall = require('./../install/install');
const Serverless = require('../../../Serverless');
const CLI = require('../../../classes/CLI');
const testUtils = require('../../../../tests/utils');
const { expect } = require('chai');
const { getTmpDirPath } = require('../../../../tests/utils/fs');
chai.use(require('chai-as-promised'));
const expect = require('chai').expect;
describe('PluginUtils', () => {
let pluginUtils;
@ -66,7 +67,7 @@ describe('PluginUtils', () => {
let servicePath;
beforeEach(() => {
servicePath = testUtils.getTmpDirPath();
servicePath = getTmpDirPath();
pluginUtils.serverless.config.servicePath = servicePath;
});

View File

@ -10,10 +10,11 @@ const fse = require('fs-extra');
const PluginUninstall = require('./uninstall');
const Serverless = require('../../../Serverless');
const CLI = require('../../../classes/CLI');
const testUtils = require('../../../../tests/utils');
const userStats = require('../../../utils/userStats');
const { expect } = require('chai');
const { getTmpDirPath } = require('../../../../tests/utils/fs');
chai.use(require('chai-as-promised'));
const expect = require('chai').expect;
describe('PluginUninstall', () => {
let pluginUninstall;
@ -105,7 +106,7 @@ describe('PluginUninstall', () => {
let uninstallPeerDependenciesStub;
beforeEach(() => {
servicePath = testUtils.getTmpDirPath();
servicePath = getTmpDirPath();
pluginUninstall.serverless.config.servicePath = servicePath;
fse.ensureDirSync(servicePath);
serverlessYmlFilePath = path.join(servicePath, 'serverless.yml');
@ -203,7 +204,7 @@ describe('PluginUninstall', () => {
beforeEach(() => {
pluginUninstall.options.pluginName = 'serverless-plugin-1';
servicePath = testUtils.getTmpDirPath();
servicePath = getTmpDirPath();
pluginUninstall.serverless.config.servicePath = servicePath;
fse.ensureDirSync(servicePath);
packageJsonFilePath = path.join(servicePath, 'package.json');
@ -249,7 +250,7 @@ describe('PluginUninstall', () => {
let serverlessYmlFilePath;
beforeEach(() => {
servicePath = testUtils.getTmpDirPath();
servicePath = getTmpDirPath();
pluginUninstall.serverless.config.servicePath = servicePath;
serverlessYmlFilePath = path.join(servicePath, 'serverless.yml');
});
@ -477,7 +478,7 @@ describe('PluginUninstall', () => {
beforeEach(() => {
pluginName = 'some-plugin';
pluginUninstall.options.pluginName = pluginName;
servicePath = testUtils.getTmpDirPath();
servicePath = getTmpDirPath();
pluginUninstall.serverless.config.servicePath = servicePath;
pluginPath = path.join(
servicePath, 'node_modules', pluginName);

View File

@ -1,19 +1,19 @@
'use strict';
const expect = require('chai').expect;
const sinon = require('sinon');
const BbPromise = require('bluebird');
const testUtils = require('../../tests/utils');
const fse = require('fs-extra');
const path = require('path');
const proxyquire = require('proxyquire');
const { expect } = require('chai');
const { getTmpDirPath } = require('../../tests/utils/fs');
const writeFileSync = require('./fs/writeFileSync');
const readFileSync = require('./fs/readFileSync');
const remove = BbPromise.promisify(fse.remove);
const parseRepoURL = require('./downloadTemplateFromRepo').parseRepoURL;
const { parseRepoURL } = require('./downloadTemplateFromRepo');
describe('downloadTemplateFromRepo', () => {
let downloadTemplateFromRepo;
@ -24,7 +24,7 @@ describe('downloadTemplateFromRepo', () => {
let newServicePath;
beforeEach(() => {
const tmpDir = testUtils.getTmpDirPath();
const tmpDir = getTmpDirPath();
cwd = process.cwd();
fse.mkdirsSync(tmpDir);

View File

@ -1,9 +1,9 @@
'use strict';
const testUtils = require('../../../tests/utils');
const chai = require('chai');
const writeFile = require('./writeFile');
const readFile = require('./readFile');
const { getTmpFilePath } = require('../../../tests/utils/fs');
// Configure chai
chai.use(require('chai-as-promised'));
@ -12,28 +12,28 @@ const expect = require('chai').expect;
describe('#readFile()', () => {
it('should read a file asynchronously', () => {
const tmpFilePath = testUtils.getTmpFilePath('anything.json');
const tmpFilePath = getTmpFilePath('anything.json');
return writeFile(tmpFilePath, { foo: 'bar' })
.then(() => expect(readFile(tmpFilePath)).to.eventually.deep.equal({ foo: 'bar' }));
});
it('should read a filename extension .yml', () => {
const tmpFilePath = testUtils.getTmpFilePath('anything.yml');
const tmpFilePath = getTmpFilePath('anything.yml');
return writeFile(tmpFilePath, { foo: 'bar' })
.then(() => expect(readFile(tmpFilePath)).to.eventually.deep.equal({ foo: 'bar' }));
});
it('should read a filename extension .yaml', () => {
const tmpFilePath = testUtils.getTmpFilePath('anything.yaml');
const tmpFilePath = getTmpFilePath('anything.yaml');
return writeFile(tmpFilePath, { foo: 'bar' })
.then(() => expect(readFile(tmpFilePath)).to.eventually.deep.equal({ foo: 'bar' }));
});
it('should throw YAMLException with filename if yml file is invalid format', () => {
const tmpFilePath = testUtils.getTmpFilePath('invalid.yml');
const tmpFilePath = getTmpFilePath('invalid.yml');
return writeFile(tmpFilePath, ': a').then(() => readFile(tmpFilePath))
.catch(e => {
expect(e.name).to.equal('YAMLException');

View File

@ -1,13 +1,13 @@
'use strict';
const testUtils = require('../../../tests/utils');
const expect = require('chai').expect;
const writeFileSync = require('./writeFileSync');
const readFileSync = require('./readFileSync');
const { getTmpFilePath } = require('../../../tests/utils/fs');
describe('#readFileSync()', () => {
it('should read a file synchronously', () => {
const tmpFilePath = testUtils.getTmpFilePath('anything.json');
const tmpFilePath = getTmpFilePath('anything.json');
writeFileSync(tmpFilePath, { foo: 'bar' });
const obj = readFileSync(tmpFilePath);
@ -16,7 +16,7 @@ describe('#readFileSync()', () => {
});
it('should read a filename extension .yml', () => {
const tmpFilePath = testUtils.getTmpFilePath('anything.yml');
const tmpFilePath = getTmpFilePath('anything.yml');
writeFileSync(tmpFilePath, { foo: 'bar' });
const obj = readFileSync(tmpFilePath);
@ -25,7 +25,7 @@ describe('#readFileSync()', () => {
});
it('should read a filename extension .yaml', () => {
const tmpFilePath = testUtils.getTmpFilePath('anything.yaml');
const tmpFilePath = getTmpFilePath('anything.yaml');
writeFileSync(tmpFilePath, { foo: 'bar' });
const obj = readFileSync(tmpFilePath);
@ -34,7 +34,7 @@ describe('#readFileSync()', () => {
});
it('should throw YAMLException with filename if yml file is invalid format', () => {
const tmpFilePath = testUtils.getTmpFilePath('invalid.yml');
const tmpFilePath = getTmpFilePath('invalid.yml');
writeFileSync(tmpFilePath, ': a');

View File

@ -2,14 +2,14 @@
const fs = require('fs');
const path = require('path');
const expect = require('chai').expect;
const testUtils = require('../../../tests/utils');
const writeFileSync = require('./writeFileSync');
const walkDirSync = require('./walkDirSync');
const { expect } = require('chai');
const { getTmpDirPath } = require('../../../tests/utils/fs');
describe('#walkDirSync()', () => {
it('should return an array with corresponding paths to the found files', () => {
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
const nestedDir1 = path.join(tmpDirPath, 'foo');
const nestedDir2 = path.join(tmpDirPath, 'foo', 'bar');
@ -31,7 +31,7 @@ describe('#walkDirSync()', () => {
});
it('should check noLinks option', () => {
const tmpDirPath = testUtils.getTmpDirPath();
const tmpDirPath = getTmpDirPath();
const realFile = path.join(tmpDirPath, 'real');
writeFileSync(realFile, 'content');

View File

@ -1,11 +1,11 @@
'use strict';
const fse = require('./fse');
const testUtils = require('../../../tests/utils');
const Serverless = require('../../../lib/Serverless');
const chai = require('chai');
const writeFile = require('./writeFile');
const readFile = require('./readFile');
const { getTmpFilePath } = require('../../../tests/utils/fs');
// Configure chai
chai.use(require('chai-as-promised'));
@ -21,14 +21,14 @@ describe('#writeFile()', function () {
});
it('should write a .json file asynchronously', () => {
const tmpFilePath = testUtils.getTmpFilePath('anything.json');
const tmpFilePath = getTmpFilePath('anything.json');
return writeFile(tmpFilePath, { foo: 'bar' })
.then(() => expect(readFile(tmpFilePath))
.to.eventually.deep.equal({ foo: 'bar' }));
});
it('should write a .yml file synchronously', () => {
const tmpFilePath = testUtils.getTmpFilePath('anything.yml');
const tmpFilePath = getTmpFilePath('anything.yml');
return writeFile(tmpFilePath, { foo: 'bar' })
.then(() => expect(serverless.yamlParser.parse(tmpFilePath))
@ -36,7 +36,7 @@ describe('#writeFile()', function () {
});
it('should write a .yaml file synchronously', () => {
const tmpFilePath = testUtils.getTmpFilePath('anything.yaml');
const tmpFilePath = getTmpFilePath('anything.yaml');
return writeFile(tmpFilePath, { foo: 'bar' })
.then(() => expect(serverless.yamlParser.parse(tmpFilePath))
@ -44,7 +44,7 @@ describe('#writeFile()', function () {
});
it('should be able to write an object with circular references', () => {
const tmpFilePath = testUtils.getTmpFilePath('anything.json');
const tmpFilePath = getTmpFilePath('anything.json');
const bar = {};
bar.foo = bar;
const expected = '{\n "foo": {\n "$ref": "$"\n }\n}';

View File

@ -1,11 +1,11 @@
'use strict';
const fse = require('./fse');
const testUtils = require('../../../tests/utils');
const Serverless = require('../../../lib/Serverless');
const expect = require('chai').expect;
const writeFileSync = require('./writeFileSync');
const readFileSync = require('./readFileSync');
const { expect } = require('chai');
const { getTmpFilePath } = require('../../../tests/utils/fs');
describe('#writeFileSync()', () => {
let serverless;
@ -15,7 +15,7 @@ describe('#writeFileSync()', () => {
});
it('should write a .json file synchronously', () => {
const tmpFilePath = testUtils.getTmpFilePath('anything.json');
const tmpFilePath = getTmpFilePath('anything.json');
writeFileSync(tmpFilePath, { foo: 'bar' });
const obj = readFileSync(tmpFilePath);
@ -24,7 +24,7 @@ describe('#writeFileSync()', () => {
});
it('should write a .yml file synchronously', () => {
const tmpFilePath = testUtils.getTmpFilePath('anything.yml');
const tmpFilePath = getTmpFilePath('anything.yml');
writeFileSync(tmpFilePath, { foo: 'bar' });
@ -34,7 +34,7 @@ describe('#writeFileSync()', () => {
});
it('should write a .yaml file synchronously', () => {
const tmpFilePath = testUtils.getTmpFilePath('anything.yaml');
const tmpFilePath = getTmpFilePath('anything.yaml');
writeFileSync(tmpFilePath, { foo: 'bar' });
@ -48,7 +48,7 @@ describe('#writeFileSync()', () => {
});
it('should be able to write an object with circular references', () => {
const tmpFilePath = testUtils.getTmpFilePath('anything.json');
const tmpFilePath = getTmpFilePath('anything.json');
const bar = {};
bar.foo = bar;
const expected = '{\n "foo": {\n "$ref": "$"\n }\n}';

View File

@ -2,9 +2,9 @@
const path = require('path');
const chai = require('chai');
const testUtils = require('../../tests/utils');
const writeFileSync = require('./fs/writeFileSync');
const serverlessConfigFileUtils = require('./getServerlessConfigFile');
const { getTmpDirPath } = require('../../tests/utils/fs');
const getServerlessConfigFile = serverlessConfigFileUtils.getServerlessConfigFile;
@ -16,7 +16,7 @@ describe('#getServerlessConfigFile()', () => {
let tmpDirPath;
beforeEach(() => {
tmpDirPath = testUtils.getTmpDirPath();
tmpDirPath = getTmpDirPath();
});
it('should return an empty string if no serverless file is found', () => {

View File

@ -1,12 +1,12 @@
'use strict';
const expect = require('chai').expect;
const Serverless = require('../Serverless');
const testUtils = require('../../tests/utils');
const fse = require('fs-extra');
const path = require('path');
const { expect } = require('chai');
const { getTmpDirPath } = require('../../tests/utils/fs');
const renameService = require('./renameService').renameService;
const { renameService } = require('./renameService');
describe('renameService', () => {
let serverless;
@ -15,7 +15,7 @@ describe('renameService', () => {
let servicePath;
beforeEach(() => {
const tmpDir = testUtils.getTmpDirPath();
const tmpDir = getTmpDirPath();
cwd = process.cwd();
fse.mkdirsSync(tmpDir);

View File

@ -2,12 +2,12 @@
const path = require('path');
const chai = require('chai');
const testUtils = require('../../tests/utils');
const writeFileSync = require('./fs/writeFileSync');
const readFileSync = require('./fs/readFileSync');
const yamlAstParser = require('./yamlAstParser');
const _ = require('lodash');
const chaiAsPromised = require('chai-as-promised');
const { getTmpDirPath } = require('../../tests/utils/fs');
chai.use(chaiAsPromised);
const expect = require('chai').expect;
@ -16,7 +16,7 @@ describe('#yamlAstParser', () => {
let tmpDirPath;
beforeEach(() => {
tmpDirPath = testUtils.getTmpDirPath();
tmpDirPath = getTmpDirPath();
});
describe('#addNewArrayItem()', () => {

245
package-lock.json generated
View File

@ -274,21 +274,6 @@
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
"integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==",
"dev": true
},
"ansi-regex": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
"dev": true
},
"strip-ansi": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
"dev": true,
"requires": {
"ansi-regex": "^4.1.0"
}
}
}
},
@ -522,11 +507,10 @@
}
},
"@serverless/platform-sdk": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@serverless/platform-sdk/-/platform-sdk-1.0.0.tgz",
"integrity": "sha512-+MYfXA36tXERShJDbfMQcEJKt4eRHQBbUeAzrY7emzJ/RYViPTw49Z8iHvYXhsMIi0v0DOlGHma7xNtGaKNm6Q==",
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@serverless/platform-sdk/-/platform-sdk-1.0.1.tgz",
"integrity": "sha512-x7DWlvAEOdwur7pYLPHkqsEJ4+1xgmOHjSqpv3krthqQoUuh1+IBexL+GhtYqpN1t3N//a4mXDREb2Vd5eqIhA==",
"requires": {
"babel-polyfill": "^6.26.0",
"body-parser": "^1.19.0",
"chalk": "^2.4.1",
"cors": "^2.8.4",
@ -538,6 +522,7 @@
"querystring": "^0.2.0",
"ramda": "^0.25.0",
"rc": "^1.2.8",
"regenerator-runtime": "^0.13.1",
"source-map-support": "^0.5.12",
"uuid": "^3.3.2",
"write-file-atomic": "^2.4.2"
@ -1021,9 +1006,9 @@
"dev": true
},
"aws-sdk": {
"version": "2.452.0",
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.452.0.tgz",
"integrity": "sha512-l6J2NmUg12xpDKG9YdlPje5+Z+nNvqyWMA85ookzPqwx8RcD28D3vg4K1aGi27/oo/3NsngR3XfKUBPSqUpUMA==",
"version": "2.454.0",
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.454.0.tgz",
"integrity": "sha512-1vB9DNIwh+mqKD2IZspYTQapCD6f5VnMT5V2VPlXJ1CNcUdFSU8FFyxKmYApNs+S3re1h3fhWDjpwTreS+XLRQ==",
"requires": {
"buffer": "4.9.1",
"events": "1.1.1",
@ -1098,17 +1083,15 @@
"has-ansi": "^2.0.0",
"strip-ansi": "^3.0.0",
"supports-color": "^2.0.0"
},
"dependencies": {
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
"requires": {
"ansi-regex": "^2.0.0"
}
}
}
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
"requires": {
"ansi-regex": "^2.0.0"
}
},
"supports-color": {
@ -1173,23 +1156,6 @@
"@types/babel__traverse": "^7.0.6"
}
},
"babel-polyfill": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz",
"integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=",
"requires": {
"babel-runtime": "^6.26.0",
"core-js": "^2.5.0",
"regenerator-runtime": "^0.10.5"
},
"dependencies": {
"regenerator-runtime": {
"version": "0.10.5",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz",
"integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg="
}
}
},
"babel-preset-jest": {
"version": "24.6.0",
"resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.6.0.tgz",
@ -1200,22 +1166,6 @@
"babel-plugin-jest-hoist": "^24.6.0"
}
},
"babel-runtime": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
"requires": {
"core-js": "^2.4.0",
"regenerator-runtime": "^0.11.0"
},
"dependencies": {
"regenerator-runtime": {
"version": "0.11.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
}
}
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
@ -1865,9 +1815,9 @@
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
},
"combined-stream": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
"integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==",
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"requires": {
"delayed-stream": "~1.0.0"
}
@ -1988,11 +1938,6 @@
"resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
"integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40="
},
"core-js": {
"version": "2.6.8",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.8.tgz",
"integrity": "sha512-RWlREFU74TEkdXzyl1bka66O3kYp8jeTXrvJZDzVVMH8AiHUSOFpL1yfhQJ+wHocAm1m+4971W1PPzfLuCv1vg=="
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
@ -2653,17 +2598,6 @@
"has-ansi": "^2.0.0",
"strip-ansi": "^3.0.0",
"supports-color": "^2.0.0"
},
"dependencies": {
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
"requires": {
"ansi-regex": "^2.0.0"
}
}
}
},
"debug": {
@ -2694,17 +2628,6 @@
"string-width": "^1.0.1",
"strip-ansi": "^3.0.0",
"through": "^2.3.6"
},
"dependencies": {
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
"requires": {
"ansi-regex": "^2.0.0"
}
}
}
},
"ms": {
@ -2722,6 +2645,15 @@
"once": "^1.3.0"
}
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
"requires": {
"ansi-regex": "^2.0.0"
}
},
"supports-color": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
@ -3135,9 +3067,9 @@
}
},
"express": {
"version": "4.17.0",
"resolved": "https://registry.npmjs.org/express/-/express-4.17.0.tgz",
"integrity": "sha512-1Z7/t3Z5ZnBG252gKUPyItc4xdeaA0X934ca2ewckAsVsw9EG71i++ZHZPYnus8g/s5Bty8IMpSVEuRkmwwPRQ==",
"version": "4.17.1",
"resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
"integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
"requires": {
"accepts": "~1.3.7",
"array-flatten": "1.1.1",
@ -3612,8 +3544,7 @@
"version": "2.1.1",
"resolved": false,
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
"dev": true,
"optional": true
"dev": true
},
"aproba": {
"version": "1.2.0",
@ -3637,15 +3568,13 @@
"version": "1.0.0",
"resolved": false,
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"dev": true,
"optional": true
"dev": true
},
"brace-expansion": {
"version": "1.1.11",
"resolved": false,
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -3662,22 +3591,19 @@
"version": "1.1.0",
"resolved": false,
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
"dev": true,
"optional": true
"dev": true
},
"concat-map": {
"version": "0.0.1",
"resolved": false,
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true,
"optional": true
"dev": true
},
"console-control-strings": {
"version": "1.1.0",
"resolved": false,
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
"dev": true,
"optional": true
"dev": true
},
"core-util-is": {
"version": "1.0.2",
@ -3808,8 +3734,7 @@
"version": "2.0.3",
"resolved": false,
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
"dev": true,
"optional": true
"dev": true
},
"ini": {
"version": "1.3.5",
@ -3823,7 +3748,6 @@
"resolved": false,
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
"dev": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@ -3840,7 +3764,6 @@
"resolved": false,
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@ -3849,15 +3772,13 @@
"version": "0.0.8",
"resolved": false,
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
"dev": true,
"optional": true
"dev": true
},
"minipass": {
"version": "2.3.5",
"resolved": false,
"integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==",
"dev": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@ -3878,7 +3799,6 @@
"resolved": false,
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"dev": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@ -3967,8 +3887,7 @@
"version": "1.0.1",
"resolved": false,
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
"dev": true,
"optional": true
"dev": true
},
"object-assign": {
"version": "4.1.1",
@ -3982,7 +3901,6 @@
"resolved": false,
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@ -4078,8 +3996,7 @@
"version": "5.1.2",
"resolved": false,
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"dev": true,
"optional": true
"dev": true
},
"safer-buffer": {
"version": "2.1.2",
@ -4121,7 +4038,6 @@
"resolved": false,
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"dev": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@ -4143,7 +4059,6 @@
"resolved": false,
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@ -4192,15 +4107,13 @@
"version": "1.0.2",
"resolved": false,
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true,
"optional": true
"dev": true
},
"yallist": {
"version": "3.0.3",
"resolved": false,
"integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==",
"dev": true,
"optional": true
"dev": true
}
}
},
@ -5230,6 +5143,30 @@
}
}
},
"jest-circus": {
"version": "24.8.0",
"resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-24.8.0.tgz",
"integrity": "sha512-2QASG3QuDdk0SMP2O73D8u3/lc/A/E2G7q23v5WhbUR+hCGzWZXwRMKif18f11dSLfL1wcrMbwE4IorvV0DRVw==",
"dev": true,
"requires": {
"@babel/traverse": "^7.1.0",
"@jest/environment": "^24.8.0",
"@jest/test-result": "^24.8.0",
"@jest/types": "^24.8.0",
"chalk": "^2.0.1",
"co": "^4.6.0",
"expect": "^24.8.0",
"is-generator-fn": "^2.0.0",
"jest-each": "^24.8.0",
"jest-matcher-utils": "^24.8.0",
"jest-message-util": "^24.8.0",
"jest-snapshot": "^24.8.0",
"jest-util": "^24.8.0",
"pretty-format": "^24.8.0",
"stack-utils": "^1.0.1",
"throat": "^4.0.0"
}
},
"jest-cli": {
"version": "24.8.0",
"resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-24.8.0.tgz",
@ -6750,9 +6687,9 @@
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
},
"neo-async": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz",
"integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==",
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz",
"integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==",
"dev": true
},
"nested-error-stacks": {
@ -8968,12 +8905,6 @@
"json-stable-stringify": "^1.0.1"
}
},
"ansi-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
"dev": true
},
"ansi-styles": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
@ -8991,23 +8922,6 @@
"has-ansi": "^2.0.0",
"strip-ansi": "^3.0.0",
"supports-color": "^2.0.0"
},
"dependencies": {
"ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
"dev": true
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
"requires": {
"ansi-regex": "^2.0.0"
}
}
}
},
"is-fullwidth-code-point": {
@ -9026,6 +8940,12 @@
"strip-ansi": "^4.0.0"
},
"dependencies": {
"ansi-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
"dev": true
},
"strip-ansi": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
@ -9037,6 +8957,15 @@
}
}
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
"requires": {
"ansi-regex": "^2.0.0"
}
},
"supports-color": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
@ -9337,9 +9266,9 @@
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
},
"uglify-js": {
"version": "3.5.11",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.11.tgz",
"integrity": "sha512-izPJg8RsSyqxbdnqX36ExpbH3K7tDBsAU/VfNv89VkMFy3z39zFjunQGsSHOlGlyIfGLGprGeosgQno3bo2/Kg==",
"version": "3.5.12",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.12.tgz",
"integrity": "sha512-KeQesOpPiZNgVwJj8Ge3P4JYbQHUdZzpx6Fahy6eKAYRSV4zhVmLXoC+JtOeYxcHCHTve8RG1ZGdTvpeOUM26Q==",
"dev": true,
"optional": true,
"requires": {

View File

@ -57,10 +57,10 @@
"test": "nyc --reporter=lcov --reporter=html --reporter=text-summary npm run test-bare",
"lint": "eslint . --cache",
"docs": "node scripts/generate-readme.js",
"integration-test-cleanup": "node scripts/integration-test-cleanup.js",
"packaging-integration-test": "jest --maxWorkers=5 packaging-suite",
"simple-integration-test": "jest --maxWorkers=5 simple-suite",
"complex-integration-test": "jest --maxWorkers=5 integration",
"integration-test-run-package": "jest --maxWorkers=5 integration-package",
"integration-test-run-basic": "jest --maxWorkers=5 integration-basic",
"integration-test-run-all": "jest --maxWorkers=5 integration-all",
"integration-test-cleanup": "node tests/utils/aws-cleanup.js",
"postinstall": "node ./scripts/postinstall.js"
},
"mocha": {
@ -71,8 +71,9 @@
"testRegex": "(\\.|/)(tests)\\.js$",
"testEnvironment": "node",
"setupFilesAfterEnv": [
"<rootDir>/tests/setupTests.js"
]
"<rootDir>/tests/setup-tests.js"
],
"testRunner": "jest-circus/runner"
},
"devDependencies": {
"chai": "^3.5.0",
@ -86,6 +87,7 @@
"eslint-plugin-import": "^1.13.0",
"eslint-plugin-jsx-a11y": "^2.1.0",
"eslint-plugin-react": "^6.1.1",
"jest-circus": "^24.8.0",
"jest-cli": "^24.5.0",
"markdown-link": "^0.1.1",
"markdown-magic": "^0.1.25",

View File

@ -1,97 +0,0 @@
'use strict';
const BbPromise = require('bluebird');
const AWS = require('aws-sdk');
const CF = new AWS.CloudFormation({ region: 'us-east-1' });
const S3 = new AWS.S3({ region: 'us-east-1' });
BbPromise.promisifyAll(CF, { suffix: 'Promised' });
BbPromise.promisifyAll(S3, { suffix: 'Promised' });
const logger = console;
const emptyS3Bucket = (bucket) => (
S3.listObjectsPromised({ Bucket: bucket })
.then(data => {
logger.log('Bucket', bucket, 'has', data.Contents.length, 'items');
if (data.Contents.length) {
const keys = data.Contents.map(item => Object.assign({}, { Key: item.Key }));
return S3.deleteObjectsPromised({
Bucket: bucket,
Delete: {
Objects: keys,
},
});
}
return BbPromise.resolve();
})
);
const deleteS3Bucket = (bucket) => (
emptyS3Bucket(bucket)
.then(() => {
logger.log('Bucket', bucket, 'is now empty, deleting ...');
return S3.deleteBucketPromised({ Bucket: bucket });
})
);
const cleanupS3Buckets = (token) => {
logger.log('Looking through buckets ...');
const params = {};
if (token) {
params.NextToken = token;
}
return S3.listBucketsPromised()
.then(response =>
response.Buckets.reduce((memo, bucket) => memo
.then(() => deleteS3Bucket(bucket.Name)), BbPromise.resolve())
.then(() => {
if (response.NextToken) {
return cleanupS3Buckets(response.NextToken);
}
return BbPromise.resolve();
})
);
};
const cleanupCFStacks = (token) => {
const params = {
StackStatusFilter: [
'CREATE_FAILED',
'CREATE_COMPLETE',
'ROLLBACK_FAILED',
'ROLLBACK_COMPLETE',
'DELETE_FAILED',
'UPDATE_ROLLBACK_FAILED',
'UPDATE_ROLLBACK_COMPLETE',
],
};
if (token) {
params.NextToken = token;
}
logger.log('Looking through stacks ...');
return CF.listStacksPromised(params)
.then(response =>
response.StackSummaries.reduce((memo, stack) => {
if (['DELETE_COMPLETE', 'DELETE_IN_PROGRESS'].indexOf(stack.StackStatus) === -1) {
logger.log('Deleting stack', stack.StackName);
return memo.then(() => CF.deleteStackPromised({ StackName: stack.StackName }));
}
return memo;
}, BbPromise.resolve())
.then(() => {
if (response.NextToken) {
return cleanupCFStacks(response.NextToken);
}
return BbPromise.resolve();
})
);
};
cleanupS3Buckets().then(cleanupCFStacks);

5
tests/.eslintrc.js Normal file
View File

@ -0,0 +1,5 @@
module.exports = {
"parserOptions": {
"ecmaVersion": 2017,
}
};

View File

@ -0,0 +1,51 @@
'use strict';
async function minimal(event) {
return {
statusCode: 200,
body: JSON.stringify({
message: 'Hello from API Gateway! - (minimal)',
event,
}),
};
}
async function cors(event) {
return {
statusCode: 200,
headers: {
'Access-Control-Allow-Origin': '*',
},
body: JSON.stringify({
message: 'Hello from API Gateway! - (cors)',
event,
}),
};
}
async function customAuthorizers(event) {
return ({
statusCode: 200,
body: JSON.stringify({
message: 'Hello from API Gateway! - (customAuthorizers)',
event,
}),
});
}
async function apiKeys(event) {
return {
statusCode: 200,
body: JSON.stringify({
message: 'Hello from API Gateway! - (apiKeys)',
event,
}),
};
}
module.exports = {
minimal,
cors,
customAuthorizers,
apiKeys,
};

View File

@ -1,6 +1,7 @@
'use strict';
const generatePolicy = (principalId, effect, resource) => {
// custom authorizer
function generatePolicy(principalId, effect, resource) {
const authResponse = {};
authResponse.principalId = principalId;
@ -18,20 +19,18 @@ const generatePolicy = (principalId, effect, resource) => {
}
return authResponse;
};
}
// protected function
module.exports.hello = (event, context, callback) => {
callback(null, { message: 'Successfully authorized!', event });
};
// auth function
module.exports.auth = (event, context) => {
async function auth(event, context) {
const token = event.authorizationToken.split(' ');
if (token[0] === 'Bearer' && token[1] === 'ShouldBeAuthorized') {
context.succeed(generatePolicy('SomeRandomId', 'Allow', '*'));
return context.succeed(generatePolicy('SomeRandomId', 'Allow', '*'));
}
context.fail('Unauthorized');
return context.fail('Unauthorized');
}
module.exports = {
auth,
};

View File

@ -0,0 +1,62 @@
service: aws-nodejs # NOTE: update this with your service name
provider:
name: aws
runtime: nodejs10.x
versionFunctions: false
apiKeys:
- name: api-key-1
value: 0p3ns3s4m3-0p3ns3s4m3-0p3ns3s4m3
functions:
# core functions
minimal:
handler: core.minimal
events:
- http: GET /
- http:
method: POST
path: minimal-1
- http:
method: PUT
path: /minimal-2
- http:
method: DELETE
path: /minimal-3/
cors:
handler: core.cors
events:
- http:
method: GET
path: simple-cors
cors: true
- http:
method: GET
path: complex-cors
cors:
origin: '*'
headers:
- Content-Type
- X-Amz-Date
- Authorization
- X-Api-Key
- X-Amz-Security-Token
- X-Amz-User-Agent
allowCredentials: true
customAuthorizers:
handler: core.customAuthorizers
events:
- http:
path: custom-auth
method: GET
authorizer: authorizer
apiKeys:
handler: core.apiKeys
events:
- http:
path: api-keys
method: GET
private: true
# helper functions
authorizer:
handler: helper.auth

View File

@ -0,0 +1,267 @@
'use strict';
const path = require('path');
const AWS = require('aws-sdk');
const _ = require('lodash');
const fetch = require('node-fetch');
const { expect } = require('chai');
const { getTmpDirPath, readYamlFile, writeYamlFile } = require('../../utils/fs');
const { region, createTestService, deployService, removeService } = require('../../utils/misc');
const { createRestApi, deleteRestApi, getResources } = require('../../utils/api-gateway');
const CF = new AWS.CloudFormation({ region });
describe('AWS - API Gateway Integration Test', () => {
let serviceName;
let endpoint;
let StackName;
let tmpDirPath;
let serverlessFilePath;
let restApiId;
let restApiRootResourceId;
const stage = 'dev';
beforeAll(() => {
tmpDirPath = getTmpDirPath();
serverlessFilePath = path.join(tmpDirPath, 'serverless.yml');
serviceName = createTestService('aws-nodejs', tmpDirPath, path.join(__dirname, 'service'));
StackName = `${serviceName}-${stage}`;
deployService();
// create an external REST API
const externalRestApiName = `${stage}-${serviceName}-ext-api`;
return createRestApi(externalRestApiName)
.then((restApiMeta) => {
restApiId = restApiMeta.id;
return getResources(restApiId);
})
.then((resources) => {
restApiRootResourceId = resources[0].id;
});
});
afterAll(() => {
// NOTE: deleting the references to the old, external REST API
const serverless = readYamlFile(serverlessFilePath);
delete serverless.provider.apiGateway.restApiId;
delete serverless.provider.apiGateway.restApiRootResourceId;
writeYamlFile(serverlessFilePath, serverless);
// NOTE: deploying once again to get the stack into the original state
deployService();
removeService();
return deleteRestApi(restApiId);
});
beforeEach(() => {
return CF.describeStacks({ StackName }).promise()
.then((result) => _.find(result.Stacks[0].Outputs,
{ OutputKey: 'ServiceEndpoint' }).OutputValue)
.then((endpointOutput) => {
endpoint = endpointOutput.match(/https:\/\/.+\.execute-api\..+\.amazonaws\.com.+/)[0];
endpoint = `${endpoint}`;
});
});
describe('Minimal Setup', () => {
const expectedMessage = 'Hello from API Gateway! - (minimal)';
it('should expose an accessible GET HTTP endpoint', () => {
const testEndpoint = `${endpoint}`;
return fetch(testEndpoint, { method: 'GET' })
.then(response => response.json())
.then((json) => expect(json.message).to.equal(expectedMessage));
});
it('should expose an accessible POST HTTP endpoint', () => {
const testEndpoint = `${endpoint}/minimal-1`;
return fetch(testEndpoint, { method: 'POST' })
.then(response => response.json())
.then((json) => expect(json.message).to.equal(expectedMessage));
});
it('should expose an accessible PUT HTTP endpoint', () => {
const testEndpoint = `${endpoint}/minimal-2`;
return fetch(testEndpoint, { method: 'PUT' })
.then(response => response.json())
.then((json) => expect(json.message).to.equal(expectedMessage));
});
it('should expose an accessible DELETE HTTP endpoint', () => {
const testEndpoint = `${endpoint}/minimal-3`;
return fetch(testEndpoint, { method: 'DELETE' })
.then(response => response.json())
.then((json) => expect(json.message).to.equal(expectedMessage));
});
});
describe('CORS', () => {
it('should setup simple CORS support via cors: true config', () => {
const testEndpoint = `${endpoint}/simple-cors`;
return fetch(testEndpoint, { method: 'OPTIONS' })
.then((response) => {
const headers = response.headers;
const allowHeaders = [
'Content-Type',
'X-Amz-Date',
'Authorization',
'X-Api-Key',
'X-Amz-Security-Token',
'X-Amz-User-Agent',
].join(',');
expect(headers.get('access-control-allow-headers')).to.equal(allowHeaders);
expect(headers.get('access-control-allow-methods')).to.equal('OPTIONS,GET');
expect(headers.get('access-control-allow-credentials')).to.equal('false');
// TODO: for some reason this test fails for now...
// expect(headers.get('access-control-allow-origin')).to.equal('*');
});
});
it('should setup CORS support with complex object config', () => {
const testEndpoint = `${endpoint}/complex-cors`;
return fetch(testEndpoint, { method: 'OPTIONS' })
.then((response) => {
const headers = response.headers;
const allowHeaders = [
'Content-Type',
'X-Amz-Date',
'Authorization',
'X-Api-Key',
'X-Amz-Security-Token',
'X-Amz-User-Agent',
].join(',');
expect(headers.get('access-control-allow-headers')).to.equal(allowHeaders);
expect(headers.get('access-control-allow-methods')).to.equal('OPTIONS,GET');
expect(headers.get('access-control-allow-credentials')).to.equal('true');
expect(headers.get('access-control-allow-origin')).to.equal('*');
});
});
});
describe('Custom Authorizers', () => {
let testEndpoint;
beforeEach(() => {
testEndpoint = `${endpoint}/custom-auth`;
});
it('should reject requests without authorization', () => {
return fetch(testEndpoint)
.then((response) => {
expect(response.status).to.equal(401);
});
});
it('should reject requests with wrong authorization', () => {
return fetch(testEndpoint, { headers: { Authorization: 'Bearer ShouldNotBeAuthorized' } })
.then((response) => {
expect(response.status).to.equal(401);
});
});
it('should authorize requests with correct authorization', () => {
return fetch(testEndpoint, { headers: { Authorization: 'Bearer ShouldBeAuthorized' } })
.then(response => response.json())
.then((json) => {
expect(json.message).to.equal('Hello from API Gateway! - (customAuthorizers)');
expect(json.event.requestContext.authorizer.principalId).to.equal('SomeRandomId');
expect(json.event.headers.Authorization).to.equal('Bearer ShouldBeAuthorized');
});
});
});
describe('API Keys', () => {
let testEndpoint;
beforeEach(() => {
testEndpoint = `${endpoint}/api-keys`;
});
it('should reject a request with an invalid API Key', () => {
return fetch(testEndpoint)
.then((response) => {
expect(response.status).to.equal(403);
});
});
it('should succeed if correct API key is given', () => {
const apiKey = '0p3ns3s4m3-0p3ns3s4m3-0p3ns3s4m3';
return fetch(testEndpoint, { headers: { 'X-API-Key': apiKey } })
.then(response => response.json())
.then((json) => {
expect(json.message).to.equal('Hello from API Gateway! - (apiKeys)');
});
});
});
describe('Using stage specific configuration', () => {
beforeAll(() => {
const serverless = readYamlFile(serverlessFilePath);
// enable Logs, Tags and Tracing
_.merge(serverless.provider, {
tags: {
foo: 'bar',
baz: 'qux',
},
tracing: {
apiGateway: true,
},
logs: {
restApi: true,
},
});
writeYamlFile(serverlessFilePath, serverless);
deployService();
});
it('should update the stage without service interruptions', () => {
// re-using the endpoint from the "minimal" test case
const testEndpoint = `${endpoint}`;
return fetch(testEndpoint, { method: 'GET' })
.then(response => response.json())
.then((json) => expect(json.message).to.equal('Hello from API Gateway! - (minimal)'));
});
});
// NOTE: this test should be at the very end because we're using an external REST API here
describe('when using an existing REST API with stage specific configuration', () => {
beforeAll(() => {
const serverless = readYamlFile(serverlessFilePath);
// enable Logs, Tags and Tracing
_.merge(serverless.provider, {
apiGateway: {
restApiId,
restApiRootResourceId,
},
tags: {
foo: 'bar',
baz: 'qux',
},
tracing: {
apiGateway: true,
},
logs: {
restApi: true,
},
});
writeYamlFile(serverlessFilePath, serverless);
deployService();
});
it('should update the stage without service interruptions', () => {
// re-using the endpoint from the "minimal" test case
const testEndpoint = `${endpoint}/minimal-1`;
return fetch(testEndpoint, { method: 'POST' })
.then(response => response.json())
.then((json) => expect(json.message).to.equal('Hello from API Gateway! - (minimal)'));
});
});
});

View File

@ -1,45 +1,55 @@
'use strict';
const fs = require('fs');
const expect = require('chai').expect;
const path = require('path');
const fs = require('fs');
const fse = require('fs-extra');
const BbPromise = require('bluebird');
const execSync = require('child_process').execSync;
const AWS = require('aws-sdk');
const testUtils = require('../utils/index');
const { expect } = require('chai');
const { execSync } = require('child_process');
const { getTmpDirPath, replaceTextInFile } = require('../utils/fs');
const { region, getServiceName } = require('../utils/misc');
const serverlessExec = path.join(__dirname, '..', '..', 'bin', 'serverless');
const tmpDir = testUtils.getTmpDirPath();
fse.mkdirsSync(tmpDir);
process.chdir(tmpDir);
const templateName = 'aws-nodejs';
const newServiceName = `service-${(new Date()).getTime().toString()}`;
const stackName = `${newServiceName}-dev`;
const CF = new AWS.CloudFormation({ region: 'us-east-1' });
BbPromise.promisifyAll(CF, { suffix: 'Promised' });
const CF = new AWS.CloudFormation({ region });
describe('Service Lifecyle Integration Test', () => {
const templateName = 'aws-nodejs';
const tmpDir = getTmpDirPath();
let oldCwd;
let serviceName;
let StackName;
beforeAll(() => {
oldCwd = process.cwd();
serviceName = getServiceName();
StackName = `${serviceName}-dev`;
fse.mkdirsSync(tmpDir);
process.chdir(tmpDir);
});
afterAll(() => {
process.chdir(oldCwd);
});
it('should create service in tmp directory', () => {
execSync(`${serverlessExec} create --template ${templateName}`, { stdio: 'inherit' });
testUtils.replaceTextInFile('serverless.yml', templateName, newServiceName);
execSync(`${serverlessExec} create --template ${templateName}`);
replaceTextInFile('serverless.yml', templateName, serviceName);
expect(fs.existsSync(path.join(tmpDir, 'serverless.yml'))).to.be.equal(true);
expect(fs.existsSync(path.join(tmpDir, 'handler.js'))).to.be.equal(true);
});
it('should deploy service to aws', () => {
execSync(`${serverlessExec} deploy`, { stdio: 'inherit' });
execSync(`${serverlessExec} deploy`);
return CF.describeStacksPromised({ StackName: stackName })
return CF.describeStacks({ StackName }).promise()
.then(d => expect(d.Stacks[0].StackStatus).to.be.equal('UPDATE_COMPLETE'));
});
it('should invoke function from aws', () => {
const invoked = execSync(`${serverlessExec} invoke --function hello --noGreeting true`);
const result = JSON.parse(new Buffer(invoked, 'base64').toString());
const result = JSON.parse(Buffer.from(invoked, 'base64').toString());
// parse it once again because the body is stringified to be LAMBDA-PROXY ready
const message = JSON.parse(result.body).message;
expect(message).to.be.equal('Go Serverless v1.0! Your function executed successfully!');
@ -56,12 +66,12 @@ describe('Service Lifecyle Integration Test', () => {
`;
fs.writeFileSync(path.join(tmpDir, 'handler.js'), newHandler);
execSync(`${serverlessExec} deploy`, { stdio: 'inherit' });
execSync(`${serverlessExec} deploy`);
});
it('should invoke updated function from aws', () => {
const invoked = execSync(`${serverlessExec} invoke --function hello --noGreeting true`);
const result = JSON.parse(new Buffer(invoked, 'base64').toString());
const result = JSON.parse(Buffer.from(invoked, 'base64').toString());
expect(result.message).to.be.equal('Service Update Succeeded');
});
@ -79,16 +89,16 @@ describe('Service Lifecyle Integration Test', () => {
execSync(`${serverlessExec} rollback -t ${timestamp}`);
const invoked = execSync(`${serverlessExec} invoke --function hello --noGreeting true`);
const result = JSON.parse(new Buffer(invoked, 'base64').toString());
const result = JSON.parse(Buffer.from(invoked, 'base64').toString());
// parse it once again because the body is stringified to be LAMBDA-PROXY ready
const message = JSON.parse(result.body).message;
expect(message).to.be.equal('Go Serverless v1.0! Your function executed successfully!');
});
it('should remove service from aws', () => {
execSync(`${serverlessExec} remove`, { stdio: 'inherit' });
execSync(`${serverlessExec} remove`);
return CF.describeStacksPromised({ StackName: stackName })
return CF.describeStacks({ StackName }).promise()
.then(d => expect(d.Stacks[0].StackStatus).to.be.equal('DELETE_COMPLETE'))
.catch(error => {
if (error.message.indexOf('does not exist') > -1) return BbPromise.resolve();

View File

@ -2,16 +2,15 @@
const fs = require('fs');
const path = require('path');
const execSync = require('child_process').execSync;
const fse = require('fs-extra');
const testUtils = require('../utils/index');
const serverlessExec = path.join(__dirname, '..', '..', 'bin', 'serverless');
const { execSync } = require('child_process');
const { serverlessExec } = require('../utils/misc');
const { getTmpDirPath, listZipFiles } = require('../utils/fs');
describe('Integration test - Packaging', () => {
let cwd;
beforeEach(() => {
cwd = testUtils.getTmpDirPath();
cwd = getTmpDirPath();
fse.mkdirsSync(cwd);
});
@ -19,7 +18,7 @@ describe('Integration test - Packaging', () => {
fse.copySync(path.join(__dirname, 'serverless.yml'), path.join(cwd, 'serverless.yml'));
fse.copySync(path.join(__dirname, 'handler.js'), path.join(cwd, 'handler.js'));
execSync(`${serverlessExec} package`, { cwd });
return testUtils.listZipFiles(path.join(cwd, '.serverless/aws-nodejs.zip'))
return listZipFiles(path.join(cwd, '.serverless/aws-nodejs.zip'))
.then(zipfiles => {
expect(zipfiles).toEqual(['handler.js']);
});
@ -31,7 +30,7 @@ describe('Integration test - Packaging', () => {
execSync('npm init --yes', { cwd });
execSync('npm i lodash', { cwd });
execSync(`${serverlessExec} package`, { cwd });
return testUtils.listZipFiles(path.join(cwd, '.serverless/aws-nodejs.zip'))
return listZipFiles(path.join(cwd, '.serverless/aws-nodejs.zip'))
.then(zipfiles => {
const nodeModules = new Set(
zipfiles.filter(f => f.startsWith('node_modules')).map(f => f.split(path.sep)[1]));
@ -47,7 +46,7 @@ describe('Integration test - Packaging', () => {
execSync('npm init --yes', { cwd });
execSync('npm i --save-dev lodash', { cwd });
execSync(`${serverlessExec} package`, { cwd });
return testUtils.listZipFiles(path.join(cwd, '.serverless/aws-nodejs.zip'))
return listZipFiles(path.join(cwd, '.serverless/aws-nodejs.zip'))
.then(zipfiles => {
const nodeModules = new Set(
zipfiles.filter(f => f.startsWith('node_modules')).map(f => f.split(path.sep)[1]));
@ -64,7 +63,7 @@ describe('Integration test - Packaging', () => {
execSync('echo \'package: {exclude: ["package*.json"]}\' >> serverless.yml', { cwd });
execSync('npm i lodash', { cwd });
execSync(`${serverlessExec} package`, { cwd });
return testUtils.listZipFiles(path.join(cwd, '.serverless/aws-nodejs.zip'))
return listZipFiles(path.join(cwd, '.serverless/aws-nodejs.zip'))
.then(zipfiles => {
const nodeModules = new Set(
zipfiles.filter(f => f.startsWith('node_modules')).map(f => f.split(path.sep)[1]));
@ -145,7 +144,7 @@ describe('Integration test - Packaging', () => {
'IamRoleLambdaExecution',
],
});
return testUtils.listZipFiles(path.join(cwd, '.serverless/aws-nodejs.zip'))
return listZipFiles(path.join(cwd, '.serverless/aws-nodejs.zip'))
.then(zipfiles => {
expect(zipfiles).toEqual(['handler.js']);
});
@ -188,9 +187,9 @@ describe('Integration test - Packaging', () => {
'IamRoleLambdaExecution',
],
});
return testUtils.listZipFiles(path.join(cwd, '.serverless/hello.zip'))
return listZipFiles(path.join(cwd, '.serverless/hello.zip'))
.then(zipfiles => expect(zipfiles).toEqual(['handler.js']))
.then(() => testUtils.listZipFiles(path.join(cwd, '.serverless/hello2.zip')))
.then(() => listZipFiles(path.join(cwd, '.serverless/hello2.zip')))
.then(zipfiles => expect(zipfiles).toEqual(['handler2.js']));
});
});

View File

@ -1,13 +0,0 @@
'use strict';
module.exports.hello = (event, context, callback) => {
const response = {
statusCode: 200,
body: JSON.stringify({
message: 'Hello from API Gateway!',
event,
}),
};
callback(null, response);
};

View File

@ -1,16 +0,0 @@
service: aws-nodejs # NOTE: update this with your service name
provider:
name: aws
runtime: nodejs10.x
apiKeys:
- WillBeReplacedBeforeDeployment
functions:
hello:
handler: handler.hello
events:
- http:
path: hello
method: GET
private: true

View File

@ -1,83 +0,0 @@
'use strict';
const path = require('path');
const expect = require('chai').expect;
const BbPromise = require('bluebird');
const execSync = require('child_process').execSync;
const AWS = require('aws-sdk');
const _ = require('lodash');
const fetch = require('node-fetch');
const fse = require('fs-extra');
const crypto = require('crypto');
const Utils = require('../../../../../utils/index');
const CF = new AWS.CloudFormation({ region: 'us-east-1' });
const APIG = new AWS.APIGateway({ region: 'us-east-1' });
BbPromise.promisifyAll(CF, { suffix: 'Promised' });
BbPromise.promisifyAll(APIG, { suffix: 'Promised' });
describe('AWS - API Gateway (Integration: Lambda Proxy): API keys test', () => {
let stackName;
let endpoint;
let apiKey;
beforeAll(() => {
stackName = Utils.createTestService('aws-nodejs', path.join(__dirname, 'service'));
// replace name of the API key with something unique
const serverlessYmlFilePath = path.join(process.cwd(), 'serverless.yml');
let serverlessYmlFileContent = fse.readFileSync(serverlessYmlFilePath).toString();
const apiKeyName = crypto.randomBytes(8).toString('hex');
serverlessYmlFileContent = serverlessYmlFileContent
.replace(/WillBeReplacedBeforeDeployment/, apiKeyName);
fse.writeFileSync(serverlessYmlFilePath, serverlessYmlFileContent);
Utils.deployService();
});
beforeAll(() => {
const info = execSync(`${Utils.serverlessExec} info`);
const stringifiedOutput = (new Buffer(info, 'base64').toString());
// some regex magic to extract the first API key value from the info output
apiKey = stringifiedOutput.match(/(api keys:\n)(\s*)(.+):(\s*)(.+)/)[5];
});
it('should expose the endpoint(s) in the CloudFormation Outputs', () =>
CF.describeStacksPromised({ StackName: stackName })
.then((result) => _.find(result.Stacks[0].Outputs,
{ OutputKey: 'ServiceEndpoint' }).OutputValue)
.then((endpointOutput) => {
const matched = endpointOutput.match(/https:\/\/.+\.execute-api\..+\.amazonaws\.com.+/)[0];
endpoint = `${matched}/hello`;
})
);
it('should expose the API key(s) with its values when running the info command', () => {
expect(apiKey.length).to.be.above(0);
});
it('should reject a request with an invalid API Key', () =>
fetch(endpoint)
.then((response) => {
expect(response.status).to.equal(403);
})
);
it('should succeed if correct API key is given', () =>
fetch(endpoint, { headers: { 'x-api-key': apiKey } })
.then(response => response.json())
.then((json) => {
expect(json.message).to.equal('Hello from API Gateway!');
expect(json.event.requestContext.identity.apiKey).to.equal(apiKey);
expect(json.event.headers['x-api-key']).to.equal(apiKey);
})
);
afterAll(() => {
Utils.removeService();
});
});

View File

@ -1,16 +0,0 @@
'use strict';
module.exports.hello = (event, context, callback) => {
const response = {
statusCode: 200,
headers: {
'Access-Control-Allow-Origin': '*',
},
body: JSON.stringify({
message: 'Hello from API Gateway!',
input: event,
}),
};
callback(null, response);
};

View File

@ -1,27 +0,0 @@
service: aws-nodejs # NOTE: update this with your service name
provider:
name: aws
runtime: nodejs10.x
functions:
hello:
handler: handler.hello
events:
- http:
method: GET
path: simple-cors
cors: true
- http:
method: GET
path: complex-cors
cors:
origins:
- '*'
headers:
- Content-Type
- X-Amz-Date
- Authorization
- X-Api-Key
- X-Amz-Security-Token
- X-Amz-User-Agent

View File

@ -1,62 +0,0 @@
'use strict';
const path = require('path');
const expect = require('chai').expect;
const BbPromise = require('bluebird');
const AWS = require('aws-sdk');
const _ = require('lodash');
const fetch = require('node-fetch');
const Utils = require('../../../../../utils/index');
const CF = new AWS.CloudFormation({ region: 'us-east-1' });
BbPromise.promisifyAll(CF, { suffix: 'Promised' });
describe('AWS - API Gateway (Integration: Lambda Proxy): CORS test', () => {
let stackName;
let endpointBase;
beforeAll(() => {
stackName = Utils.createTestService('aws-nodejs', path.join(__dirname, 'service'));
Utils.deployService();
});
it('should expose the endpoint(s) in the CloudFormation Outputs', () =>
CF.describeStacksPromised({ StackName: stackName })
.then((result) => _.find(result.Stacks[0].Outputs,
{ OutputKey: 'ServiceEndpoint' }).OutputValue)
.then((endpointOutput) => {
endpointBase = endpointOutput.match(/https:\/\/.+\.execute-api\..+\.amazonaws\.com.+/)[0];
})
);
it('should setup CORS support with simple string config', () =>
fetch(`${endpointBase}/simple-cors`, { method: 'OPTIONS' })
.then((response) => {
const headers = response.headers;
expect(headers.get('access-control-allow-headers'))
.to.equal('Content-Type,X-Amz-Date,Authorization,X-Api-Key,'
+ 'X-Amz-Security-Token,X-Amz-User-Agent');
expect(headers.get('access-control-allow-methods')).to.equal('OPTIONS,GET');
expect(headers.get('access-control-allow-origin')).to.equal('*');
})
);
it('should setup CORS support with complex object config', () =>
fetch(`${endpointBase}/complex-cors`, { method: 'OPTIONS' })
.then((response) => {
const headers = response.headers;
expect(headers.get('access-control-allow-headers'))
.to.equal('Content-Type,X-Amz-Date,Authorization,X-Api-Key,'
+ 'X-Amz-Security-Token,X-Amz-User-Agent');
expect(headers.get('access-control-allow-methods')).to.equal('OPTIONS,GET');
expect(headers.get('access-control-allow-origin')).to.equal('*');
})
);
afterAll(() => {
Utils.removeService();
});
});

View File

@ -1,45 +0,0 @@
'use strict';
const generatePolicy = (principalId, effect, resource) => {
const authResponse = {};
authResponse.principalId = principalId;
if (effect && resource) {
const policyDocument = {};
policyDocument.Version = '2012-10-17';
policyDocument.Statement = [];
const statementOne = {};
statementOne.Action = 'execute-api:Invoke';
statementOne.Effect = effect;
statementOne.Resource = resource;
policyDocument.Statement[0] = statementOne;
authResponse.policyDocument = policyDocument;
}
return authResponse;
};
// protected function
module.exports.hello = (event, context, callback) => {
const response = {
statusCode: 200,
body: JSON.stringify({
message: 'Successfully authorized!',
event,
}),
};
callback(null, response);
};
// auth function
module.exports.auth = (event, context) => {
const token = event.authorizationToken.split(' ');
if (token[0] === 'Bearer' && token[1] === 'ShouldBeAuthorized') {
context.succeed(generatePolicy('SomeRandomId', 'Allow', '*'));
}
context.fail('Unauthorized');
};

View File

@ -1,16 +0,0 @@
service: aws-nodejs # NOTE: update this with your service name
provider:
name: aws
runtime: nodejs10.x
functions:
hello:
handler: handler.hello
events:
- http:
path: hello
method: GET
authorizer: auth
auth:
handler: handler.auth

View File

@ -1,62 +0,0 @@
'use strict';
const path = require('path');
const expect = require('chai').expect;
const BbPromise = require('bluebird');
const AWS = require('aws-sdk');
const _ = require('lodash');
const fetch = require('node-fetch');
const Utils = require('../../../../../utils/index');
const CF = new AWS.CloudFormation({ region: 'us-east-1' });
BbPromise.promisifyAll(CF, { suffix: 'Promised' });
describe('AWS - API Gateway (Integration: Lambda Proxy): Custom authorizers test', () => {
let stackName;
let endpoint;
beforeAll(() => {
stackName = Utils.createTestService('aws-nodejs', path.join(__dirname, 'service'));
Utils.deployService();
});
it('should expose the endpoint(s) in the CloudFormation Outputs', () =>
CF.describeStacksPromised({ StackName: stackName })
.then((result) => _.find(result.Stacks[0].Outputs,
{ OutputKey: 'ServiceEndpoint' }).OutputValue)
.then((endpointOutput) => {
endpoint = endpointOutput.match(/https:\/\/.+\.execute-api\..+\.amazonaws\.com.+/)[0];
endpoint = `${endpoint}/hello`;
})
);
it('should reject requests without authorization', () =>
fetch(endpoint)
.then((response) => {
expect(response.status).to.equal(401);
})
);
it('should reject requests with wrong authorization', () =>
fetch(endpoint, { headers: { Authorization: 'Bearer ShouldNotBeAuthorized' } })
.then((response) => {
expect(response.status).to.equal(401);
})
);
it('should authorize requests with correct authorization', () =>
fetch(endpoint, { headers: { Authorization: 'Bearer ShouldBeAuthorized' } })
.then(response => response.json())
.then((json) => {
expect(json.message).to.equal('Successfully authorized!');
expect(json.event.requestContext.authorizer.principalId).to.equal('SomeRandomId');
expect(json.event.headers.Authorization).to.equal('Bearer ShouldBeAuthorized');
})
);
afterAll(() => {
Utils.removeService();
});
});

View File

@ -1,13 +0,0 @@
'use strict';
module.exports.hello = (event, context, callback) => {
const response = {
statusCode: 200,
body: JSON.stringify({
message: 'Hello from API Gateway!',
input: event,
}),
};
callback(null, response);
};

View File

@ -1,37 +0,0 @@
service: aws-nodejs # NOTE: update this with your service name
provider:
name: aws
runtime: nodejs10.x
functions:
hello:
handler: handler.hello
events:
# paths without a slash
- http: POST without-slash
- http: GET without-slash
- http:
method: PUT
path: without-slash
- http:
method: DELETE
path: without-slash
# paths with a slash
- http: POST /with-slash
- http: GET /with-slash
- http:
method: PUT
path: /with-slash
- http:
method: DELETE
path: /with-slash
# root only paths
- http: POST /
- http: GET /
- http:
method: PUT
path: /
- http:
method: DELETE
path: /

View File

@ -1,139 +0,0 @@
'use strict';
const path = require('path');
const expect = require('chai').expect;
const BbPromise = require('bluebird');
const AWS = require('aws-sdk');
const _ = require('lodash');
const fetch = require('node-fetch');
const Utils = require('../../../../../utils/index');
const CF = new AWS.CloudFormation({ region: 'us-east-1' });
BbPromise.promisifyAll(CF, { suffix: 'Promised' });
describe('AWS - API Gateway (Integration: Lambda Proxy): Simple API test', () => {
let stackName;
let endpoint;
beforeAll(() => {
stackName = Utils.createTestService('aws-nodejs', path.join(__dirname, 'service'));
Utils.deployService();
});
it('should expose the endpoint(s) in the CloudFormation Outputs', () =>
CF.describeStacksPromised({ StackName: stackName })
.then((result) => _.find(result.Stacks[0].Outputs,
{ OutputKey: 'ServiceEndpoint' }).OutputValue)
.then((endpointOutput) => {
endpoint = endpointOutput.match(/https:\/\/.+\.execute-api\..+\.amazonaws\.com.+/)[0];
endpoint = `${endpoint}`;
})
);
describe('when having a "without-slash" path setup', () => {
it('should expose an accessible POST HTTP endpoint', () => {
const testEndpoint = `${endpoint}/without-slash`;
return fetch(testEndpoint, { method: 'POST' })
.then(response => response.json())
.then((json) => expect(json.message).to.equal('Hello from API Gateway!'));
});
it('should expose an accessible GET HTTP endpoint', () => {
const testEndpoint = `${endpoint}/without-slash`;
return fetch(testEndpoint)
.then(response => response.json())
.then((json) => expect(json.message).to.equal('Hello from API Gateway!'));
});
it('should expose an accessible PUT HTTP endpoint', () => {
const testEndpoint = `${endpoint}/without-slash`;
return fetch(testEndpoint, { method: 'PUT' })
.then(response => response.json())
.then((json) => expect(json.message).to.equal('Hello from API Gateway!'));
});
it('should expose an accessible DELETE HTTP endpoint', () => {
const testEndpoint = `${endpoint}/without-slash`;
return fetch(testEndpoint, { method: 'DELETE' })
.then(response => response.json())
.then((json) => expect(json.message).to.equal('Hello from API Gateway!'));
});
});
describe('when having a "/with-slash" path setup', () => {
it('should expose an accessible POST HTTP endpoint', () => {
const testEndpoint = `${endpoint}/with-slash`;
return fetch(testEndpoint, { method: 'POST' })
.then(response => response.json())
.then((json) => expect(json.message).to.equal('Hello from API Gateway!'));
});
it('should expose an accessible GET HTTP endpoint', () => {
const testEndpoint = `${endpoint}/with-slash`;
return fetch(testEndpoint)
.then(response => response.json())
.then((json) => expect(json.message).to.equal('Hello from API Gateway!'));
});
it('should expose an accessible PUT HTTP endpoint', () => {
const testEndpoint = `${endpoint}/with-slash`;
return fetch(testEndpoint, { method: 'PUT' })
.then(response => response.json())
.then((json) => expect(json.message).to.equal('Hello from API Gateway!'));
});
it('should expose an accessible DELETE HTTP endpoint', () => {
const testEndpoint = `${endpoint}/with-slash`;
return fetch(testEndpoint, { method: 'DELETE' })
.then(response => response.json())
.then((json) => expect(json.message).to.equal('Hello from API Gateway!'));
});
});
describe('when having a "/" path setup', () => {
it('should expose an accessible POST HTTP endpoint', () => {
const testEndpoint = `${endpoint}`;
return fetch(testEndpoint, { method: 'POST' })
.then(response => response.json())
.then((json) => expect(json.message).to.equal('Hello from API Gateway!'));
});
it('should expose an accessible GET HTTP endpoint', () => {
const testEndpoint = `${endpoint}`;
return fetch(testEndpoint)
.then(response => response.json())
.then((json) => expect(json.message).to.equal('Hello from API Gateway!'));
});
it('should expose an accessible PUT HTTP endpoint', () => {
const testEndpoint = `${endpoint}`;
return fetch(testEndpoint, { method: 'PUT' })
.then(response => response.json())
.then((json) => expect(json.message).to.equal('Hello from API Gateway!'));
});
it('should expose an accessible DELETE HTTP endpoint', () => {
const testEndpoint = `${endpoint}`;
return fetch(testEndpoint, { method: 'DELETE' })
.then(response => response.json())
.then((json) => expect(json.message).to.equal('Hello from API Gateway!'));
});
});
afterAll(() => {
Utils.removeService();
});
});

View File

@ -1,5 +0,0 @@
'use strict';
module.exports.hello = (event, context, callback) => {
callback(null, { message: 'Hello from API Gateway!', event });
};

View File

@ -1,17 +0,0 @@
service: aws-nodejs # NOTE: update this with your service name
provider:
name: aws
runtime: nodejs10.x
apiKeys:
- WillBeReplacedBeforeDeployment
functions:
hello:
handler: handler.hello
events:
- http:
path: hello
method: GET
integration: lambda
private: true

View File

@ -1,83 +0,0 @@
'use strict';
const path = require('path');
const expect = require('chai').expect;
const BbPromise = require('bluebird');
const execSync = require('child_process').execSync;
const AWS = require('aws-sdk');
const _ = require('lodash');
const fetch = require('node-fetch');
const fse = require('fs-extra');
const crypto = require('crypto');
const Utils = require('../../../../../utils/index');
const CF = new AWS.CloudFormation({ region: 'us-east-1' });
const APIG = new AWS.APIGateway({ region: 'us-east-1' });
BbPromise.promisifyAll(CF, { suffix: 'Promised' });
BbPromise.promisifyAll(APIG, { suffix: 'Promised' });
describe('AWS - API Gateway (Integration: Lambda): API keys test', () => {
let stackName;
let endpoint;
let apiKey;
beforeAll(() => {
stackName = Utils.createTestService('aws-nodejs', path.join(__dirname, 'service'));
// replace name of the API key with something unique
const serverlessYmlFilePath = path.join(process.cwd(), 'serverless.yml');
let serverlessYmlFileContent = fse.readFileSync(serverlessYmlFilePath).toString();
const apiKeyName = crypto.randomBytes(8).toString('hex');
serverlessYmlFileContent = serverlessYmlFileContent
.replace(/WillBeReplacedBeforeDeployment/, apiKeyName);
fse.writeFileSync(serverlessYmlFilePath, serverlessYmlFileContent);
Utils.deployService();
});
it('should expose the endpoint(s) in the CloudFormation Outputs', () =>
CF.describeStacksPromised({ StackName: stackName })
.then((result) => _.find(result.Stacks[0].Outputs,
{ OutputKey: 'ServiceEndpoint' }).OutputValue)
.then((endpointOutput) => {
endpoint = endpointOutput.match(/https:\/\/.+\.execute-api\..+\.amazonaws\.com.+/)[0];
endpoint = `${endpoint}/hello`;
})
);
it('should expose the API key(s) with its values when running the info command', () => {
const info = execSync(`${Utils.serverlessExec} info`);
const stringifiedOutput = (new Buffer(info, 'base64').toString());
// some regex magic to extract the first API key value from the info output
apiKey = stringifiedOutput.match(/(api keys:\n)(\s*)(.+):(\s*)(.+)/)[5];
expect(apiKey.length).to.be.above(0);
});
it('should reject a request with an invalid API Key', () =>
fetch(endpoint)
.then((response) => {
expect(response.status).to.equal(403);
})
);
it('should succeed if correct API key is given', () =>
fetch(endpoint, { headers: { 'x-api-key': apiKey } })
.then(response => response.json())
.then((json) => {
expect(json.message).to.equal('Hello from API Gateway!');
expect(json.event.identity.apiKey).to.equal(apiKey);
expect(json.event.headers['x-api-key']).to.equal(apiKey);
})
);
afterAll(() => {
Utils.removeService();
});
});

View File

@ -1,5 +0,0 @@
'use strict';
module.exports.hello = (event, context, callback) => {
callback(null, { message: 'Hello from API Gateway!', event });
};

View File

@ -1,29 +0,0 @@
service: aws-nodejs # NOTE: update this with your service name
provider:
name: aws
runtime: nodejs10.x
functions:
hello:
handler: handler.hello
events:
- http:
method: GET
path: simple-cors
integration: lambda
cors: true
- http:
method: GET
path: complex-cors
integration: lambda
cors:
origins:
- '*'
headers:
- Content-Type
- X-Amz-Date
- Authorization
- X-Api-Key
- X-Amz-Security-Token
- X-Amz-User-Agent

View File

@ -1,62 +0,0 @@
'use strict';
const path = require('path');
const expect = require('chai').expect;
const BbPromise = require('bluebird');
const AWS = require('aws-sdk');
const _ = require('lodash');
const fetch = require('node-fetch');
const Utils = require('../../../../../utils/index');
const CF = new AWS.CloudFormation({ region: 'us-east-1' });
BbPromise.promisifyAll(CF, { suffix: 'Promised' });
describe('AWS - API Gateway (Integration: Lambda): CORS test', () => {
let stackName;
let endpointBase;
beforeAll(() => {
stackName = Utils.createTestService('aws-nodejs', path.join(__dirname, 'service'));
Utils.deployService();
});
it('should expose the endpoint(s) in the CloudFormation Outputs', () =>
CF.describeStacksPromised({ StackName: stackName })
.then((result) => _.find(result.Stacks[0].Outputs,
{ OutputKey: 'ServiceEndpoint' }).OutputValue)
.then((endpointOutput) => {
endpointBase = endpointOutput.match(/https:\/\/.+\.execute-api\..+\.amazonaws\.com.+/)[0];
})
);
it('should setup CORS support with simple string config', () =>
fetch(`${endpointBase}/simple-cors`, { method: 'OPTIONS' })
.then((response) => {
const headers = response.headers;
expect(headers.get('access-control-allow-headers'))
.to.equal('Content-Type,X-Amz-Date,Authorization,X-Api-Key,'
+ 'X-Amz-Security-Token,X-Amz-User-Agent');
expect(headers.get('access-control-allow-methods')).to.equal('OPTIONS,GET');
expect(headers.get('access-control-allow-origin')).to.equal('*');
})
);
it('should setup CORS support with complex object config', () =>
fetch(`${endpointBase}/complex-cors`, { method: 'OPTIONS' })
.then((response) => {
const headers = response.headers;
expect(headers.get('access-control-allow-headers'))
.to.equal('Content-Type,X-Amz-Date,Authorization,X-Api-Key,'
+ 'X-Amz-Security-Token,X-Amz-User-Agent');
expect(headers.get('access-control-allow-methods')).to.equal('OPTIONS,GET');
expect(headers.get('access-control-allow-origin')).to.equal('*');
})
);
afterAll(() => {
Utils.removeService();
});
});

View File

@ -1,17 +0,0 @@
service: aws-nodejs # NOTE: update this with your service name
provider:
name: aws
runtime: nodejs10.x
functions:
hello:
handler: handler.hello
events:
- http:
path: hello
method: GET
integration: lambda
authorizer: auth
auth:
handler: handler.auth

View File

@ -1,61 +0,0 @@
'use strict';
const path = require('path');
const expect = require('chai').expect;
const BbPromise = require('bluebird');
const AWS = require('aws-sdk');
const _ = require('lodash');
const fetch = require('node-fetch');
const Utils = require('../../../../../utils/index');
const CF = new AWS.CloudFormation({ region: 'us-east-1' });
BbPromise.promisifyAll(CF, { suffix: 'Promised' });
describe('AWS - API Gateway (Integration: Lambda): Custom authorizers test', () => {
let stackName;
let endpoint;
beforeAll(() => {
stackName = Utils.createTestService('aws-nodejs', path.join(__dirname, 'service'));
Utils.deployService();
});
it('should expose the endpoint(s) in the CloudFormation Outputs', () =>
CF.describeStacksPromised({ StackName: stackName })
.then((result) => _.find(result.Stacks[0].Outputs,
{ OutputKey: 'ServiceEndpoint' }).OutputValue)
.then((endpointOutput) => {
endpoint = endpointOutput.match(/https:\/\/.+\.execute-api\..+\.amazonaws\.com.+/)[0];
endpoint = `${endpoint}/hello`;
})
);
it('should reject requests without authorization', () =>
fetch(endpoint)
.then((response) => {
expect(response.status).to.equal(401);
})
);
it('should reject requests with wrong authorization', () =>
fetch(endpoint, { headers: { Authorization: 'Bearer ShouldNotBeAuthorized' } })
.then((response) => {
expect(response.status).to.equal(401);
})
);
it('should authorize requests with correct authorization', () =>
fetch(endpoint, { headers: { Authorization: 'Bearer ShouldBeAuthorized' } })
.then(response => response.json())
.then((json) => {
expect(json.message).to.equal('Successfully authorized!');
expect(json.event.principalId).to.equal('SomeRandomId');
expect(json.event.headers.Authorization).to.equal('Bearer ShouldBeAuthorized');
})
);
afterAll(() => {
Utils.removeService();
});
});

View File

@ -1,5 +0,0 @@
'use strict';
module.exports.hello = (event, context, callback) => {
callback(null, { message: 'Hello from API Gateway!', event });
};

View File

@ -1,61 +0,0 @@
service: aws-nodejs # NOTE: update this with your service name
provider:
name: aws
runtime: nodejs10.x
functions:
hello:
handler: handler.hello
events:
# paths without a slash
- http:
method: POST
path: without-slash
integration: lambda
- http:
method: GET
path: without-slash
integration: lambda
- http:
method: PUT
path: without-slash
integration: lambda
- http:
method: DELETE
path: without-slash
integration: lambda
# paths with a slash
- http:
method: POST
path: /with-slash
integration: lambda
- http:
method: GET
path: /with-slash
integration: lambda
- http:
method: PUT
path: /with-slash
integration: lambda
- http:
method: DELETE
path: /with-slash
integration: lambda
# root only paths
- http:
method: POST
path: /
integration: lambda
- http:
method: GET
path: /
integration: lambda
- http:
method: PUT
path: /
integration: lambda
- http:
method: DELETE
path: /
integration: lambda

View File

@ -1,139 +0,0 @@
'use strict';
const path = require('path');
const expect = require('chai').expect;
const BbPromise = require('bluebird');
const AWS = require('aws-sdk');
const _ = require('lodash');
const fetch = require('node-fetch');
const Utils = require('../../../../../utils/index');
const CF = new AWS.CloudFormation({ region: 'us-east-1' });
BbPromise.promisifyAll(CF, { suffix: 'Promised' });
describe('AWS - API Gateway (Integration: Lambda): Simple API test', () => {
let stackName;
let endpoint;
beforeAll(() => {
stackName = Utils.createTestService('aws-nodejs', path.join(__dirname, 'service'));
Utils.deployService();
});
it('should expose the endpoint(s) in the CloudFormation Outputs', () =>
CF.describeStacksPromised({ StackName: stackName })
.then((result) => _.find(result.Stacks[0].Outputs,
{ OutputKey: 'ServiceEndpoint' }).OutputValue)
.then((endpointOutput) => {
endpoint = endpointOutput.match(/https:\/\/.+\.execute-api\..+\.amazonaws\.com.+/)[0];
endpoint = `${endpoint}`;
})
);
describe('when having a "without-slash" path setup', () => {
it('should expose an accessible POST HTTP endpoint', () => {
const testEndpoint = `${endpoint}/without-slash`;
return fetch(testEndpoint, { method: 'POST' })
.then(response => response.json())
.then((json) => expect(json.message).to.equal('Hello from API Gateway!'));
});
it('should expose an accessible GET HTTP endpoint', () => {
const testEndpoint = `${endpoint}/without-slash`;
return fetch(testEndpoint)
.then(response => response.json())
.then((json) => expect(json.message).to.equal('Hello from API Gateway!'));
});
it('should expose an accessible PUT HTTP endpoint', () => {
const testEndpoint = `${endpoint}/without-slash`;
return fetch(testEndpoint, { method: 'PUT' })
.then(response => response.json())
.then((json) => expect(json.message).to.equal('Hello from API Gateway!'));
});
it('should expose an accessible DELETE HTTP endpoint', () => {
const testEndpoint = `${endpoint}/without-slash`;
return fetch(testEndpoint, { method: 'DELETE' })
.then(response => response.json())
.then((json) => expect(json.message).to.equal('Hello from API Gateway!'));
});
});
describe('when having a "/with-slash" path setup', () => {
it('should expose an accessible POST HTTP endpoint', () => {
const testEndpoint = `${endpoint}/with-slash`;
return fetch(testEndpoint, { method: 'POST' })
.then(response => response.json())
.then((json) => expect(json.message).to.equal('Hello from API Gateway!'));
});
it('should expose an accessible GET HTTP endpoint', () => {
const testEndpoint = `${endpoint}/with-slash`;
return fetch(testEndpoint)
.then(response => response.json())
.then((json) => expect(json.message).to.equal('Hello from API Gateway!'));
});
it('should expose an accessible PUT HTTP endpoint', () => {
const testEndpoint = `${endpoint}/with-slash`;
return fetch(testEndpoint, { method: 'PUT' })
.then(response => response.json())
.then((json) => expect(json.message).to.equal('Hello from API Gateway!'));
});
it('should expose an accessible DELETE HTTP endpoint', () => {
const testEndpoint = `${endpoint}/with-slash`;
return fetch(testEndpoint, { method: 'DELETE' })
.then(response => response.json())
.then((json) => expect(json.message).to.equal('Hello from API Gateway!'));
});
});
describe('when having a "/" path setup', () => {
it('should expose an accessible POST HTTP endpoint', () => {
const testEndpoint = `${endpoint}`;
return fetch(testEndpoint, { method: 'POST' })
.then(response => response.json())
.then((json) => expect(json.message).to.equal('Hello from API Gateway!'));
});
it('should expose an accessible GET HTTP endpoint', () => {
const testEndpoint = `${endpoint}`;
return fetch(testEndpoint)
.then(response => response.json())
.then((json) => expect(json.message).to.equal('Hello from API Gateway!'));
});
it('should expose an accessible PUT HTTP endpoint', () => {
const testEndpoint = `${endpoint}`;
return fetch(testEndpoint, { method: 'PUT' })
.then(response => response.json())
.then((json) => expect(json.message).to.equal('Hello from API Gateway!'));
});
it('should expose an accessible DELETE HTTP endpoint', () => {
const testEndpoint = `${endpoint}`;
return fetch(testEndpoint, { method: 'DELETE' })
.then(response => response.json())
.then((json) => expect(json.message).to.equal('Hello from API Gateway!'));
});
});
afterAll(() => {
Utils.removeService();
});
});

View File

@ -1,11 +0,0 @@
'use strict';
module.exports.cwe1 = (event, context, callback) => {
process.stdout.write(JSON.stringify(event));
callback(null, {});
};
module.exports.cwe2 = (event, context, callback) => {
process.stdout.write(JSON.stringify(event));
callback(null, {});
};

View File

@ -1,29 +0,0 @@
service: aws-nodejs
provider:
name: aws
runtime: nodejs10.x
functions:
cwe1:
handler: handler.cwe1
events:
- cloudwatchEvent:
event:
source:
- serverless.testapp1
- cloudwatchEvent:
event:
source:
- serverless.testapp2
cwe2:
handler: handler.cwe2
events:
- cloudwatchEvent:
event:
source:
- serverless.testapp1
- cloudwatchEvent:
event:
source:
- serverless.testapp2

View File

@ -1,29 +0,0 @@
'use strict';
const path = require('path');
const expect = require('chai').expect;
const Utils = require('../../../../utils/index');
describe('AWS - CloudWatch Event: Multiple events with multiple functions', () => {
beforeAll(() => {
Utils.createTestService('aws-nodejs', path.join(__dirname, 'service'));
Utils.deployService();
});
it('should trigger functions when cloudwatchEvent runs', () => Utils
.putCloudWatchEvents(['serverless.testapp1', 'serverless.testapp2'])
.delay(60000)
.then(() => {
const logs1 = Utils.getFunctionLogs('cwe1');
const logs2 = Utils.getFunctionLogs('cwe2');
expect(/serverless\.testapp1/g.test(logs1)).to.equal(true);
expect(/serverless\.testapp1/g.test(logs2)).to.equal(true);
expect(/serverless\.testapp2/g.test(logs1)).to.equal(true);
expect(/serverless\.testapp2/g.test(logs2)).to.equal(true);
})
);
afterAll(() => {
Utils.removeService();
});
});

View File

@ -1,6 +0,0 @@
'use strict';
module.exports.cwe1 = (event, context, callback) => {
process.stdout.write(JSON.stringify(event));
callback(null, {});
};

View File

@ -1,18 +0,0 @@
service: aws-nodejs
provider:
name: aws
runtime: nodejs10.x
functions:
cwe1:
handler: handler.cwe1
events:
- cloudwatchEvent:
event:
source:
- serverless.testapp1
- cloudwatchEvent:
event:
source:
- serverless.testapp2

View File

@ -1,26 +0,0 @@
'use strict';
const path = require('path');
const expect = require('chai').expect;
const Utils = require('../../../../utils/index');
describe('AWS - CloudWatch Event: Multiple events with single function', () => {
beforeAll(() => {
Utils.createTestService('aws-nodejs', path.join(__dirname, 'service'));
Utils.deployService();
});
it('should trigger function when cloudwatchEvent runs', () => Utils
.putCloudWatchEvents(['serverless.testapp1', 'serverless.testapp2'])
.delay(60000)
.then(() => {
const logs = Utils.getFunctionLogs('cwe1');
expect(/serverless\.testapp1/g.test(logs)).to.equal(true);
expect(/serverless\.testapp2/g.test(logs)).to.equal(true);
})
);
afterAll(() => {
Utils.removeService();
});
});

View File

@ -1,11 +0,0 @@
'use strict';
module.exports.cwe1 = (event, context, callback) => {
process.stdout.write(JSON.stringify(event));
callback(null, {});
};
module.exports.cwe2 = (event, context, callback) => {
process.stdout.write(JSON.stringify(event));
callback(null, {});
};

View File

@ -1,21 +0,0 @@
service: aws-nodejs
provider:
name: aws
runtime: nodejs10.x
functions:
cwe1:
handler: handler.cwe1
events:
- cloudwatchEvent:
event:
source:
- serverless.testapp1
cwe2:
handler: handler.cwe2
events:
- cloudwatchEvent:
event:
source:
- serverless.testapp1

View File

@ -1,27 +0,0 @@
'use strict';
const path = require('path');
const expect = require('chai').expect;
const Utils = require('../../../../utils/index');
describe('AWS - CloudWatch Event: Single event with multiple functions', () => {
beforeAll(() => {
Utils.createTestService('aws-nodejs', path.join(__dirname, 'service'));
Utils.deployService();
});
it('should trigger functions when cloudwatchEvent runs', () => Utils
.putCloudWatchEvents(['serverless.testapp1'])
.delay(60000)
.then(() => {
const logs1 = Utils.getFunctionLogs('cwe1');
const logs2 = Utils.getFunctionLogs('cwe2');
expect(/serverless\.testapp1/g.test(logs1)).to.equal(true);
expect(/serverless\.testapp1/g.test(logs2)).to.equal(true);
})
);
afterAll(() => {
Utils.removeService();
});
});

View File

@ -1,6 +0,0 @@
'use strict';
module.exports.cwe1 = (event, context, callback) => {
process.stdout.write(JSON.stringify(event));
callback(null, {});
};

View File

@ -1,14 +0,0 @@
service: aws-nodejs
provider:
name: aws
runtime: nodejs10.x
functions:
cwe1:
handler: handler.cwe1
events:
- cloudwatchEvent:
event:
source:
- serverless.testapp1

View File

@ -1,25 +0,0 @@
'use strict';
const path = require('path');
const expect = require('chai').expect;
const Utils = require('../../../../utils/index');
describe('AWS - CloudWatch Event: Single event with single function', () => {
beforeAll(() => {
Utils.createTestService('aws-nodejs', path.join(__dirname, 'service'));
Utils.deployService();
});
it('should trigger function when cloudwatchEvent runs', () => Utils
.putCloudWatchEvents(['serverless.testapp1'])
.delay(60000)
.then(() => {
const logs = Utils.getFunctionLogs('cwe1');
expect(/serverless\.testapp1/g.test(logs)).to.equal(true);
})
);
afterAll(() => {
Utils.removeService();
});
});

View File

@ -1,27 +0,0 @@
'use strict';
const preSignUp = (event, context, callback) => {
const nextEvent = Object.assign({}, event);
nextEvent.response.autoConfirmUser = true;
process.stdout.write(JSON.stringify(nextEvent));
callback(null, nextEvent);
};
const customMessage = (event, context, callback) => {
const nextEvent = Object.assign({}, event);
if (event.triggerSource === 'CustomMessage_SignUp') {
nextEvent.response.smsMessage = `Welcome to the service. Your confirmation code is ${
event.request.codeParameter}`;
nextEvent.response.emailSubject = 'Welcome to the service';
nextEvent.response.emailMessage = `Thank you for signing up. ${
event.request.codeParameter} is your verification code`;
}
process.stdout.write(JSON.stringify(nextEvent));
callback(null, nextEvent);
};
module.exports.preSignUp1 = preSignUp;
module.exports.preSignUp2 = preSignUp;
module.exports.customMessage1 = customMessage;
module.exports.customMessage2 = customMessage;

View File

@ -1,31 +0,0 @@
service: aws-nodejs
provider:
name: aws
runtime: nodejs10.x
functions:
preSignUp1:
handler: handler.preSignUp1
events:
- cognitoUserPool:
pool: ${env:COGNITO_USER_POOL_1}
trigger: PreSignUp
customMessage1:
handler: handler.customMessage1
events:
- cognitoUserPool:
pool: ${env:COGNITO_USER_POOL_1}
trigger: CustomMessage
preSignUp2:
handler: handler.preSignUp2
events:
- cognitoUserPool:
pool: ${env:COGNITO_USER_POOL_2}
trigger: PreSignUp
customMessage2:
handler: handler.customMessage2
events:
- cognitoUserPool:
pool: ${env:COGNITO_USER_POOL_2}
trigger: CustomMessage

View File

@ -1,77 +0,0 @@
'use strict';
const path = require('path');
const expect = require('chai').expect;
const Utils = require('../../../../utils/index');
describe('AWS - Cognito User Pool: Multiple User Pools with multiple ' +
'events with multiple functions', () => {
beforeAll(() => {
Utils.createTestService('aws-nodejs', path.join(__dirname, 'service'));
Utils.deployService();
});
it('should call the specified function on the first User Pool when PreSignUp ' +
'event is triggered', () => Utils
.getCognitoUserPoolId(process.env.COGNITO_USER_POOL_1)
.then((poolId) =>
Promise.all([
poolId,
Utils.createCognitoUser(poolId, 'test@test.com', 'Password123!'),
])
)
.delay(60000)
.then((promiseResponse) => {
const poolId = promiseResponse[0];
const logs = Utils.getFunctionLogs('preSignUp1');
expect(RegExp(`"userPoolId":"${poolId}"`, 'g').test(logs)).to.equal(true);
expect(/"triggerSource":"PreSignUp_\w+"/g.test(logs)).to.equal(true);
})
);
it('should call the specified function on the first User Pool when CustomMessage ' +
'event is triggered', () => Utils
.getCognitoUserPoolId(process.env.COGNITO_USER_POOL_1)
.then((poolId) => {
const logs = Utils.getFunctionLogs('customMessage1');
expect(RegExp(`"userPoolId":"${poolId}"`, 'g').test(logs)).to.equal(true);
expect(/"triggerSource":"CustomMessage_AdminCreateUser"/g.test(logs)).to.equal(true);
})
);
it('should call the specified function on the second User Pool when PreSignUp ' +
'event is triggered', () => Utils
.getCognitoUserPoolId(process.env.COGNITO_USER_POOL_2)
.then((poolId) =>
Promise.all([
poolId,
Utils.createCognitoUser(poolId, 'test@test.com', 'Password123!'),
])
)
.delay(60000)
.then((promiseResponse) => {
const poolId = promiseResponse[0];
const logs = Utils.getFunctionLogs('preSignUp2');
expect(RegExp(`"userPoolId":"${poolId}"`, 'g').test(logs)).to.equal(true);
expect(/"triggerSource":"PreSignUp_\w+"/g.test(logs)).to.equal(true);
})
);
it('should call the specified function on the second User Pool when CustomMessage ' +
'event is triggered', () => Utils
.getCognitoUserPoolId(process.env.COGNITO_USER_POOL_2)
.then((poolId) => {
const logs = Utils.getFunctionLogs('customMessage2');
expect(RegExp(`"userPoolId":"${poolId}"`, 'g').test(logs)).to.equal(true);
expect(/"triggerSource":"CustomMessage_AdminCreateUser"/g.test(logs)).to.equal(true);
})
);
afterAll(() => {
Utils.removeService();
});
});

View File

@ -1,9 +0,0 @@
'use strict';
module.exports.preSignUp = (event, context, callback) => {
const nextEvent = Object.assign({}, event);
nextEvent.response.autoConfirmUser = true;
process.stdout.write(JSON.stringify(nextEvent));
callback(null, nextEvent);
};

View File

@ -1,16 +0,0 @@
service: aws-nodejs
provider:
name: aws
runtime: nodejs10.x
functions:
preSignUp:
handler: handler.preSignUp
events:
- cognitoUserPool:
pool: ${env:COGNITO_USER_POOL_1}
trigger: PreSignUp
- cognitoUserPool:
pool: ${env:COGNITO_USER_POOL_2}
trigger: PreSignUp

View File

@ -1,53 +0,0 @@
'use strict';
const path = require('path');
const expect = require('chai').expect;
const Utils = require('../../../../utils/index');
describe('AWS - Cognito User Pool: Multiple User Pools with single ' +
'event with single function', () => {
beforeAll(() => {
Utils.createTestService('aws-nodejs', path.join(__dirname, 'service'));
Utils.deployService();
});
it('should call the specified function on the first User Pool when PreSignUp ' +
'event is triggered', () => Utils
.getCognitoUserPoolId(process.env.COGNITO_USER_POOL_1)
.then((poolId) =>
Promise.all([
poolId,
Utils.createCognitoUser(poolId, 'test@test.com', 'Password123!'),
])
)
.delay(60000)
.then((promiseResponse) => {
const poolId = promiseResponse[0];
const logs = Utils.getFunctionLogs('preSignUp');
expect(RegExp(`"userPoolId":"${poolId}"`, 'g').test(logs)).to.equal(true);
expect(/"triggerSource":"PreSignUp_\w+"/g.test(logs)).to.equal(true);
})
);
it('should call the specified function on the second User Pool when PreSignUp ' +
'event is triggered', () => Utils
.getCognitoUserPoolId(process.env.COGNITO_USER_POOL_2)
.then((poolId) =>
Promise.all([
poolId,
Utils.createCognitoUser(poolId, 'test@test.com', 'Password123!'),
])
)
.delay(60000)
.then((promiseResponse) => {
const poolId = promiseResponse[0];
const logs = Utils.getFunctionLogs('preSignUp');
expect(RegExp(`"userPoolId":"${poolId}"`, 'g').test(logs)).to.equal(true);
expect(/"triggerSource":"PreSignUp_\w+"/g.test(logs)).to.equal(true);
})
);
afterAll(() => {
Utils.removeService();
});
});

View File

@ -1,22 +0,0 @@
'use strict';
module.exports.preSignUp = (event, context, callback) => {
const nextEvent = Object.assign({}, event);
nextEvent.response.autoConfirmUser = true;
process.stdout.write(JSON.stringify(nextEvent));
callback(null, nextEvent);
};
module.exports.customMessage = (event, context, callback) => {
const nextEvent = Object.assign({}, event);
if (event.triggerSource === 'CustomMessage_SignUp') {
nextEvent.response.smsMessage = `Welcome to the service. Your confirmation code is ${
event.request.codeParameter}`;
nextEvent.response.emailSubject = 'Welcome to the service';
nextEvent.response.emailMessage = `Thank you for signing up. ${
event.request.codeParameter} is your verification code`;
}
process.stdout.write(JSON.stringify(nextEvent));
callback(null, nextEvent);
};

View File

@ -1,19 +0,0 @@
service: aws-nodejs
provider:
name: aws
runtime: nodejs10.x
functions:
preSignUp:
handler: handler.preSignUp
events:
- cognitoUserPool:
pool: ${env:COGNITO_USER_POOL_1}
trigger: PreSignUp
customMessage:
handler: handler.customMessage
events:
- cognitoUserPool:
pool: ${env:COGNITO_USER_POOL_1}
trigger: CustomMessage

View File

@ -1,39 +0,0 @@
'use strict';
const path = require('path');
const expect = require('chai').expect;
const Utils = require('../../../../utils/index');
describe('AWS - Cognito User Pool: Single User Pool with multiple ' +
'events with multiple functions', () => {
beforeAll(() => {
Utils.createTestService('aws-nodejs', path.join(__dirname, 'service'));
Utils.deployService();
});
it('should call the specified function when PreSignUp event is triggered', () => Utils
.getCognitoUserPoolId(process.env.COGNITO_USER_POOL_1)
.then((poolId) =>
Utils.createCognitoUser(poolId, 'test@test.com', 'Password123!')
)
.delay(60000)
.then(() => {
const logs = Utils.getFunctionLogs('preSignUp');
expect(/"triggerSource":"PreSignUp_\w+"/g.test(logs)).to.equal(true);
})
);
it('should call the specified function when CustomMessage event is triggered', () => Utils
.getCognitoUserPoolId(process.env.COGNITO_USER_POOL_1)
.then((poolId) => {
const logs = Utils.getFunctionLogs('customMessage');
expect(RegExp(`"userPoolId":"${poolId}"`, 'g').test(logs)).to.equal(true);
expect(/"triggerSource":"CustomMessage_AdminCreateUser"/g.test(logs)).to.equal(true);
})
);
afterAll(() => {
Utils.removeService();
});
});

View File

@ -1,9 +0,0 @@
'use strict';
module.exports.preSignUp = (event, context, callback) => {
const nextEvent = Object.assign({}, event);
nextEvent.response.autoConfirmUser = true;
process.stdout.write(JSON.stringify(nextEvent));
callback(null, nextEvent);
};

View File

@ -1,13 +0,0 @@
service: aws-nodejs
provider:
name: aws
runtime: nodejs10.x
functions:
preSignUp:
handler: handler.preSignUp
events:
- cognitoUserPool:
pool: ${env:COGNITO_USER_POOL_1}
trigger: PreSignUp

Some files were not shown because too many files have changed in this diff Show More