Repository: BRIKEV/express-jsdoc-swagger
Pull request #221 (2022-06-10 17:36:55)

fix: schema type casing
Update logic for type application casing to ensure lowercase.

### What kind of change does this PR introduce? (check at least one)
 - [x] Bugfix
 - [ ] Feature
 - [ ] Test
 - [ ] Docs
 - [ ] Refactor
 - [ ] Build-related changes
 - [ ] Other, please describe:

### Description:

When types such as `Array<Song>` or `Song[]` are used, the `type` for the property resolves to `'Array'` rather than the officially support OpenAPI [data type](https://swagger.io/docs/specification/data-models/data-types/) of `'array'`. When the type is `'Array'`, the OpenAPI document does not correctly recognize the property as a valid array. The officially supported types are lowercase anyway:

- [string](https://swagger.io/docs/specification/data-models/data-types/#string) (this includes dates and [files](https://swagger.io/docs/specification/data-models/data-types/#file))
- [number](https://swagger.io/docs/specification/data-models/data-types/#numbers)
- [integer](https://swagger.io/docs/specification/data-models/data-types/#numbers)
- [boolean](https://swagger.io/docs/specification/data-models/data-types/#boolean)
- [array](https://swagger.io/docs/specification/data-models/data-types/#array)
- [object](https://swagger.io/docs/specification/data-models/data-types/#object)

sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=BRIKEV_express-jsdoc-swagger&pullRequest=221)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=CODE_SMELL)

[![No Coverage information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo-16px.png 'No Coverage information')](https://sonarcloud.io/component_measures?id=BRIKEV_express-jsdoc-swagger&pullRequest=221) No Coverage information  
[![0.0%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3-16px.png '0.0%')](https://sonarcloud.io/component_measures?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&metric=new_duplicated_lines_density&view=list)


alexstaroselsky: Found another location of `type.expression.name` in `getSchema()` will update that as well and update relevant tests to demonstrate fix.
sonarcloud[bot]: SonarCloud Quality Gate failed.&nbsp; &nbsp; [![Quality Gate failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonarcloud.io/dashboard?id=BRIKEV_express-jsdoc-swagger&pullRequest=221)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=CODE_SMELL) [1 Code Smell](https://sonarcloud.io/project/issues?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=CODE_SMELL)

[![No Coverage information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo-16px.png 'No Coverage information')](https://sonarcloud.io/component_measures?id=BRIKEV_express-jsdoc-swagger&pullRequest=221) No Coverage information  
[![62.3%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/20plus-16px.png '62.3%')](https://sonarcloud.io/component_measures?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&metric=new_duplicated_lines_density&view=list) [62.3% Duplication](https://sonarcloud.io/component_measures?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&metric=new_duplicated_lines_density&view=list)


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=BRIKEV_express-jsdoc-swagger&pullRequest=221)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&resolved=false&types=CODE_SMELL)

[![No Coverage information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo-16px.png 'No Coverage information')](https://sonarcloud.io/component_measures?id=BRIKEV_express-jsdoc-swagger&pullRequest=221) No Coverage information  
[![2.4%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3-16px.png '2.4%')](https://sonarcloud.io/component_measures?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&metric=new_duplicated_lines_density&view=list) [2.4% Duplication](https://sonarcloud.io/component_measures?id=BRIKEV_express-jsdoc-swagger&pullRequest=221&metric=new_duplicated_lines_density&view=list)


alexstaroselsky: @kevinccbsg Could you please clarify who could be a good member to review this PR? Thanks.
LonelyPrincess: > @kevinccbsg or @bri06 or @LonelyPrincess Could you please clarify who would be a good member to review this PR? Or if anything additionally is needed for it to be ready for review? Thanks.

This looks fine to me! The PR description is pretty clear, and doesn't seem like we would be missing anything to consider it complete. I've approved it, although will wait for @kevinccbsg to give the OK before merging. Thanks for your contribution! 😉 
kevinccbsg: @all-contributors please add @alexstaroselsky for code

Patch:
diff --git a/transforms/components/index.js b/transforms/components/index.js
index 320281b..777fd0b 100644
--- a/transforms/components/index.js
+++ b/transforms/components/index.js
@@ -15,7 +15,7 @@ const getPropertyName = ({ name: propertyName }) => {
 const addTypeApplication = (applications, expression) => {
   if (!applications && !expression) return {};
   return {
-    type: expression.name,
+    type: expression.name.toLowerCase(),
     items: {
       type: applications[0].name,
     },
diff --git a/transforms/paths/schema.js b/transforms/paths/schema.js
index 0e7f472..2d12588 100644
--- a/transforms/paths/schema.js
+++ b/transforms/paths/schema.js
@@ -23,7 +23,7 @@ const getSchema = (entity, message) => (type, enumValues = [], jsonOptions = {})
     const parseItems = formatRefSchema(type.applications);
     schema = {
       ...schema,
-      type: type.expression.name,
+      type: type.expression.name.toLowerCase(),
       items: parseItems.items ? parseItems.items : parseItems,
     };
   }


Test patch:
diff --git a/test/transforms/components/index.test.js b/test/transforms/components/index.test.js
index b336cb3..d5fcfa0 100644
--- a/test/transforms/components/index.test.js
+++ b/test/transforms/components/index.test.js
@@ -647,13 +647,29 @@ describe('parseComponents method', () => {
   });
 
   it('Should parse an album schema with an array of Songs schemas.', () => {
-    const jsodInput = [`
-      /**
-       * Album
-       * @typedef {object} Album
-       * @property {array<Song>} Songs
-       */
-    `];
+    const jsodInput = [
+      [`
+        /**
+         * Album
+         * @typedef {object} Album
+         * @property {array<Song>} Songs
+         */
+      `],
+      [`
+        /**
+         * Album
+         * @typedef {object} Album
+         * @property {Array<Song>} Songs
+         */
+      `],
+      [`
+        /**
+         * Album
+         * @typedef {object} Album
+         * @property {Song[]} Songs
+         */
+      `],
+    ];
     const expected = {
       components: {
         schemas: {
@@ -673,9 +689,11 @@ describe('parseComponents method', () => {
         },
       },
     };
-    const parsedJSDocs = jsdocInfo()(jsodInput);
-    const result = parseComponents({}, parsedJSDocs);
-    expect(result).toEqual(expected);
+    jsodInput.forEach(jsod => {
+      const parsedJSDocs = jsdocInfo()(jsod);
+      const result = parseComponents({}, parsedJSDocs);
+      expect(result).toEqual(expected);
+    });
   });
 
   it('Should parse a SingleAlbum schema with allOf reference of Song.', () => {
diff --git a/test/transforms/paths/parameters.test.js b/test/transforms/paths/parameters.test.js
index c49d3d6..f438c58 100644
--- a/test/transforms/paths/parameters.test.js
+++ b/test/transforms/paths/parameters.test.js
@@ -192,12 +192,26 @@ describe('params tests', () => {
   });
 
   it('should parse jsdoc path params with array of references', () => {
-    const jsodInput = [`
-      /**
-       * GET /api/v1
-       * @param {array<Song>} name.query.required.deprecated - name param description
-       */
-    `];
+    const jsodInput = [
+      [`
+        /**
+         * GET /api/v1
+         * @param {array<Song>} name.query.required.deprecated - name param description
+         */
+      `],
+      [`
+        /**
+         * GET /api/v1
+         * @param {Array<Song>} name.query.required.deprecated - name param description
+         */
+      `],
+      [`
+        /**
+         * GET /api/v1
+         * @param {Song[]} name.query.required.deprecated - name param description
+         */
+      `],
+    ];
     const expected = {
       paths: {
         '/api/v1': {
@@ -225,9 +239,11 @@ describe('params tests', () => {
         },
       },
     };
-    const parsedJSDocs = jsdocInfo()(jsodInput);
-    const result = setPaths({}, parsedJSDocs);
-    expect(result).toEqual(expected);
+    jsodInput.forEach(jsod => {
+      const parsedJSDocs = jsdocInfo()(jsod);
+      const result = setPaths({}, parsedJSDocs);
+      expect(result).toEqual(expected);
+    });
   });
 
   it('should parse jsdoc path params with enum values', () => {