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

[Feature]: Attach 3rd party HTTP client request/response info to test steps #33481

Open
bdcarr opened this issue Nov 6, 2024 · 2 comments
Open

Comments

@bdcarr
Copy link

bdcarr commented Nov 6, 2024

🚀 Feature Request

Similar request to #32748, but I'd like it expanded to support 3rd party request clients such as Axios. It seems like you're planning to implement that request, so my request is to expose whatever function you end up using to attach request info to test steps. I don't mind if I have to transform the Axios/whatever data structure to fit your API, I understand maintaining such a function to support various popular libraries would be a burden.

Example

I guess I'd use it much like my current solution below, except instead of creating new steps with the request/response info jammed into the step name, I'd do something like:

private async attachResponseToTest(responseOrError: AxiosResponse | AxiosError) {
  if (process.env.ATTACH_RESPONSES_TO_TEST !== 'true') return;
  const response = axios.isAxiosError(responseOrError) ? responseOrError?.response : responseOrError;

  const { data, config } = response;
  await test.step.attachHttpResponse({
    request: {
      method: config?.method?.toUpperCase(),
      path: config?.url,
      headers: etc,
    },
    response: {
      status: response?.status,
      data: data,
    },
  });
}

This function would be registered as an interceptor for responses for our Axios instances.

Motivation

We already used Playwright for UI tests for a long time before we started doing API testing with it, so we've built up quite a library of functions for interacting with our API and they all use a customised instance of Axios. When we started doing API stuff in the same framework, we had a look at the built-in HTTP client but it was missing certain config that we need (more on that below), so I hacked a slightly dodgy workaround for attaching requests/responses to the test steps. This function gets set as a request & response interceptor on Axios:

private async attachResponseToTest(responseOrError: AxiosResponse | AxiosError) {
  if (process.env.ATTACH_RESPONSES_TO_TEST !== 'true') return;
  const response = axios.isAxiosError(responseOrError) ? responseOrError?.response : responseOrError;

  const { data, config } = response;
  await test.step(`${config?.method?.toUpperCase()} ${config?.url}`, async () => {
    await test.step(`Request: ${config?.data}`, async () => {});
    await test.step(`Response: ${response?.status} ${response?.statusText} ${stringify(data)}`, async () => {});
  });
}

It's not perfect (you have to inspect HTML in the report to see more than the first few dozen chars of the 'step name', and it does eventually truncate) but it's done the job well enough for now:

Image

Why we stuck with Axios rather than ApiRequestContext

@Skn0tt asked:

I'm curious, what's that config that you're missing in the builtin API Client? What would we need to build so you can migrate from Axios?

These are the three reasons I found to stick with Axios during my little investigation in September.

  1. Interceptors - we use these a bunch to do things like refresh auth tokens and transform error responses for cleaner logging. I keep finding more uses for them and don't want to give them up.
  2. The function to create an ApiRequestContext is async. We instantiate our axios clients inside class constructors, where you can't use await, so changing clients would seem to involve refactoring everything.
  3. We pass the below option to axios.create() to work around some deficiency in the local dev environment. At the time I couldn't find a way to do the same thing with ApiRequestContext. It looks like maybe we could do it with your clientCertificates option now, but I'm not familiar with the issue:
httpsAgent: new https.Agent({
  rejectUnauthorized: env !== 'local',
}),

Thank you for your consideration ❤

@yury-s
Copy link
Member

yury-s commented Nov 7, 2024

The step attachments from #32748 should cover your current needs. I leave this request open though, as we could provide better support for API testing and have third-party libraries represented in the traces and network tab of the trace viewer.

@Skn0tt
Copy link
Member

Skn0tt commented Nov 12, 2024

We pass the below option to axios.create() to work around some deficiency in the local dev environment. At the time I couldn't find a way to do the same thing with ApiRequestContext.

I think you should be able to achieve this with ignoreHTTPSErrors:

Have you given that a try? Does it help your usecase?

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

No branches or pull requests

3 participants