Yeah, I realized the same thing; this aspect really makes it harder to keep the system simple, naturally. I've thought about different ways of approaching this, considering chained requests as a possibility.
Scenario: Push money to an existing debit card
Given I have sufficient funds in my marketplace
And I have a tokenized debit card
When I POST to /cards/:debit_card_id/credits with the JSON API body:
"""
{
"credits": [{
"amount": 1234
}]
}
"""
Then I should get a 201 Created status code
And the response is valid according to the "credits" schema
And the fields on this credit match:
"""
{
"status": "succeeded"
}
"""
And the credit was successfully created
There's several things in there like "And I have a tokenized debit card" that setup the scenario to be able to do things like "/cards/:debit_card_id/credits", which refers to an actual card ID created in the test API.
That's really quite impressive! I hadn't realized that you meant that an endpoint can be referenced "in the abstract" without explicit parameters, which makes for much easier integration.
For some reason, though, I feel like the natural language would actually intimidate me. Where are ideas like "sufficient funds" defined?
Given(/^I have sufficient funds in my marketplace$/) do
step 'I have tokenized a card'
@client.post("/cards/#{@card_id}/debits", {
amount: 500000
})
end
Here's another example from the scenario above:
Given(/^I have a tokenized debit card$/) do
@client.post('/cards',
{
name: "Johannes Bach",
number: "4342561111111118",
expiration_month: "05",
expiration_year: "2015"
}
)
@debit_card_id = @client['cards']['id']
@client.add_hydrate(:debit_card_id, @debit_card_id)
end
As a simple example:
1. Create customer
2. Add tokenized card to customer
3. Charge the card
Step 2 requires the HREF/ID of the customer. Step 3 requires the HREF/ID of the card.