0

I'm trying to DRY up rspec tests that keeps on declaring let(:createBody) do...end. I thought to take out the let statement and just modify the variable on each block as needed. However the variable (createBody) is not accessible. Added a comment on sample code below to see exactly where I want to modify createBody.

post "Creates object", controller_action: :create do
  ...
  let(:createBody) do
    {
      name: "yes",
      type: "my_type",
      amount_cents: 200,
      parameters: {
        day: "today"
      },
      user_group_ids: [],
      user_ids: []
    }
  end

  # no users or groups
  response 201, "object created" do
    ...

    run_test! do |res|
      # this block works fine and can access createBody
      body = JSON.parse(res.body)
      expect(body["name"]).to eq(createBody[:name])
      expect(body["amount_cents"]).to eq(createBody[:amount_cents])
      expect(body["type"]).to eq(createBody[:type])
    end
  end

  # with users
  response 201, "autocharge rule created" do
    ...

    # want to make some modifications on createBody here, like adding user_ids, but it is out of scope
    
    run_test! do |res|
      # this block works fine and can access createBody
      body = JSON.parse(res.body)
      expect(body["user_ids"]).to match_array(createBody[:user_ids])
    end
  end
  ...
end

Is there a way to achieve this approach? Are there any alternatives?

  • That variable is only available from within individual examples, as you've seen. What would the goal of modifying it outside of an example be? – Jake Worth Jun 24 '22 at 17:26
  • Depending on `createBody`, `run_test!`'s `|res|` (result) would vary. – nakakapagpabagabag Jun 24 '22 at 17:38
  • 1
    You could create a variable in each spec that modifies `createBody` to merge in the unique parameters for that spec. – Jake Worth Jun 24 '22 at 17:55
  • I dont think I follow, could you please elaborate or provide an example. Will check on this again later, currently 3am here. – nakakapagpabagabag Jun 24 '22 at 18:03
  • I'm not sure that I understand what the goal is. How are you using `createBody` outside of the example that it would need to be modified? – Jake Worth Jun 24 '22 at 18:35
  • The goal is to make changes on `createBody` before executing `run_test!`. `run_test!` would then simulate an api request using `createBody` and it would also have the response data based from the `createBody` used. Having the ability to modify `createBody` before executing `run_test!` gives the flexibility of testing various response status and testing data from the response. – nakakapagpabagabag Jun 25 '22 at 09:20

1 Answers1

0

I assume response block works in the same way as context

post "Creates object", controller_action: :create do
  let(:createBody) do
    {
      name: "yes",
      type: "my_type",
      amount_cents: 200,
      parameters: {
        day: "today"
      },
      user_group_ids: [],
      user_ids: user_ids # now we can add a let(:user_ids) to each context
    }
  end

  response 201, "object created" do
    let(:user_ids) { [] } # empty since we're not using it here

    ...

    run_test! do |res|
      # this block works fine and can access createBody
      body = JSON.parse(res.body)
      expect(body["name"]).to eq(createBody[:name])
      expect(body["amount_cents"]).to eq(createBody[:amount_cents])
      expect(body["type"]).to eq(createBody[:type])
    end
  end

  # with users
  response 201, "autocharge rule created" do
    let(:user_ids) { [1, 2, 3] } # add required ids

    ...
    
    run_test! do |res|
      # this block works fine and can access createBody
      body = JSON.parse(res.body)
      expect(body["user_ids"]).to match_array(createBody[:user_ids]) # we can match by user_ids now
    end
  end
  ...
end
O. Larkin
  • 144
  • 1
  • 5
  • 1
    @o-larkin your answer led me to the right path. I had to do a `let (:my_user_ids) { [] }` above `let(:createBody) do`. I then had to do `user_ids: my_user_ids` inside the `createBody` block. Then doing `let(:user_ids) { ... }` inside the response blocks allowed me to modify `createBody` before `run_test!` – nakakapagpabagabag Jun 25 '22 at 09:25