debitoor / chai-subset

"containSubset" object properties matcher for Chai
http://chaijs.com/plugins/chai-subset/
MIT License
82 stars 20 forks source link

Combining chai-subset and chai-as-promised #69

Open bkimminich opened 6 years ago

bkimminich commented 6 years ago

I hope to be able to replace some ugly

  it('should consist of one object pushed into flagKeys.results per challenge', function () {
    return expect(generateData(challenges, options.noTextHints, options.noHintUrls, '')).to.eventually.deep.include(
      {
        flagKeys: {
          results: [
            { id: 1, chal: 1, flag: '958c64658383140e7d08d5dee091009cc0eafc1f', type: 'static', key_type: 'static', data: null }, ...
          ]
        }
      })
  })

assertions (which need to specify all the object properties that I don't even care about) with

  it('should consist of one object pushed into flagKeys.results per challenge', function () {
    return expect(generateData(challenges, options.noTextHints, options.noHintUrls, '')).to.eventually.containSubset(
      {
        flagKeys: {
          results: [
            { id: 1, chal: 1, flag: '958c64658383140e7d08d5dee091009cc0eafc1f' }, ...
          ]
        }
      })
  })

checks. Unfortunately that does not work, because that eventually-thing is a promise with the actual compare value nested inside. This gives me errors like:

 AssertionError: expected { Object (_bitField, _fulfillmentHandler0, ...) } to contain subset { Object (flagKeys) }
      + expected - actual

       {
      -  "_bitField": 33554432
      -  "_fulfillmentHandler0": [undefined]
      -  "_promise0": [undefined]
      -  "_receiver0": [undefined]
      -  "_rejectionHandler0": {
      -    "challenges": {
      -      "results": [...]
      -    }
      -    "flagKeys": {
      -      "results": [
      -        {
      -          "chal": 1
      -          "data": [null]
      -          "flag": "958c64658383140e7d08d5dee091009cc0eafc1f"
      -          "id": 1
      -          "key_type": "static"
      -          "type": "static"
      -        } ...
      -      ]
      -    }
      -    "hints": {
      -      "results": []
      -    }
      +  "flagKeys": {
      +    "results": [
      +      {
      +        "chal": 1
      +        "data": [null]
      +        "flag": "958c64658383140e7d08d5dee091009cc0eafc1f"
      +      } ...
      +    ]
         }
       }

      at Proxy.<anonymous> (node_modules\chai-subset\lib\chai-subset.js:20:30)
      at Proxy.methodWrapper (node_modules\chai\lib\chai\utils\addMethod.js:57:25)
      at Context.<anonymous> (test\unit\generateData-spec.js:38:104)

Using to.eventually.deep.containSubset does not work either. You can find the original unit test here: https://github.com/bkimminich/juice-shop-ctf/blob/develop/test/unit/generateData-spec.js#L37-L76

Thanks in advance for your help/hints! Btw, merry :christmas_tree: to you!

bkimminich commented 6 years ago

To clarify what I'd actually want to achieve, here's an example:

  xit('should contain the "key_type" property for backward compatibility with CTFd <1.1.0', function () {
    return expect(generateData(challenges, options.noTextHints, options.noHintUrls, '')).to.eventually.deep.containSubset(
      {
        flagKeys: {
          results: [
            { key_type: 'static' }
          ]
        }
      })
  })

In the original test above I could then remove the key_type property from the expectation and have functional and backward compatibility test separated.

I pushed what I would like to have in the end to develop. I hope that helps understand my goal: https://github.com/bkimminich/juice-shop-ctf/blob/develop/test/unit/generateData-spec.js#L37-L76

IonelLupu commented 4 years ago

I would also like to combine the two.

Right now, I am getting an error saying that containSubset does not exist on PromisseAssertion :(

myPromise
    .should.be.rejected
    .and.should.eventually.to.containSubset([{
    property1: {
        property2: `some value`
    }
}]);

I get this error only from typescript. At runtime, the code works

jedwards1211 commented 3 years ago

@IonelLupu @bkimminich The way chai-as-promised works is gnarly. Are you using chai-subset before or after chai-as-promised? If you use chai-as-promise after chai-subset you should be able to .eventually any of its assertions.

chai-as-promised scans and wraps all of the language chains that are available at the time it is used, so the ones from chai-subset don't get wrapped unless you use chai-subset first.

jedwards1211 commented 3 years ago

This is kind of a footnote in the chai-as-promised docs:

Note when using other Chai plugins: Chai as Promised finds all currently-registered asserters and promisifies them, at the time it is installed. Thus, you should install Chai as Promised last, after any other Chai plugins, if you expect their asserters to be promisified.