DEV Community

Cover image for My First OpenAI Streaming Example: The Code, the Tests, and the Edge Cases
Virginia Nyambura  Mwega
Virginia Nyambura Mwega

Posted on

My First OpenAI Streaming Example: The Code, the Tests, and the Edge Cases

I wanted to understand AI streaming by building it—not just reading about it.

So I added a streaming command to my OpenAI SDK practice project using JavaScript and the OpenAI Responses API.

The goal was simple: instead of waiting for the entire AI response, display text fragments as they arrive.

Along the way, I got to practise something I care about just as much as the implementation: making an example understandable, testable, and useful to the next developer.

Here is what I built and what I learned.

Project: OpenAI SDK Docs Practice on GitHub

1. The streaming function

The core implementation is a small asynchronous function:

export async function streamText(client, prompt, onText) {
  if (typeof prompt !== "string" || !prompt.trim()) {
    throw new Error("Prompt is required.");
  }

  if (typeof onText !== "function") {
    throw new Error("A text callback is required.");
  }

  const stream = await client.responses.create({
    model: MODEL,
    input: prompt,
    stream: true,
  });

  for await (const event of stream) {
    if (event.type === "response.output_text.delta") {
      onText(event.delta);
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

MODEL is defined elsewhere in the project.

A few things are happening here:

  • I validate the prompt before making the request.
  • I validate the callback so the caller has a way to receive text.
  • I enable streaming in the API request.
  • I consume the asynchronous event stream.
  • I forward only text-delta events to the callback.

In the command-line interface, the callback uses process.stdout.write() to display each fragment as it arrives.

To run the example with a valid API key configured locally:

node index.js stream "Explain how an API works"
Enter fullscreen mode Exit fullscreen mode

The project uses OPENAI_API_KEY from a local .env file. Never commit a real API key to your repository.

2. What I decided to test

I didn't want to stop at checking that the function returned without throwing.

Because streaming is event-driven, I wanted to check what happened as different events arrived.

I created a mocked client that yields simulated events, including two text fragments and a completion event.

The test verifies that the received fragments are:

["Hello", ", developer!"]
Enter fullscreen mode Exit fullscreen mode

Joining them produces:

Hello, developer!
Enter fullscreen mode Exit fullscreen mode

The completion event isn't forwarded to the text callback.

I also added coverage for:

  • Ignoring non-text events
  • Rejecting an empty prompt
  • Rejecting a missing callback
  • Propagating an SDK error when stream startup fails

This makes the tests repeatable without depending on a network connection or consuming API usage.

3. The result—and an important limitation

The latest reported run of the project's automated test suite was:

19 passed, 0 failed.

That is a useful milestone, but I want to be precise about what it means.

The streaming tests use mocked events. I haven't tested a live API stream because I don't currently have an API key.

The tests verify my application's behavior with the events and failures I simulate. They don't prove that a real provider request succeeds or that the implementation handles every possible interruption.

My next improvements would include testing a stream interrupted after some text has already arrived, defining how partial output should be reported, and verifying a live integration when credentials are available.

4. The documentation is part of the feature

I also documented the implementation in STREAMING-COOKBOOK.md.

It covers:

  • Prerequisites
  • How the streaming function works
  • The command to run
  • How to execute the automated tests
  • Common setup and troubleshooting issues
  • What has and hasn't been verified

This exercise reminded me that a code example is much more useful when someone else can follow it without guessing.

A working snippet alone doesn't explain how to configure it, test it, or diagnose a failure.

5. What I learned about Developer Experience

The biggest lesson wasn't simply how to use stream: true.

It was how much of the developer experience lives around the API call:

Validate → Request → Consume events → Handle errors → Test → Document

Every step gives the next developer more confidence and fewer surprises.

I'm building these examples as part of my journey into AI Developer Documentation and Developer Experience. I want to be able to build the integration, understand its limitations, and explain it clearly—not just write a tutorial around code I haven't tested.

If you'd like to explore the project, here's the repository:

OpenAI SDK Docs Practice

I'd love to learn from other developers

When you're implementing a streaming API, which edge case do you make sure to test first?

  • A failure before the stream starts
  • A connection dropping halfway through
  • Cancellation when the user leaves the page
  • Handling partial output after a failure

I'd be interested to hear how you approach it.


Verification note: Automated tests passed in the latest reported run, using mocked streaming events. Live API streaming has not yet been verified.

Top comments (0)