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

Can subject be called when one of the API methods is called? #47

Closed
PikachuEXE opened this issue Apr 15, 2015 · 10 comments
Closed

Can subject be called when one of the API methods is called? #47

PikachuEXE opened this issue Apr 15, 2015 · 10 comments

Comments

@PikachuEXE
Copy link
Contributor

I have many context group for my controller spec.
But I always needs to add the get /path at the very end BUT in before hook

I just tried put the get in subject to avoid the repeated call, it works with json_spec since they implement with custom matcher.
But it doesn't work with this gem, with error complaining about missing json_body, meaning subject is not called.

Is there a way to make it call subject when one of the API methods (e.g. expect_json_types) is called?

@sethpollack
Copy link
Collaborator

@PikachuEXE do you have an example of what you are trying to do?

@PikachuEXE
Copy link
Contributor Author

subject do
  call_action
  controller
end

let(:call_action) do
  get :index
end

it {expect_json_types(pagination: :object)}
it {expect_json_types("data", {posts: :array_of_objects})}
it {expect_json_sizes("data", {listings: 1})}

@drewcimino
Copy link

I think using subject { call_action; controller } is abusing the subject block a little bit.

subject isn't a substitute for before, it's shorthand for:

let(:thing)
...
  expect(thing).to be_something
...

In many cases, when you're using the shorthand test syntax it { is_expected.to be_something }, the code in your subject is in effect run like it is in a before block, but it's not guaranteed (nor should it be).

Also: I think using something like

before(:each) { get :index }
subject { controller }

is cleaner and more readable than the blocks you're using up top. With properly nested context blocks, you should only have to write that once and have it accessible by all your tests that need them.

@sethpollack
Copy link
Collaborator

I agree. I don't think that is what subject is meant for.

@PikachuEXE
Copy link
Contributor Author

Regardless of how I use / abuse subject, the question I am asking here is: is it intended to not call subject?

@sethpollack
Copy link
Collaborator

Its not that we are intentionally not calling the subject hook, we just had no reason to do so.

Normally RSpec expectation take both the subject and the expectation, however with Airborne, we just use the response as the subject and therefore have no reason to be calling the subject hook.

Is there a use-case other than the one above where it would make sense to do so?

@PikachuEXE
Copy link
Contributor Author

I will find my own way to solve this then.
Thanks for your time.

@sethpollack
Copy link
Collaborator

No problem. You can try wrapping the methods in your spec_helper

    [:expect_json_types, :expect_json, :expect_json_keys, :expect_status, :expect_header, :expect_header_contains].each do |method_name|
      method = instance_method(method_name)
      define_method(method_name) do |*args, &block|
        subject()
        method.bind(self).call(*args, &block)
      end
    end

@PikachuEXE
Copy link
Contributor Author

I am already do the same thing (with another way).
Thanks anyway.

@sethpollack
Copy link
Collaborator

Ok no problem!

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