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

Issue with TestResponse::streamedContent() when upgrading to Spectator v2 #202

Open
villfa opened this issue Nov 28, 2024 · 2 comments
Open

Comments

@villfa
Copy link

villfa commented Nov 28, 2024

Hello,

After upgrading Spectator to v2, I encountered an issue when using it in combination with \Illuminate\Testing\TestResponse::streamedContent().

Example Controller

Consider the following controller:

public function index(): StreamedResponse
{
    return response()->streamDownload(fn () => print('foo'));
}

Corresponding Test

Here’s the test for this controller:

public function testIndex(): void
{
    Spectator::using('my-specs.yaml');

    $response = $this->get('/foo')->assertSuccessful();

    self::assertSame('foo', $response->streamedContent());
}

Observed Behaviour

  • This test passed with Spectator v1.
  • After upgrading to Spectator v2, the test fails because streamedContent() returns an empty string.

Root Cause

The issue seems to originate in \Spectator\Validation\ResponseValidator. Specifically, it calls \Symfony\Component\HttpFoundation\StreamedResponse::sendContent() before \Illuminate\Testing\TestResponse::streamedContent() is invoked.

However, sendContent() should only be called once, as it consumes the stream. By the time TestResponse::streamedContent() is called, the stream has already been consumed, leaving no content for it to access.

Expected Behaviour

TestResponse::streamedContent() should return the expected streamed content, as it did in Spectator v1.


Let me know if any additional details would be helpful!

@spodmore
Copy link

Having the same issue. And just to add to this, I figured it doesn't matter if you assert valid response or not.

Also, it only fails if your actual response's Content-Type is one of the defined response types in the specification. E.g., I have 'text/csv':

content:
  text/csv:
    schema:
      type: object

(BTW with assertValidResponse(), it will fail with 'Unable to map [text/csv] to schema type [object]', I guess because the actual type is string.)

If I comment out that text/csv part, I get my content in TestResponse::streamedContent(). I get it as well if I use any other type that is not listed in the spec. Which means it goes into ResponseValidator::streamedContent() only if Content-Type of the response matches a content type from the specification.

@bastien-phi
Copy link
Collaborator

Thanks for the report. I did not have a lot of time lately, I'll try to look at this next week.
If somebody can open a PR with a failing test, it would save me a lot of time ! Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants