brooklynDev / airborne

RSpec driven API testing framework
MIT License
1.13k stars 124 forks source link

Is there a way to test for the absence of data? #126

Open gee-forr opened 7 years ago

gee-forr commented 7 years ago

Hi guys,

I was just wondering if there is a way to test for the absence of JSON using airborne? My particular use case centers around me testing whether or not I am successfully sideloading some data using a toggle param, of which it has a default to not sideload under certain conditions.

Example: No sideloading

{ "foo": "bar" }

Example: sideloading

{
  "foo": "bar",
  "extraStuff": {
    "could": "be",
    "arbitrary": ["json", "data"]
  }
}

For my tests, I wish to test that in the no sideloading example, the "extraStuff" key is not there. Is this possible?

I naïvely thought !expect_json_types(extraStuff: :object) would work, but it unfortunately doesn't.

Any help or pointers would be greatly appreciated. Right now, I'm pulling the json out of json_body, and doing an expect(blob).to_not have_key :extraStuff, which works, but is... not super pretty.

sethpollack commented 7 years ago

You can adjust the strictness with match_expected: true and match_actual: true. If you do that you can just test for the presence of { "foo": "bar" } and if anything extra is there it will fail .

sethpollack commented 7 years ago

You can read more about it here https://github.com/brooklynDev/airborne#configuration

gee-forr commented 7 years ago

Hey @sethpollack - thanks for the response :)

I did initially go that route, but the payload in question is considerably more complex than the example I provided. It would make it quite tedious to test an entire huge payload just to ensure that one key is not there.

If it's OK with you, I'd like to issue a PR to expand the API's expect_* methods to have expect_no_* equivalents.

Sound good?

sethpollack commented 7 years ago

You can also test that it is there and expect it to fail

gee-forr commented 7 years ago

I'm a little slow on the uptake today :) How would I go about doing that?

sethpollack commented 7 years ago

expect { expect_json_types(name: :foo) }.to raise_error

gee-forr commented 7 years ago

Ah. Of course. Thanks for that.

I'd still like to issue that PR nonetheless if you're still keen?

sethpollack commented 7 years ago

What did you have in mind?

gee-forr commented 7 years ago

So, something like the following:

{ "foo": "bar" }

expect_no_json_types(extraStuff: :object) would pass because the extraStuff object is present.

Similarly:

expect_no_json(foo: 'baz') would also pass, as foo is bar, not baz.

The examples are tending towards the contrived, but I feel they add a lot more expressiveness than nesting an expectation and checking for an exception. It would also hew closer to how RSpec does things by providing a complementary .to_not method alongside .to.

It would work great for other matchers like expect_no_header_contains, but not so great for expect_no_json_sizes.