Repository: oppia/oppia

Issue:
ExpressionEvaluatorService test not passing when using `Set` in ExpressionSyntaxTreeService
<!--
  - Thanks for taking the time to report a bug in the Oppia project.
  - Before filing a new issue, please do a quick search to check that it hasn't
  - already been filed on the [issue tracker](https://github.com/oppia/oppia/issues)._
  -->

**Describe the bug**
During the migration of `ExpressionSyntaxtTreeService` when using `Set` data structure (to prevent duplicates) in `findParams` method, used in `getParamsUsedInExpression`, you get unexpected results during the test "Should get params used in expressions".
[Link to the discussion](https://github.com/oppia/oppia/pull/8886#discussion_r401807387)

Due to migration, we have to transform them into classes and because `_findParams` was a recursive function we had to extract it:
```
public getParamsUsedInExpression(expression: string): string[] {
    let parsed = this.expressionParserService.parse(expression);

    return Array.from(this.findParams(parsed)).sort();
  }

  private findParams(parseTree: string[]|string): Set<string> {
    let paramsFound = new Set<string>();
    if (parseTree instanceof Array) {
      if (parseTree[0] === '#') {
        paramsFound.add(parseTree[1]);
      } else {
        for (let i = 1; i < parseTree.length; i++) {
          this.findParams(parseTree[i]).forEach((p: string) =>
            paramsFound.add(p));
        }
      }
      return paramsFound;
    }
  }
```

**To Reproduce**
Steps to reproduce the behavior:
 1. Go to expression-syntax-tree.service.ts file
 2. Replace this block of code inside `_findParams` method with this:
```
    let paramsFound = new Set<string>();
    if (parseTree instanceof Array) {
      if (parseTree[0] === '#') {
        paramsFound.add(parseTree[1]);
      } else {
        for (let i = 1; i < parseTree.length; i++) {
          this.findParams(parseTree[i]).forEach((p: string) =>
            paramsFound.add(p));
        }
      }
      return paramsFound;
    }
```
3. Remove uniqueParams block and return as an Array sorted like so:
```
return Array.from(this._findParams(parsed)).sort();
```
 3. Open the file expression-evaluator.service.spec.ts
 4. Perform the front end test

**Observed behavior**
The following has been observed during the test:
```
ERROR: 'input           : +10'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'parsed          : ["+",10]'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'expected        : []'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'exception       : TypeError: Cannot read property 'forEach' of undefined'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'input           : 2   + 10'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'parsed          : ["+",2,10]'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'expected        : []'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'exception       : TypeError: Cannot read property 'forEach' of undefined'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'input           : 20 - num100_001'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'parsed          : ["-",20,["#","num100_001"]]'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'expected        : ["num100_001"]'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'exception       : TypeError: Cannot read property 'forEach' of undefined'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'input           : 0x100 - 256'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'parsed          : ["-",256,256]'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'expected        : []'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'exception       : TypeError: Cannot read property 'forEach' of undefined'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'input           : 1 - 2 * 3'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'parsed          : ["-",1,["*",2,3]]'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'expected        : []'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'exception       : TypeError: Cannot read property 'forEach' of undefined'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'input           : num100_001 / 0.1'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'parsed          : ["/",["#","num100_001"],0.1]'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'expected        : ["num100_001"]'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'exception       : TypeError: Cannot read property 'forEach' of undefined'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'input           : floor((numZero + num100_001)/2)'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'parsed          : ["floor",["/",["+",["#","numZero"],["#","num100_001"]],2]]'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'expected        : ["num100_001","numZero"]'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'exception       : TypeError: Cannot read property 'forEach' of undefined'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'input           : 23 % 5'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'parsed          : ["%",23,5]'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'expected        : []'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'exception       : TypeError: Cannot read property 'forEach' of undefined'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'input           : 1 <= numZero || 1 >= numZero'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'parsed          : ["||",["<=",1,["#","numZero"]],[">=",1,["#","numZero"]]]'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'expected        : ["numZero"]'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'exception       : TypeError: Cannot read property 'forEach' of undefined'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'input           : 100 < num100_001 && 1 > num100_001'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'parsed          : ["&&",["<",100,["#","num100_001"]],[">",1,["#","num100_001"]]]'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'expected        : ["num100_001"]'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'exception       : TypeError: Cannot read property 'forEach' of undefined'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'input           : num100_001 / 0'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'parsed          : ["/",["#","num100_001"],0]'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'expected        : ["num100_001"]'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'exception       : TypeError: Cannot read property 'forEach' of undefined'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'input           : abs(-3)'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'parsed          : ["abs",["-",3]]'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'expected        : []'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'exception       : TypeError: Cannot read property 'forEach' of undefined'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'input           : log(9, 3)'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'parsed          : ["log",9,3]'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'expected        : []'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
ERROR: 'exception       : TypeError: Cannot read property 'forEach' of undefined'
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6): Executed 1506 of 1972 SUCCESS (0 secs / 18.54 secs)
HeadlessChrome 80.0.3987 (Mac OS X 10.14.6) Expression evaluator service should get params used in expressions FAILED
	Error: Expected true to be false.
```

**Expected behavior**
The test must pass when input is, let's say: `log(9, 3)` the expected (as shown above) should be an empty array `[]`



Discussion:

Resolving patch:
diff --git a/scripts/check_frontend_coverage.py b/scripts/check_frontend_coverage.py
--- a/scripts/check_frontend_coverage.py
+++ b/scripts/check_frontend_coverage.py
@@ -139,6 +139,7 @@
     'ExplorationObjectFactory.ts',
     'ExplorationOpportunitySummaryObjectFactory.ts',
     'expression-parser.service.ts',
+    'expression-syntax-tree.service.ts',
     'extension-tag-assembler.service.ts',
     'extract-image-filenames-from-state.service.ts',
     'FeedbackImprovementTaskObjectFactory.ts',


Test patch: