From 97d62097c6bb75ffc6d38c104a710abc86151cf1 Mon Sep 17 00:00:00 2001 From: My Ho Date: Fri, 31 May 2019 14:43:39 -0700 Subject: [PATCH 1/3] remove default stage value in provider object the current default is using AWS region naming syntax, this mean other cloud provider would have to add extra code to set their default value. Instead, region default should be left to each provider. --- lib/classes/Service.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/classes/Service.js b/lib/classes/Service.js index 0ec8d06062c..8d05585ee74 100644 --- a/lib/classes/Service.js +++ b/lib/classes/Service.js @@ -20,7 +20,6 @@ class Service { this.serviceObject = null; this.provider = { stage: 'dev', - region: 'us-east-1', variableSyntax: '\\${([ ~:a-zA-Z0-9._@\'",\\-\\/\\(\\)*]+?)}', }; this.custom = {}; From 5541f2b9eff5d06880733fe9ce9ba37d14a5467f Mon Sep 17 00:00:00 2001 From: My Ho Date: Wed, 5 Jun 2019 16:08:51 -0700 Subject: [PATCH 2/3] Fix tests --- lib/classes/Service.test.js | 363 ++++++++++++++++++------------------ 1 file changed, 181 insertions(+), 182 deletions(-) diff --git a/lib/classes/Service.test.js b/lib/classes/Service.test.js index d5342a097f8..2e8fa0af541 100644 --- a/lib/classes/Service.test.js +++ b/lib/classes/Service.test.js @@ -30,7 +30,6 @@ describe('Service', () => { expect(serviceInstance.serviceObject).to.be.equal(null); expect(serviceInstance.provider).to.deep.equal({ stage: 'dev', - region: 'us-east-1', variableSyntax: '\\${([ ~:a-zA-Z0-9._@\'",\\-\\/\\(\\)*]+?)}', }); expect(serviceInstance.custom).to.deep.equal({}); @@ -268,23 +267,23 @@ describe('Service', () => { serviceInstance = new Service(serverless); return expect(serviceInstance.load()).to.eventually.be.fulfilled - .then(() => { - expect(serviceInstance.service).to.be.equal('new-service'); - expect(serviceInstance.provider.name).to.deep.equal('aws'); - expect(serviceInstance.provider.variableSyntax).to.equal( - '\\${{([ ~:a-zA-Z0-9._@\'",\\-\\/\\(\\)*]+?)}}' - ); - expect(serviceInstance.plugins).to.deep.equal(['testPlugin']); - expect(serviceInstance.resources.aws).to.deep.equal({ resourcesProp: 'value' }); - expect(serviceInstance.resources.azure).to.deep.equal({}); - expect(serviceInstance.resources.google).to.deep.equal({}); - expect(serviceInstance.package.exclude.length).to.equal(1); - expect(serviceInstance.package.exclude[0]).to.equal('exclude-me'); - expect(serviceInstance.package.include.length).to.equal(1); - expect(serviceInstance.package.include[0]).to.equal('include-me'); - expect(serviceInstance.package.artifact).to.equal('some/path/foo.zip'); - expect(serviceInstance.package.excludeDevDependencies).to.equal(undefined); - }); + .then(() => { + expect(serviceInstance.service).to.be.equal('new-service'); + expect(serviceInstance.provider.name).to.deep.equal('aws'); + expect(serviceInstance.provider.variableSyntax).to.equal( + '\\${{([ ~:a-zA-Z0-9._@\'",\\-\\/\\(\\)*]+?)}}' + ); + expect(serviceInstance.plugins).to.deep.equal(['testPlugin']); + expect(serviceInstance.resources.aws).to.deep.equal({ resourcesProp: 'value' }); + expect(serviceInstance.resources.azure).to.deep.equal({}); + expect(serviceInstance.resources.google).to.deep.equal({}); + expect(serviceInstance.package.exclude.length).to.equal(1); + expect(serviceInstance.package.exclude[0]).to.equal('exclude-me'); + expect(serviceInstance.package.include.length).to.equal(1); + expect(serviceInstance.package.include[0]).to.equal('include-me'); + expect(serviceInstance.package.artifact).to.equal('some/path/foo.zip'); + expect(serviceInstance.package.excludeDevDependencies).to.equal(undefined); + }); }); it('should load serverless.js from filesystem', () => { @@ -323,23 +322,23 @@ describe('Service', () => { serviceInstance = new Service(serverless); return expect(serviceInstance.load()).to.eventually.be.fulfilled - .then(() => { - expect(serviceInstance.service).to.be.equal('new-service'); - expect(serviceInstance.provider.name).to.deep.equal('aws'); - expect(serviceInstance.provider.variableSyntax).to.equal( - '\\${{([ ~:a-zA-Z0-9._@\'",\\-\\/\\(\\)*]+?)}}' - ); - expect(serviceInstance.plugins).to.deep.equal(['testPlugin']); - expect(serviceInstance.resources.aws).to.deep.equal({ resourcesProp: 'value' }); - expect(serviceInstance.resources.azure).to.deep.equal({}); - expect(serviceInstance.resources.google).to.deep.equal({}); - expect(serviceInstance.package.exclude.length).to.equal(1); - expect(serviceInstance.package.exclude[0]).to.equal('exclude-me'); - expect(serviceInstance.package.include.length).to.equal(1); - expect(serviceInstance.package.include[0]).to.equal('include-me'); - expect(serviceInstance.package.artifact).to.equal('some/path/foo.zip'); - expect(serviceInstance.package.excludeDevDependencies).to.equal(undefined); - }); + .then(() => { + expect(serviceInstance.service).to.be.equal('new-service'); + expect(serviceInstance.provider.name).to.deep.equal('aws'); + expect(serviceInstance.provider.variableSyntax).to.equal( + '\\${{([ ~:a-zA-Z0-9._@\'",\\-\\/\\(\\)*]+?)}}' + ); + expect(serviceInstance.plugins).to.deep.equal(['testPlugin']); + expect(serviceInstance.resources.aws).to.deep.equal({ resourcesProp: 'value' }); + expect(serviceInstance.resources.azure).to.deep.equal({}); + expect(serviceInstance.resources.google).to.deep.equal({}); + expect(serviceInstance.package.exclude.length).to.equal(1); + expect(serviceInstance.package.exclude[0]).to.equal('exclude-me'); + expect(serviceInstance.package.include.length).to.equal(1); + expect(serviceInstance.package.include[0]).to.equal('include-me'); + expect(serviceInstance.package.artifact).to.equal('some/path/foo.zip'); + expect(serviceInstance.package.excludeDevDependencies).to.equal(undefined); + }); }); it('should load serverless.js from filesystem', () => { @@ -378,23 +377,23 @@ describe('Service', () => { serviceInstance = new Service(serverless); return expect(serviceInstance.load()).to.eventually.be.fulfilled - .then(() => { - expect(serviceInstance.service).to.be.equal('new-service'); - expect(serviceInstance.provider.name).to.deep.equal('aws'); - expect(serviceInstance.provider.variableSyntax).to.equal( - '\\${{([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}}' - ); - expect(serviceInstance.plugins).to.deep.equal(['testPlugin']); - expect(serviceInstance.resources.aws).to.deep.equal({ resourcesProp: 'value' }); - expect(serviceInstance.resources.azure).to.deep.equal({}); - expect(serviceInstance.resources.google).to.deep.equal({}); - expect(serviceInstance.package.exclude.length).to.equal(1); - expect(serviceInstance.package.exclude[0]).to.equal('exclude-me'); - expect(serviceInstance.package.include.length).to.equal(1); - expect(serviceInstance.package.include[0]).to.equal('include-me'); - expect(serviceInstance.package.artifact).to.equal('some/path/foo.zip'); - expect(serviceInstance.package.excludeDevDependencies).to.equal(undefined); - }); + .then(() => { + expect(serviceInstance.service).to.be.equal('new-service'); + expect(serviceInstance.provider.name).to.deep.equal('aws'); + expect(serviceInstance.provider.variableSyntax).to.equal( + '\\${{([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}}' + ); + expect(serviceInstance.plugins).to.deep.equal(['testPlugin']); + expect(serviceInstance.resources.aws).to.deep.equal({ resourcesProp: 'value' }); + expect(serviceInstance.resources.azure).to.deep.equal({}); + expect(serviceInstance.resources.google).to.deep.equal({}); + expect(serviceInstance.package.exclude.length).to.equal(1); + expect(serviceInstance.package.exclude[0]).to.equal('exclude-me'); + expect(serviceInstance.package.include.length).to.equal(1); + expect(serviceInstance.package.include[0]).to.equal('include-me'); + expect(serviceInstance.package.artifact).to.equal('some/path/foo.zip'); + expect(serviceInstance.package.excludeDevDependencies).to.equal(undefined); + }); }); it('should throw error if serverless.js exports invalid config', () => { @@ -451,10 +450,10 @@ describe('Service', () => { serviceInstance = new Service(serverless); return expect(serviceInstance.load()).to.eventually.be.fulfilled - .then(() => { - // YAML should have been loaded instead of JSON - expect(serviceInstance.service).to.be.equal('YAML service'); - }); + .then(() => { + // YAML should have been loaded instead of JSON + expect(serviceInstance.service).to.be.equal('YAML service'); + }); }); it('should reject when the service name is missing', () => { @@ -491,10 +490,10 @@ describe('Service', () => { serviceInstance = new Service(serverless); return expect(serviceInstance.load()).to.eventually.be.fulfilled - .then(() => { - expect(serviceInstance.service).to.equal('my-service'); - expect(serviceInstance.serviceObject).to.deep.equal(serverlessYaml.service); - }); + .then(() => { + expect(serviceInstance.service).to.equal('my-service'); + expect(serviceInstance.serviceObject).to.deep.equal(serverlessYaml.service); + }); }); it('should support Serverless file with a non-aws provider', () => { @@ -516,18 +515,18 @@ describe('Service', () => { serviceInstance = new Service(serverless); return expect(serviceInstance.load()).to.eventually.be.fulfilled - .then(() => { - serviceInstance.setFunctionNames(); - const expectedFunc = { - functionA: { - name: 'customFunctionName', - events: [], - }, - }; - expect(serviceInstance.service).to.be.equal('my-service'); - expect(serviceInstance.provider.name).to.deep.equal('openwhisk'); - expect(serviceInstance.functions).to.deep.equal(expectedFunc); - }); + .then(() => { + serviceInstance.setFunctionNames(); + const expectedFunc = { + functionA: { + name: 'customFunctionName', + events: [], + }, + }; + expect(serviceInstance.service).to.be.equal('my-service'); + expect(serviceInstance.provider.name).to.deep.equal('openwhisk'); + expect(serviceInstance.functions).to.deep.equal(expectedFunc); + }); }); it('should support Serverless file with a .yaml extension', () => { @@ -549,18 +548,18 @@ describe('Service', () => { serviceInstance = new Service(serverless); return expect(serviceInstance.load()).to.eventually.be.fulfilled - .then(() => { - serviceInstance.setFunctionNames(); - const expectedFunc = { - functionA: { - name: 'customFunctionName', - events: [], - }, - }; - expect(serviceInstance.service).to.be.equal('my-service'); - expect(serviceInstance.provider.name).to.deep.equal('aws'); - expect(serviceInstance.functions).to.deep.equal(expectedFunc); - }); + .then(() => { + serviceInstance.setFunctionNames(); + const expectedFunc = { + functionA: { + name: 'customFunctionName', + events: [], + }, + }; + expect(serviceInstance.service).to.be.equal('my-service'); + expect(serviceInstance.provider.name).to.deep.equal('aws'); + expect(serviceInstance.functions).to.deep.equal(expectedFunc); + }); }); it('should support Serverless file with a .yml extension', () => { @@ -580,18 +579,18 @@ describe('Service', () => { serviceInstance = new Service(serverless); return expect(serviceInstance.load({ stage: 'dev' })).to.eventually.be.fulfilled - .then(() => { - serviceInstance.setFunctionNames(); - const expectedFunc = { - functionA: { - name: 'my-service-dev-functionA', - events: [], - }, - }; - expect(serviceInstance.service).to.be.equal('my-service'); - expect(serviceInstance.provider.name).to.deep.equal('aws'); - expect(serviceInstance.functions).to.deep.equal(expectedFunc); - }); + .then(() => { + serviceInstance.setFunctionNames(); + const expectedFunc = { + functionA: { + name: 'my-service-dev-functionA', + events: [], + }, + }; + expect(serviceInstance.service).to.be.equal('my-service'); + expect(serviceInstance.provider.name).to.deep.equal('aws'); + expect(serviceInstance.functions).to.deep.equal(expectedFunc); + }); }); it('should reject if service property is missing', () => { @@ -679,15 +678,15 @@ describe('Service', () => { serviceInstance = new Service(serverless); return expect(serviceInstance.load()).to.eventually.be.fulfilled - .then(() => { - // populate variables in service configuration - serverless.variables.populateService(); + .then(() => { + // populate variables in service configuration + serverless.variables.populateService(); - // validate the service configuration, now that variables are loaded - serviceInstance.validate(); + // validate the service configuration, now that variables are loaded + serviceInstance.validate(); - expect(serviceInstance.functions).to.deep.equal({}); - }); + expect(serviceInstance.functions).to.deep.equal({}); + }); }); }); @@ -716,11 +715,11 @@ describe('Service', () => { serverless.service = new Service(serverless); return expect(serverless.service.load()).to.eventually.be.fulfilled - .then(() => { - // validate the service configuration, now that variables are loaded - expect(() => serverless.service.validate()) - .to.throw('Events for "functionA" must be an array, not an string'); - }); + .then(() => { + // validate the service configuration, now that variables are loaded + expect(() => serverless.service.validate()) + .to.throw('Events for "functionA" must be an array, not an string'); + }); }); describe('stage name validation', () => { @@ -735,59 +734,59 @@ describe('Service', () => { it(`should not throw an error if http event is absent and stage contains only alphanumeric, underscore and hyphen`, function () { - this.timeout(10000); // Occasionally times out with default settings - const SUtils = new Utils(); - const serverlessYml = { - service: 'new-service', - provider: { - name: 'aws', - stage: 'xyz-101_abc-123', - }, - functions: { - first: { - events: [], + this.timeout(10000); // Occasionally times out with default settings + const SUtils = new Utils(); + const serverlessYml = { + service: 'new-service', + provider: { + name: 'aws', + stage: 'xyz-101_abc-123', }, - }, - }; - SUtils.writeFileSync(path.join(tmpDirPath, 'serverless.yml'), - YAML.dump(serverlessYml)); - - const serverless = new Serverless({ servicePath: tmpDirPath }); - return expect(simulateRun(serverless)).to.eventually.be.fulfilled.then(() => { - expect(() => serverless.service.validate()).to.not.throw(serverless.classes.Error); + functions: { + first: { + events: [], + }, + }, + }; + SUtils.writeFileSync(path.join(tmpDirPath, 'serverless.yml'), + YAML.dump(serverlessYml)); + + const serverless = new Serverless({ servicePath: tmpDirPath }); + return expect(simulateRun(serverless)).to.eventually.be.fulfilled.then(() => { + expect(() => serverless.service.validate()).to.not.throw(serverless.classes.Error); + }); }); - }); it(`should not throw an error after variable population if http event is present and the populated stage contains only alphanumeric, underscore and hyphen`, () => { - const SUtils = new Utils(); - const serverlessYml = { - service: 'new-service', - provider: { - name: 'aws', - stage: '${opt:stage, "default-stage"}', - }, - functions: { - first: { - events: [ - { - http: { - path: 'foo', - method: 'GET', + const SUtils = new Utils(); + const serverlessYml = { + service: 'new-service', + provider: { + name: 'aws', + stage: '${opt:stage, "default-stage"}', + }, + functions: { + first: { + events: [ + { + http: { + path: 'foo', + method: 'GET', + }, }, - }, - ], + ], + }, }, - }, - }; - SUtils.writeFileSync(path.join(tmpDirPath, 'serverless.yml'), - YAML.dump(serverlessYml)); - - const serverless = new Serverless({ servicePath: tmpDirPath }); - return expect(simulateRun(serverless)).to.eventually.be.fulfilled.then(() => { - expect(() => serverless.service.validate()).to.not.throw(serverless.classes.Error); + }; + SUtils.writeFileSync(path.join(tmpDirPath, 'serverless.yml'), + YAML.dump(serverlessYml)); + + const serverless = new Serverless({ servicePath: tmpDirPath }); + return expect(simulateRun(serverless)).to.eventually.be.fulfilled.then(() => { + expect(() => serverless.service.validate()).to.not.throw(serverless.classes.Error); + }); }); - }); it('should throw an error if http event is present and stage contains invalid chars', () => { const SUtils = new Utils(); @@ -825,38 +824,38 @@ describe('Service', () => { it(`should throw an error after variable population if http event is present and stage contains hyphen`, () => { - const SUtils = new Utils(); - const serverlessYml = { - service: 'new-service', - provider: { - name: 'aws', - stage: '${opt:stage, "default:stage"}', - }, - functions: { - first: { - events: [ - { - http: { - path: 'foo', - method: 'GET', + const SUtils = new Utils(); + const serverlessYml = { + service: 'new-service', + provider: { + name: 'aws', + stage: '${opt:stage, "default:stage"}', + }, + functions: { + first: { + events: [ + { + http: { + path: 'foo', + method: 'GET', + }, }, - }, - ], + ], + }, }, - }, - }; - SUtils.writeFileSync(path.join(tmpDirPath, 'serverless.yml'), - YAML.dump(serverlessYml)); - - const serverless = new Serverless({ servicePath: tmpDirPath }); - return expect(simulateRun(serverless)).to.eventually.be.fulfilled.then(() => { - expect(() => serverless.service.validate()).to.throw(serverless.classes.Error, [ - 'Invalid stage name default:stage: it should contains only [-_a-zA-Z0-9]', - 'for AWS provider if http event are present', - 'according to API Gateway limitation.', - ].join(' ')); + }; + SUtils.writeFileSync(path.join(tmpDirPath, 'serverless.yml'), + YAML.dump(serverlessYml)); + + const serverless = new Serverless({ servicePath: tmpDirPath }); + return expect(simulateRun(serverless)).to.eventually.be.fulfilled.then(() => { + expect(() => serverless.service.validate()).to.throw(serverless.classes.Error, [ + 'Invalid stage name default:stage: it should contains only [-_a-zA-Z0-9]', + 'for AWS provider if http event are present', + 'according to API Gateway limitation.', + ].join(' ')); + }); }); - }); }); }); From e2522597910efe848a3290b8ce42056eb2d774c0 Mon Sep 17 00:00:00 2001 From: Philipp Muens Date: Thu, 6 Jun 2019 12:27:19 +0200 Subject: [PATCH 3/3] Fix linting issues --- lib/classes/Service.test.js | 148 ++++++++++++++++++------------------ 1 file changed, 74 insertions(+), 74 deletions(-) diff --git a/lib/classes/Service.test.js b/lib/classes/Service.test.js index 2e8fa0af541..60b0a9f2962 100644 --- a/lib/classes/Service.test.js +++ b/lib/classes/Service.test.js @@ -733,60 +733,60 @@ describe('Service', () => { } it(`should not throw an error if http event is absent and - stage contains only alphanumeric, underscore and hyphen`, function () { - this.timeout(10000); // Occasionally times out with default settings - const SUtils = new Utils(); - const serverlessYml = { - service: 'new-service', - provider: { - name: 'aws', - stage: 'xyz-101_abc-123', - }, - functions: { - first: { - events: [], - }, + stage contains only alphanumeric, underscore and hyphen`, function () { + this.timeout(10000); // Occasionally times out with default settings + const SUtils = new Utils(); + const serverlessYml = { + service: 'new-service', + provider: { + name: 'aws', + stage: 'xyz-101_abc-123', + }, + functions: { + first: { + events: [], }, - }; - SUtils.writeFileSync(path.join(tmpDirPath, 'serverless.yml'), - YAML.dump(serverlessYml)); + }, + }; + SUtils.writeFileSync(path.join(tmpDirPath, 'serverless.yml'), + YAML.dump(serverlessYml)); - const serverless = new Serverless({ servicePath: tmpDirPath }); - return expect(simulateRun(serverless)).to.eventually.be.fulfilled.then(() => { - expect(() => serverless.service.validate()).to.not.throw(serverless.classes.Error); - }); + const serverless = new Serverless({ servicePath: tmpDirPath }); + return expect(simulateRun(serverless)).to.eventually.be.fulfilled.then(() => { + expect(() => serverless.service.validate()).to.not.throw(serverless.classes.Error); }); + }); it(`should not throw an error after variable population if http event is present and - the populated stage contains only alphanumeric, underscore and hyphen`, () => { - const SUtils = new Utils(); - const serverlessYml = { - service: 'new-service', - provider: { - name: 'aws', - stage: '${opt:stage, "default-stage"}', - }, - functions: { - first: { - events: [ - { - http: { - path: 'foo', - method: 'GET', - }, + the populated stage contains only alphanumeric, underscore and hyphen`, () => { + const SUtils = new Utils(); + const serverlessYml = { + service: 'new-service', + provider: { + name: 'aws', + stage: '${opt:stage, "default-stage"}', + }, + functions: { + first: { + events: [ + { + http: { + path: 'foo', + method: 'GET', }, - ], - }, + }, + ], }, - }; - SUtils.writeFileSync(path.join(tmpDirPath, 'serverless.yml'), - YAML.dump(serverlessYml)); + }, + }; + SUtils.writeFileSync(path.join(tmpDirPath, 'serverless.yml'), + YAML.dump(serverlessYml)); - const serverless = new Serverless({ servicePath: tmpDirPath }); - return expect(simulateRun(serverless)).to.eventually.be.fulfilled.then(() => { - expect(() => serverless.service.validate()).to.not.throw(serverless.classes.Error); - }); + const serverless = new Serverless({ servicePath: tmpDirPath }); + return expect(simulateRun(serverless)).to.eventually.be.fulfilled.then(() => { + expect(() => serverless.service.validate()).to.not.throw(serverless.classes.Error); }); + }); it('should throw an error if http event is present and stage contains invalid chars', () => { const SUtils = new Utils(); @@ -824,38 +824,38 @@ describe('Service', () => { it(`should throw an error after variable population if http event is present and stage contains hyphen`, () => { - const SUtils = new Utils(); - const serverlessYml = { - service: 'new-service', - provider: { - name: 'aws', - stage: '${opt:stage, "default:stage"}', - }, - functions: { - first: { - events: [ - { - http: { - path: 'foo', - method: 'GET', - }, + const SUtils = new Utils(); + const serverlessYml = { + service: 'new-service', + provider: { + name: 'aws', + stage: '${opt:stage, "default:stage"}', + }, + functions: { + first: { + events: [ + { + http: { + path: 'foo', + method: 'GET', }, - ], - }, + }, + ], }, - }; - SUtils.writeFileSync(path.join(tmpDirPath, 'serverless.yml'), - YAML.dump(serverlessYml)); - - const serverless = new Serverless({ servicePath: tmpDirPath }); - return expect(simulateRun(serverless)).to.eventually.be.fulfilled.then(() => { - expect(() => serverless.service.validate()).to.throw(serverless.classes.Error, [ - 'Invalid stage name default:stage: it should contains only [-_a-zA-Z0-9]', - 'for AWS provider if http event are present', - 'according to API Gateway limitation.', - ].join(' ')); - }); + }, + }; + SUtils.writeFileSync(path.join(tmpDirPath, 'serverless.yml'), + YAML.dump(serverlessYml)); + + const serverless = new Serverless({ servicePath: tmpDirPath }); + return expect(simulateRun(serverless)).to.eventually.be.fulfilled.then(() => { + expect(() => serverless.service.validate()).to.throw(serverless.classes.Error, [ + 'Invalid stage name default:stage: it should contains only [-_a-zA-Z0-9]', + 'for AWS provider if http event are present', + 'according to API Gateway limitation.', + ].join(' ')); }); + }); }); });