Repository: Redocly/redocly-cli
Pull request #754 (2022-07-06 19:34:39)

Fix : Filter-out does not filter out when value is set to false (bool) #753
## What/Why/How?

### What ?

- Fix use of if guards on filtering in and out some nodes from an openapi file. 

### Why ?

- The use of **! operator*** for checking whether a value was undefined also checked out false (boolean) and null values. What made it impossible to use those values for filtering nodes out of the file.
- As a border effect, this problem didn't occur while filtering **in** properties that had these values (false/null) but not for the "proper reason".

### How ?

- Explicitly use **"=== undefined"**  to verify if the structure hasn't been given as a parameter to the function call instead of using the **! operator** 
- This allows the use of both false and null values to filter nodes in or out an openapi file 

## Reference

[Filter-out does not filter out when value is set to false (bool) #753](https://github.com/Redocly/redocly-cli/issues/753)

## Testing

- Test if the nodes containing the given properties with false or null values are properly removed from the input file.

## Check yourself

- [ ✅  ] Code is linted
- [ ❌  ] Tested with redoc/reference-docs/workflows
- [ ✅  ] All new/updated code is covered with tests

## Security

- [ ✅ ] Security impact of change has been considered
- [ ❔  ] Code follows company security practices and guidelines


deBarrosS: @RomanHotsiy a bit later than I thought but there it is 😬 
RomanHotsiy: Amazing, you even added tests 👏 !

@tatomyr plz merge it and release after you review it.
tatomyr: LGTM.

@deBarrosS thanks for your contribution. I'm going to merge and release the new version early next week.

Patch:
diff --git a/packages/core/src/decorators/common/filters/filter-helper.ts b/packages/core/src/decorators/common/filters/filter-helper.ts
index 6a166391..47dc47ef 100644
--- a/packages/core/src/decorators/common/filters/filter-helper.ts
+++ b/packages/core/src/decorators/common/filters/filter-helper.ts
@@ -47,7 +47,7 @@ export function checkIfMatchByStrategy(
   decoratorValue: any,
   strategy: 'all' | 'any'
 ): boolean {
-  if (!nodeValue || !decoratorValue) {
+  if (nodeValue===undefined || decoratorValue===undefined) {
     return false;
   }
 


Test patch:
diff --git a/packages/core/src/decorators/__tests__/filter-out.test.ts b/packages/core/src/decorators/__tests__/filter-out.test.ts
index 04ebfa43..efb661e8 100644
--- a/packages/core/src/decorators/__tests__/filter-out.test.ts
+++ b/packages/core/src/decorators/__tests__/filter-out.test.ts
@@ -27,9 +27,7 @@ describe('oas3 filter-out', () => {
               callbacks:
                 x-access: protected
                 orderInProgress:
-                  x-internal: true
-             `
-  );
+                  x-internal: true`);
 
   it('should remove /pet path and y parameter', async () => {
     const testDocument = parseYamlToDocument(
@@ -62,7 +60,7 @@ describe('oas3 filter-out', () => {
               x:
                 name: x
 
-        `);
+                `);
   });
 
   it('should remove only /order path', async () => {
@@ -92,8 +90,8 @@ describe('oas3 filter-out', () => {
           post:
             summary: test
       components: {}
-
-    `);
+      
+      `);
   });
 
   it('should remove all paths', async () => {
@@ -134,8 +132,7 @@ describe('oas3 filter-out', () => {
                     type: object
       components: {}
             
-        `
-    );
+        `);
     const { bundle: res } = await bundleDocument({
       document: testDoc,
       externalRefResolver: new BaseResolver(),
@@ -160,6 +157,113 @@ describe('oas3 filter-out', () => {
 
     `);
   });
+
+  it('should remove /pet path and /my/path/false path', async () => {
+    const testDocument = parseYamlToDocument(
+      outdent`
+      openapi: 3.0.0
+      paths:
+        /pet:
+          get:
+            x-prop: false
+            parameters:
+              - $ref: '#/components/parameters/x'
+        /my/path/false:
+          x-access: private
+          x-prop: false
+          get:
+            parameters:
+              - $ref: '#/components/parameters/x'
+        /my/path/null:
+          x-access: private
+          x-prop: null
+          get:
+            parameters:
+              - $ref: '#/components/parameters/x'
+      components:
+        parameters:
+          x:
+            name: x
+            
+            `);
+    const { bundle: res } = await bundleDocument({
+      document: testDocument,
+      externalRefResolver: new BaseResolver(),
+      config: await makeConfig({}, { 'filter-out': { property: 'x-prop', value: false } }),
+    });
+    expect(res.parsed).toMatchInlineSnapshot(`
+      openapi: 3.0.0
+      paths:
+        /my/path/null:
+          x-access: private
+          x-prop: null
+          get:
+            parameters:
+              - $ref: '#/components/parameters/x'
+      components:
+        parameters:
+          x:
+            name: x
+
+            `);
+  });
+
+  it('should remove /my/path/null path ', async () => {
+    const testDocument = parseYamlToDocument(
+      outdent`
+      openapi: 3.0.0
+      paths:
+        /pet:
+          x-access: private
+          get:
+            x-prop: false
+            parameters:
+              - $ref: '#/components/parameters/y'
+        /my/path/false:
+          x-access: private
+          x-prop: false
+          get:
+            parameters:
+              - $ref: '#/components/parameters/y'
+        /my/path/null:
+          x-access: private
+          x-prop: null
+          get:
+            parameters:
+              - $ref: '#/components/parameters/y'
+      components:
+        parameters:
+          x:
+            name: x
+            
+            `);
+    const { bundle: res } = await bundleDocument({
+      document: testDocument,
+      externalRefResolver: new BaseResolver(),
+      config: await makeConfig({}, { 'filter-out': { property: 'x-prop', value: null } }),
+    });
+    expect(res.parsed).toMatchInlineSnapshot(`
+      openapi: 3.0.0
+      paths:
+        /pet:
+          x-access: private
+          get:
+            x-prop: false
+            parameters:
+              - $ref: '#/components/parameters/y'
+        /my/path/false:
+          x-access: private
+          x-prop: false
+          get:
+            parameters:
+              - $ref: '#/components/parameters/y'
+      components:
+        parameters:
+          x:
+            name: x
+
+            `);
+  });
 });
 
 describe('oas2 filter-out', () => {