Repository: dubzzz/fast-check
Pull request #1328 (2021-01-06 20:07:34)

✨ Better handling of known symbols with `fc.stringify`
<!-- Why is this PR for? -->
<!-- Describe the reason why you opened this PR or give a link towards the associated issue. -->

## In a nutshell

✔️ New feature
❌ Fix an issue
❌ Documentation improvement
❌ Other: *please explain*

(✔️: yes, ❌: no)

## Potential impacts

None

github-actions[bot]: Give a try to https://github.com/dubzzz/fast-check/pull/1328/commits/5068fb563e9cbb37ca598bbeaf9d38e43b1e6d60 with:

```bash
yarn add https://pkg.csb.dev/dubzzz/fast-check/commit/5068fb56/fast-check
npm i https://pkg.csb.dev/dubzzz/fast-check/commit/5068fb56/fast-check
```

⚠️ Package might not be accessible yet. Wait for CodeSandbox.

⚠️ By running one of these commands you will install the package defined by the head of the PR. But, tests are run against the result of the merge of the PR, not against the head of the PR*. *_If needed, you can install the package used for the tests by manually retrieving and installing the artifact bundle stored into GitHub Actions._

Useful links: [Codeclimate](https://codeclimate.com/github/dubzzz/fast-check/pull/1328), [Codecov](https://codecov.io/gh/dubzzz/fast-check/pull/1328), [CodeSandbox](https://ci.codesandbox.io/status/dubzzz/fast-check/pr/1328) and [GitHub Actions](https://github.com/dubzzz/fast-check/actions/runs/467044762).
codesandbox[bot]: This pull request is automatically built and testable in [CodeSandbox](https://codesandbox.io).

  To see build info of the built libraries, click [here](https://ci.codesandbox.io/status/dubzzz/fast-check/pr/1328/builds/88240) or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 5068fb563e9cbb37ca598bbeaf9d38e43b1e6d60:

|Sandbox| Source |
|--|--|
|[Vanilla](https://codesandbox.io/s/vanilla-7h3ub)| Configuration |
|[fast-check-examples](https://codesandbox.io/s/fast-check-examples-4svvz)| Configuration |

codecov[bot]: # [Codecov](https://codecov.io/gh/dubzzz/fast-check/pull/1328?src=pr&el=h1) Report
> Merging [#1328](https://codecov.io/gh/dubzzz/fast-check/pull/1328?src=pr&el=desc) (5068fb5) into [master](https://codecov.io/gh/dubzzz/fast-check/commit/d5406c2eb1873dc2b627d2a1c969c746e6726f3f?el=desc) (d5406c2) will **decrease** coverage by `8.91%`.
> The diff coverage is `0.00%`.

[![Impacted file tree graph](https://codecov.io/gh/dubzzz/fast-check/pull/1328/graphs/tree.svg?width=650&height=150&src=pr&token=fRi2fJN730)](https://codecov.io/gh/dubzzz/fast-check/pull/1328?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master    #1328      +/-   ##
==========================================
- Coverage   98.76%   89.85%   -8.92%     
==========================================
  Files          89       89              
  Lines        2914     2917       +3     
  Branches      540      542       +2     
==========================================
- Hits         2878     2621     -257     
- Misses         33      290     +257     
- Partials        3        6       +3     
```

| Flag | Coverage Δ | |
|---|---|---|
| e2e-tests | `89.85% <0.00%> (-0.13%)` | :arrow_down: |
| e2e-tests-10.x-Linux | `89.81% <0.00%> (-0.10%)` | :arrow_down: |
| e2e-tests-10.x-Windows | `?` | |
| e2e-tests-10.x-macOS | `?` | |
| e2e-tests-12.x-Linux | `?` | |
| e2e-tests-12.x-Windows | `?` | |
| e2e-tests-12.x-macOS | `?` | |
| e2e-tests-14.x-Linux | `89.85% <0.00%> (-0.13%)` | :arrow_down: |
| e2e-tests-14.x-Windows | `?` | |
| e2e-tests-14.x-macOS | `?` | |
| unit-tests | `?` | |
| unit-tests-10.x-Linux | `?` | |
| unit-tests-12.x-Linux | `?` | |
| unit-tests-14.x-Linux | `?` | |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/dubzzz/fast-check/pull/1328?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [src/utils/stringify.ts](https://codecov.io/gh/dubzzz/fast-check/pull/1328/diff?src=pr&el=tree#diff-c3JjL3V0aWxzL3N0cmluZ2lmeS50cw==) | `80.23% <0.00%> (-18.57%)` | :arrow_down: |
| [src/check/property/TimeoutProperty.ts](https://codecov.io/gh/dubzzz/fast-check/pull/1328/diff?src=pr&el=tree#diff-c3JjL2NoZWNrL3Byb3BlcnR5L1RpbWVvdXRQcm9wZXJ0eS50cw==) | `11.76% <0.00%> (-88.24%)` | :arrow_down: |
| [src/check/model/commands/ScheduledCommand.ts](https://codecov.io/gh/dubzzz/fast-check/pull/1328/diff?src=pr&el=tree#diff-c3JjL2NoZWNrL21vZGVsL2NvbW1hbmRzL1NjaGVkdWxlZENvbW1hbmQudHM=) | `7.14% <0.00%> (-82.15%)` | :arrow_down: |
| [src/utils/hash.ts](https://codecov.io/gh/dubzzz/fast-check/pull/1328/diff?src=pr&el=tree#diff-c3JjL3V0aWxzL2hhc2gudHM=) | `29.62% <0.00%> (-70.38%)` | :arrow_down: |
| [src/stream/LazyIterableIterator.ts](https://codecov.io/gh/dubzzz/fast-check/pull/1328/diff?src=pr&el=tree#diff-c3JjL3N0cmVhbS9MYXp5SXRlcmFibGVJdGVyYXRvci50cw==) | `63.63% <0.00%> (-36.37%)` | :arrow_down: |
| [src/check/property/AsyncProperty.generic.ts](https://codecov.io/gh/dubzzz/fast-check/pull/1328/diff?src=pr&el=tree#diff-c3JjL2NoZWNrL3Byb3BlcnR5L0FzeW5jUHJvcGVydHkuZ2VuZXJpYy50cw==) | `66.66% <0.00%> (-33.34%)` | :arrow_down: |
| [src/check/model/ModelRunner.ts](https://codecov.io/gh/dubzzz/fast-check/pull/1328/diff?src=pr&el=tree#diff-c3JjL2NoZWNrL21vZGVsL01vZGVsUnVubmVyLnRz) | `58.33% <0.00%> (-31.26%)` | :arrow_down: |
| [src/check/property/Property.generic.ts](https://codecov.io/gh/dubzzz/fast-check/pull/1328/diff?src=pr&el=tree#diff-c3JjL2NoZWNrL3Byb3BlcnR5L1Byb3BlcnR5LmdlbmVyaWMudHM=) | `70.58% <0.00%> (-29.42%)` | :arrow_down: |
| [.../check/runner/configuration/QualifiedParameters.ts](https://codecov.io/gh/dubzzz/fast-check/pull/1328/diff?src=pr&el=tree#diff-c3JjL2NoZWNrL3J1bm5lci9jb25maWd1cmF0aW9uL1F1YWxpZmllZFBhcmFtZXRlcnMudHM=) | `70.14% <0.00%> (-28.36%)` | :arrow_down: |
| [src/check/arbitrary/AsyncSchedulerArbitrary.ts](https://codecov.io/gh/dubzzz/fast-check/pull/1328/diff?src=pr&el=tree#diff-c3JjL2NoZWNrL2FyYml0cmFyeS9Bc3luY1NjaGVkdWxlckFyYml0cmFyeS50cw==) | `73.27% <0.00%> (-25.00%)` | :arrow_down: |
| ... and [30 more](https://codecov.io/gh/dubzzz/fast-check/pull/1328/diff?src=pr&el=tree-more) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/dubzzz/fast-check/pull/1328?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/dubzzz/fast-check/pull/1328?src=pr&el=footer). Last update [d5406c2...5068fb5](https://codecov.io/gh/dubzzz/fast-check/pull/1328?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/src/utils/stringify.ts b/src/utils/stringify.ts
index 37052f33..d2fe281b 100644
--- a/src/utils/stringify.ts
+++ b/src/utils/stringify.ts
@@ -92,7 +92,11 @@ export function stringifyInternal<Ts>(value: Ts, previousValues: any[]): string
         return `Symbol.for(${JSON.stringify(Symbol.keyFor(s))})`;
       }
       const desc = getSymbolDescription(s);
-      return desc !== null ? `Symbol(${JSON.stringify(desc)})` : `Symbol()`;
+      if (desc === null) {
+        return 'Symbol()';
+      }
+      const knownSymbol = desc.startsWith('Symbol.') && (Symbol as any)[desc.substring(7)];
+      return s === knownSymbol ? desc : `Symbol(${JSON.stringify(desc)})`;
     }
     case '[object Undefined]':
       return `undefined`;


Test patch:
diff --git a/test/unit/utils/stringify.spec.ts b/test/unit/utils/stringify.spec.ts
index fe76baa4..ca03c31e 100644
--- a/test/unit/utils/stringify.spec.ts
+++ b/test/unit/utils/stringify.spec.ts
@@ -144,6 +144,23 @@ describe('stringify', () => {
     expect(stringify(Symbol('fc'))).toEqual('Symbol("fc")');
     expect(stringify(Symbol.for('fc'))).toEqual('Symbol.for("fc")');
   });
+  it('Should be able to stringify well-known Symbols', () => {
+    expect(stringify(Symbol.iterator)).toEqual('Symbol.iterator');
+    expect(stringify(Symbol('Symbol.iterator'))).toEqual('Symbol("Symbol.iterator")');
+
+    // Same as above but with all the known symbols
+    let foundOne = false;
+    for (const symbolName of Object.getOwnPropertyNames(Symbol)) {
+      const s = (Symbol as any)[symbolName];
+      if (typeof s === 'symbol') {
+        foundOne = true;
+        expect(stringify(s)).toEqual(`Symbol.${symbolName}`);
+        expect(stringify(Symbol(`Symbol.${symbolName}`))).toEqual(`Symbol("Symbol.${symbolName}")`);
+        expect(eval(`(function() { return typeof ${stringify(s)}; })()`)).toBe('symbol');
+      }
+    }
+    expect(foundOne).toBe(true);
+  });
   it('Should be able to stringify Object without prototype', () => {
     expect(stringify(Object.create(null))).toEqual('Object.create(null)');
     expect(stringify(Object.assign(Object.create(null), { a: 1 }))).toEqual(