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

Add code blocks to the ch16 (get-authenticated-user) #29

Merged
merged 1 commit into from
Nov 13, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 57 additions & 27 deletions knpu/get-authenticated-user.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,60 +9,90 @@ create the products in `FeatureContext`.
I want to test that this table *does* show the correct author when its set. Create
a new scenario to describe this:

Scenario: Products show author
Given I am logged in as an admin
[[[ code('4c40dd7480') ]]]

Instead of just saying there are five products I'll say:

And I author 5 products
[[[ code('5847ac3fba') ]]]

This *is* new language that will need a step definition. To save time, we can go
directly to the products page,
directly to the products page:

When I go to "/admin/products"
Then I should not see "Anonymous"
[[[ code('6edea384d7') ]]]

Since "I" - some admin user - will be the author of the products, they should all
show "admin": none will say "Anonymous". And we will *only* have these 5 products
because we're clearing the database between each scenario to keep things independent.

Run just this new scenario by using its line number.
Run just this new scenario by using its line number:

Great - copy the `iAuthorProducts` function code and paste it into our handy `FeatureContext`
class - near the other product function. These two functions will be similar, so
we should reuse the logic. Copy the internals of `thereAreProducts`, make a new
`private function createProducts`. Pass it `$count` as an argument and also an optional
User object which will be the author for those products. Now, add an if statement
that says, if `$author` is passed then, `$product->setAuthor()`. I already have that
relationship setup with in Doctrine. Great!
```bash
$ ./vendor/bin/behat features/web/product_admin.feature:13
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

THANK you for adding commands when we run command - I also try to do this, but I don't catch them all. But (unlike the core Symfony docs) - we don't need to add a $ - we add a > via CSS when it renders :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, sorry... I forgot about this CSS feature here.

```

In `thereAreProducts`, change the body of this function to `$this->createProducts($count);`.
Do the same thing in `iAuthorProducts` for now. Clearly, this is still not setting
the author. But I want to see if it executes first and then we'll worry about setting
the author.
Great - copy the `iAuthorProducts()` function code and paste it into our handy `FeatureContext`
class - near the other product function:

[[[ code('a2d4b5fdea') ]]]

These two functions will be similar, so we should reuse the logic. Copy the internals
of `thereAreProducts`, make a new `private function createProducts()`. Pass it `$count`
as an argument and also an optional User object which will be the author for those products:

[[[ code('8bbd967c08') ]]]

Now, add an if statement that says, if `$author` is passed then, `$product->setAuthor()`:

[[[ code('954b443f9e') ]]]

I already have that relationship setup with in Doctrine. Great!

In `thereAreProducts()`, change the body of this function to `$this->createProducts($count);`:

[[[ code('95e36de658') ]]]

Do the same thing in `iAuthorProducts()` for now:

[[[ code('acd4d6cbd4') ]]]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And the same question, should we wrap this single line with method name like:

public function iAuthorProducts($count)
{
    $this->createProducts($count);
}

Looks like we get it from context above

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I agree - we should give it more context. Sometimes, we're working in a function, and then we add a new line to it, then another new line later. In these cases, it seems less important to include the "context" on the 2nd and 3rd code-blocks (but still maybe not a bad thing). But when we switch to work on a different function - like we do here - then yea, definitely :). I'm in the code block editor right now, so I'll tweak these.


Clearly, this is still not setting the author. But I want to see if it executes first
and then we'll worry about setting the author.

## Who is "I" in a Scenario?

Cool! It runs... and fails because anonymous *is* still shown on the page. The question
now is: how do we get the current user? The step says "I author". But who is "I" in this
case? In `product_admin.feature`, you can see that "I" is whomever we logged in as.
We didn't specify what the username should be for that user, but whoever is logged
in is who "I" represents.
case? In `product_admin.feature`:

[[[ code('88c42ae944') ]]]

You can see that "I" is whomever we logged in as. We didn't specify what the username
should be for that user, but whoever is logged in is who "I" represents.

When we worked with the `ls` scenarios earlier, we needed to share the command output
string between the steps of a scenario. In this case, we have a similar need: we
need to share the user object from the step where we log in, with the step where
"I" author some products. To share data between steps, create a new `private $currentUser;`.
"I" author some products. To share data between steps, create a new `private $currentUser;`:

[[[ code('100d047bcd') ]]]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@weaverryan Should we add more context here and wrap this property with class in the code block? I show a single line of property declaration here in code block now

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1


In `iAmLoggedInAsAnAdmin()`, add `$this->currentUser = $this->thereIsAnAdminUserWithPassword()`:

[[[ code('9d15e806ff') ]]]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I gave this more context too - it was just the single line, I expanded it to show the method name above (and the opening { and close } after it.


In `iAmLoggedInAsAdmin`, add `$this->currentUser = $this->thereIsAnAdminUserWithPassword()`.
Click to open that function. It creates the `User` object of course, but now we need
to also make sure it returns that.
to also make sure it returns that:

[[[ code('d7766a9278') ]]]

And that's it! This login step will cause the `currentUser` property to be set and
in `iAuthorProducts` we can access that and pass it into `createProducts()` so that
each product us authored by us. It's pretty common to want to know *who* is logged
in, so you'll likely want to use this in your project.
in `iAuthorProducts()` we can access that and pass it into `createProducts()` so that
each product us authored by us:

[[[ code('15862f69e1') ]]]

It's pretty common to want to know *who* is logged in, so you'll likely want to use
this in your project.

And hey it even passes! Now you can continue to write scenarios in terms of actions
that "I" take and we will actually know who "I" is.