Repository: asyncapi/generator
Pull request #350 (2020-05-20 16:06:54)

feat: show warning for wrong spelled params
**Description**

- show warning for wrong spelled params

Example:
```bash
ag asyncapi.yaml @asyncapi/html-template -p baseHef=/doc -o output
Warning: This template doesn't have following params: baseHef.
```

**Related issue(s)**
Resolves: #345 
<!-- If you refer to a particular issue, provide its number, othewise, remove this section.
For example, `Resolves #123`, `Fixes #43`, or `See also #33`. The 3rd option will not automatically close the issue after the merge. -->

sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!

[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug.png' alt='Bug' width='16' height='16' />](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=BUG) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=BUG)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability.png' alt='Vulnerability' width='16' height='16' />](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=VULNERABILITY) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=VULNERABILITY) (and [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot.png' alt='Security Hotspot' width='16' height='16' />](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=SECURITY_HOTSPOT) to review)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell.png' alt='Code Smell' width='16' height='16' />](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=CODE_SMELL) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=CODE_SMELL)

[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo.png' alt='No Coverage information' width='16' height='16' />](https://sonarcloud.io/component_measures?id=asyncapi_generator&pullRequest=350) No Coverage information  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3.png' alt='0.0%' width='16' height='16' />](https://sonarcloud.io/component_measures?id=asyncapi_generator&pullRequest=350&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=asyncapi_generator&pullRequest=350&metric=new_duplicated_lines_density&view=list)


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!

[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug.png' alt='Bug' width='16' height='16' />](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=BUG) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=BUG)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability.png' alt='Vulnerability' width='16' height='16' />](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=VULNERABILITY) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=VULNERABILITY) (and [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot.png' alt='Security Hotspot' width='16' height='16' />](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=SECURITY_HOTSPOT) to review)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell.png' alt='Code Smell' width='16' height='16' />](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=CODE_SMELL) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=CODE_SMELL)

[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo.png' alt='No Coverage information' width='16' height='16' />](https://sonarcloud.io/component_measures?id=asyncapi_generator&pullRequest=350) No Coverage information  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3.png' alt='0.0%' width='16' height='16' />](https://sonarcloud.io/component_measures?id=asyncapi_generator&pullRequest=350&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=asyncapi_generator&pullRequest=350&metric=new_duplicated_lines_density&view=list)


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!

[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug.png' alt='Bug' width='16' height='16' />](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=BUG) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=BUG)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability.png' alt='Vulnerability' width='16' height='16' />](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=VULNERABILITY) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=VULNERABILITY) (and [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot.png' alt='Security Hotspot' width='16' height='16' />](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=SECURITY_HOTSPOT) to review)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell.png' alt='Code Smell' width='16' height='16' />](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=CODE_SMELL) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=350&resolved=false&types=CODE_SMELL)

[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo.png' alt='No Coverage information' width='16' height='16' />](https://sonarcloud.io/component_measures?id=asyncapi_generator&pullRequest=350) No Coverage information  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3.png' alt='0.0%' width='16' height='16' />](https://sonarcloud.io/component_measures?id=asyncapi_generator&pullRequest=350&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=asyncapi_generator&pullRequest=350&metric=new_duplicated_lines_density&view=list)


Tenischev: > Suggestion: It would be amazing if it could show something like "Did you mean..."
> Shouldn't be hard leveraging the Levenshtein algorithm: https://www.npmjs.com/package/levenshtein-edit-distance.

I hope you wouldn't mind if i'll create a separate issue for it?
Tenischev: Created #351

Patch:
diff --git a/lib/generator.js b/lib/generator.js
index 40c0687..3a463d8 100644
--- a/lib/generator.js
+++ b/lib/generator.js
@@ -643,7 +643,6 @@ class Generator {
       this.templateConfig = {};
     }
     await this.loadDefaultValues();
-    await this.validateTemplateConfig();
   }
 
   /**
@@ -680,12 +679,7 @@ class Generator {
       throw new Error(`This template is not compatible with the current version of the generator (${packageJson.version}). This template is compatible with the following version range: ${generator}.`);
     }
 
-    const requiredParams = Object.keys(parameters || {}).filter(key => parameters[key].required === true);
-
-    const missingParams = requiredParams.filter(rp => this.templateParams[rp] === undefined);
-    if (missingParams.length) {
-      throw new Error(`This template requires the following missing params: ${missingParams}.`);
-    }
+    this.verifyParameters(parameters);
 
     if (typeof conditionalFiles === 'object') {
       const fileNames = Object.keys(conditionalFiles) || [];
@@ -709,6 +703,25 @@ class Generator {
     }
   }
 
+  /**
+   * Checks that all required parameters are set and all specified by user parameters are present in template.
+   *
+   * @private
+   * @param  {Array} [parameters] parameters known from template configuration.
+   */
+  verifyParameters(parameters) {
+    const missingParams = Object.keys(parameters || {})
+      .filter(key => parameters[key].required === true && this.templateParams[key] === undefined);
+    if (missingParams.length) {
+      throw new Error(`This template requires the following missing params: ${missingParams}.`);
+    }
+
+    const wrongParams = Object.keys(this.templateParams || {}).filter(key => parameters[key] === undefined);
+    if (wrongParams.length) {
+      console.warn(`Warning: This template doesn't have the following params: ${wrongParams}.`);
+    }
+  }
+
   /**
    * Launches all the hooks registered at a given hook point/name.
    *


Test patch:
diff --git a/test/generator.test.js b/test/generator.test.js
index a60a7cc..5ab7140 100644
--- a/test/generator.test.js
+++ b/test/generator.test.js
@@ -466,4 +466,44 @@ describe('Generator', () => {
       });
     });
   });
+
+  describe('#verifyParameters', () => {
+    it('required parameter is missed', () => {
+      const gen = new Generator('testTemplate', __dirname, {
+        templateParams: {
+          test: true
+        }
+      });
+      const params = {
+        requiredParam: {
+          required: true
+        },
+        test: {
+          required: false
+        }
+      };
+
+      expect(() => {
+        gen.verifyParameters(params);
+      }).toThrow(/requiredParam/);
+    });
+    it('wrong parameter is passed', () => {
+      const gen = new Generator('testTemplate', __dirname, {
+        templateParams: {
+          notExistInConf: true
+        }
+      });
+      const params = {
+        existInConf: {
+          required: false
+        }
+      };
+      console.warn = jest.fn();
+
+      gen.verifyParameters(params);
+
+      expect(console.warn).toBeCalledWith(expect.stringContaining('notExistInConf'));
+      expect(console.warn).toBeCalledWith(expect.not.stringContaining('existInConf'));
+    });
+  });
 });