zenstruck / browser

A fluent interface for your Symfony functional tests.
MIT License
185 stars 17 forks source link

Support for testing CSV responses #108

Closed benr77 closed 1 year ago

benr77 commented 1 year ago

Hi Kevin,

Is there any support, or plans, to support testing CSV responses? I guess in a similar manner to the JSON response testing that's currently available.

Thanks

kbond commented 1 year ago

I don't have any plans for this but seems like a reasonable request. I don't know that it's common enough to make it a method on KernelBrowser but I'd be ok adding a Csv object in the same manner as the current Json one.

Usage would be:

$browser->use(function(CSV $csv) {
   $csv->assertions...
});

What type of assertions would you like to see? Feel free to work on a PR to explore further!

benr77 commented 1 year ago

I guess the main assertions could be something like:

// The number of columns
assertColumnCount(int $count)

// Pass an array of column names that should be matched, in order
assertColumnNames(array $columnNames)

// The number of rows, minus 1 for the header row
assertDataRowCount(int $count)

Can you think of any other obvious ones?

kbond commented 1 year ago

Makes sense, think anything related to the data would be important?

assertContains(array $expectedRow)?

If we have it a mixin for Expectation (from zenstruck/assert) like Json is, we'd have the above out of the box.

benr77 commented 1 year ago

I'll try and put something together in a PR but it won't be until tomorrow as the earliest.

benr77 commented 1 year ago

One question about my current solution, which isn't working please - can you see what's wrong with this:

$this->browser()
    ->visit('/customer/export/csv')
    ->assertSuccessful()
    ->use(function (AppBrowser $browser, Crawler $crawler)
    {
        [$headers] = explode("\n", $crawler->text());
        $this->assertNotEmpty($headers, 'There are no customers in the export!');
    })
;

Calling $crawler->text() gives me a InvalidArgumentException: The current node list is empty. error. However, looking at the failed test output, the contents of the CSV file are actually there.

Should I be using something other than $crawler->text() to get the CSV data?

Thanks

nikophil commented 1 year ago

Hi @benr77

I don't think you need to use the crawler here: couldn't you reproduce the same behavior than here and create a new \Zenstruck\Browser\Csv class?

kbond commented 1 year ago

One question about my current solution

There actually doesn't appear to be a great way to get the raw response body currently. Crawler is failing because it isn't html/xml.

We should add Browser::content().

benr77 commented 1 year ago

Will this be sufficient inside Zenstruck\Browser ?

final public function content(): string
{
    return $this->client()->getResponse()->getContent();
}

My test now looks like this, and works fine:

$this->browser()
    ->visit('/customer/export/csv')
    ->assertSuccessful()
    ->use(function (AppBrowser $browser)
    {
        [$headers] = explode("\n", $browser->content());
        $this->assertNotEmpty($headers, 'There are no customers in the export!');
    })
;
nikophil commented 1 year ago

Hi @benr77

I'm closing this issue since I think it's resolved.