Hello,
I would like to know if you can give a little hand here. Im using your package (L5 branch) to secure some of my API uri's.
So now decided to dive in the testing world(nood here) and I can't seem to get this right when testing a protected uri.
$this->call('GET', 'v1/me', [], [], [], ['HTTP_Authorization' => 'Bearer <token here>' ]);
If I hard code the token in the call method it works fine but off course I first wanna get a User from my testing DB and then generate a token to pass it the call method(if this even make sense for a test)
Do you have a small example on how to this or point me in some direction?
Thanks in advance,
Helder
Hi. Did you managed to get your tests working ? I have the same problem and could use some help.
Not OP, but here's how I did this in my code.
For most tests, I need to be logged in but I don't want to test auth, so I have this function in my base TestCase class that logs in as a specific user that I call before running each test:
protected function login($user_id = 1)
{
$user = User::find($user_id);
$this->token = JWTAuth::fromUser($user);
JWTAuth::setToken($this->token);
Auth::login($user);
}
Every time I call a route, I then pass in the token in the headers:
protected function callRoute($method, $route, $data = [], $headers = [])
{
if ($this->token && !isset($headers['Authorization'])) {
$headers['HTTP_Authorization'] = "Bearer: $this->token";
}
return $this->call(
$method,
"/api$route",
[],
[],
[],
$headers,
json_encode($data)
);
}
For testing auth itself, I do this:
public function testLogin()
{
$this->seed('UserSeeder');
// callRoute's parameters: 1. Method 2. Url 3. Data 4. Headers
$resp = $this->callRoute('POST', '/auth', ['email' => '[email protected]', 'password' => 'password']);
$this->assertOk($resp);
// Get the token
$data = json_decode($resp->getContent(), true);
$this->assertArrayHasKey('token', $data);
// At this point, I could call another api endpoint and pass in the token. Something like this:
// $this->callRoute('POST', '/example', $data, ['HTTP_Authorization' => 'Bearer: ' . $data['token']]);
}
$this->callRoute and $this->assertOk are custom shortcut functions that I wrote to avoid lots of boilerplate.
Thank you @denaje for the code. That helped a ton. Here is a slightly revised version that functions more like the parent call method.
Extend the TestCase class with:
protected function createAuthenticatedUser()
{
$this->user = factory(App\Models\User::class, 'test')->create();
$this->token = JWTAuth::fromUser($this->user);
JWTAuth::setToken($this->token);
Auth::attempt(['username' => $this->user->username, 'password' => $this->user->password]);
}
protected function callAuthenticated($method, $uri, array $data = [], array $headers = [])
{
if ($this->token && !isset($headers['Authorization'])) {
$headers['Authorization'] = "Bearer: $this->token";
}
$server = $this->transformHeadersToServerVars($headers);
$this->call(strtoupper($method), $uri, $data, [], [], $server);
return $this;
}
Then use in tests like any other method:
public function testGetUser()
{
$this->createAuthenticatedUser();
$this->callAuthenticated('GET', route('auth::user'))->seeJsonStructure(['id']);
}
Most helpful comment
Thank you @denaje for the code. That helped a ton. Here is a slightly revised version that functions more like the parent
callmethod.Extend the TestCase class with:
Then use in tests like any other method: