Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
bkimminich opened this issue Dec 22, 2017 · 4 comments
Open

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

bkimminich opened this issue Dec 22, 2017 · 4 comments

Comments

@bkimminich
Copy link

bkimminich commented Dec 22, 2017

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 🎄 to you!

@bkimminich
Copy link
Author

bkimminich commented Dec 22, 2017

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
Copy link

IonelLupu commented May 29, 2020

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
Copy link

jedwards1211 commented Dec 18, 2020

@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
Copy link

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.

jedwards1211 added a commit to jedwards1211/chai-as-promised that referenced this issue Dec 18, 2020
Some people seem to miss the note (debitoor/chai-subset#69).  It's easy to forget about this too...I only really grokked this behavior after digging into what `chai-as-promise` does under the hood.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants