Claire
Claire

Reputation: 3785

How to get view data during unit testing in Laravel

I would like to check the array given to a view in a controller function has certain key value pairs. How do I do this using phpunit testing?

//my controller I am testing


public function getEdit ($user_id)
{
    $this->data['user'] = $user = \Models\User::find($user_id);

    $this->data['page_title'] = "Users | Edit";

    $this->data['clients'] = $user->account()->firstOrFail()->clients()->lists('name', 'id');

    $this->layout->with($this->data);

    $this->layout->content = \View::make('user/edit', $this->data);
}

//my test
public function testPostEdit (){

    $user = Models\User::find(parent::ACCOUNT_1_USER_1);

    $this->be($user);

    $response = $this->call('GET', 'user/edit/'.parent::ACCOUNT_1_USER_1);   

    //clients is an array.  I want to get this 
    //array and use $this->assetArrayContains() or something
    $this->assertViewHas('clients');

    $this->assertViewHas('content');

}

Upvotes: 15

Views: 33142

Answers (8)

Claire
Claire

Reputation: 3785

TL;DR; Try $data = $response->getOriginalContent()->getData();


I found a better way to do it. I wrote a function in the TestCase which returns the array I want from the view data.

protected function getResponseData($response, $key){

    $content = $response->getOriginalContent();

    $data = $content->getData();

    return $data[$key]->all();

}

So to get a value from the $data object I simply use $user = $this->getResponseData($response, 'user');

Upvotes: 19

Yevgeniy Afanasyev
Yevgeniy Afanasyev

Reputation: 41400

I have had the same problem, but my case was a bit special, because I push my data to view via view()->share($params); and in such cases the solution: $content = $response->getOriginalContent()->getData(); does not give the data out.

and I could not use $response->assertViewHas(...) because my data was objects (models) and I needed to verify object properties (keys and id-s).

So my solution was

$data = $response->original->gatherData();
$this->assertSame($currency->key, $data['currency']->key);

Tested on Laravel 8

Upvotes: 0

Looking for something like this in 2019, I got: $response->getData()->data[0]->...my properties

Still looking for a simpler way to access it.

Upvotes: 0

berrberr
berrberr

Reputation: 1960

So looking at how assertViewHas is implemented HERE it looks like, what the method does, is access the view's data after this call:

$response = $this->client->getResponse()->original;

In your code, the line:

$response = $this->call('GET', 'user/edit/'.parent::ACCOUNT_1_USER_1);

essentially returns the same thing as the line above it, namely a \Illuminate\Http\Response (which extends the symfony component \HttpFoundation\Response)

So, inside the assertViewHas function it looks like laravel accesses the data using $response->$key, so I would try to access the clients and 'content' variables through the $response object.

If that doesn't work try searching around the TestCase file in the Laravel framework ... I'm sure the answer is in there somewhere. Also try to dump the $response object and see what it looks like, there should be some clues there.

The first thing I would try, though, is accessing your data through the $response object.

Upvotes: 4

Claire
Claire

Reputation: 3785

I managed it by doing it in a messy way. I used assertViewHas:

$this->assertViewHas('clients', array('1' => 'Client 1', '6' => 'Client2'));

Upvotes: 6

cmac
cmac

Reputation: 3268

Inside a test case use:

$data = $this->response->getOriginalContent()->getData();

Example:

<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class HomeTest extends TestCase
{
    /**
     * A basic test example.
     *
     * @return void
     */
    public function testExample()
    {
        $data = $this->response->getOriginalContent()->getData();

        // do your tests on the data
    }
}

Example dumping data so you can see what in data(array) passed to view:

<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class HomeTest extends TestCase
{
    /**
     * A basic test example.
     *
     * @return void
     */
    public function testExample()
    {
        $data = $this->response->getOriginalContent()->getData();
        dd($data);
    }
}

Should get something back like what's in image:

enter image description here

Upvotes: 9

MURATSPLAT
MURATSPLAT

Reputation: 4830

You can access data in the response and it can be checked..

public function testSimpleLastProducts() {        

    $res = $this->call('GET', '/');

    $this->assertResponseOk();

    $this->assertViewHas('lastProducts');

    $lastProductOnView = $res->original['lastProducts'];

    $this->assertEquals(6, count($lastProductOnView));       

}

Upvotes: 4

rockstardev
rockstardev

Reputation: 13537

This worked for me:

$response->getSession()->get("errors")

And from there you can check the contents of the message box for whatever error you might want verify.

Upvotes: 0

Related Questions