How to mock 3rd party API calls in next.js integration tests?

118 Views Asked by At

I am calling OpenAI APIs from my next routes, I can intercept browser requests using nock library like below, but it won't mock server-side API calls since I am not calling OpenAI API from the browser directly.

import nock from 'nock';

nock(/.+openai.+/)
  .get('/api')
  .reply(200, {
    choices: [
      {
        message: {
          content: 'Here is your AI query answer',
        },
      },
    ],
  });

below is my playwright.config.ts

import { defineConfig, devices } from '@playwright/test';
import dotenv from 'dotenv';
import path from 'path';

dotenv.config({ path: '.env.test' });

// Use process.env.PORT by default and fallback to port 3000
const PORT = process.env.PORT ?? 3000;

// Set webServer.url and use.baseURL with the location of the WebServer respecting the correct set port
const baseURL = `http://localhost:${PORT}`;

// *.check.spec.ts files use ENVIRONMENT_URL instead of baseURL
process.env.ENVIRONMENT_URL = baseURL;

/**
 * See https://playwright.dev/docs/test-configuration.
 */
export default defineConfig({
  // Timeout per test
  timeout: 30 * 1000,
  // Run tests in files in parallel
  fullyParallel: false,
  // Fail the build on CI if you accidentally left test.only in the source code.
  forbidOnly: !!process.env.CI,
  // Retry on CI only
  retries: process.env.CI ? 2 : 0,
  // Opt out of parallel tests on CI
  workers: process.env.CI ? 1 : undefined,
  // Limit the number of failures on CI to save resources
  maxFailures: process.env.CI ? 10 : undefined,
  // Reporter to use. See https://playwright.dev/docs/test-reporters
  reporter: [['list'], ['junit', { outputFile: 'playwright-junit.xml' }]],

  // Run your local dev server before starting the tests:
  // https://playwright.dev/docs/test-advanced#launching-a-development-web-server-during-the-tests
  webServer: {
    command: 'pnpm run dev',
    url: baseURL,
    timeout: 120 * 1000,
    reuseExistingServer: !process.env.CI,
  },

  // Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions.
  use: {
    // Use baseURL so to make navigation relative.
    // More information: https://playwright.dev/docs/api/class-testoptions#test-options-base-url
    baseURL,

    // Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer
    trace: 'on-first-retry',
    extraHTTPHeaders: {
      // We set this header per GitHub guidelines.
      Accept: 'application/json',
    },
  },
  globalSetup: require.resolve('./globalPlaywrightSetup.ts'),
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    ...(process.env.CI
      ? [
          {
            name: 'firefox',
            use: { ...devices['Desktop Firefox'] },
          },
          {
            name: 'webkit',
            use: { ...devices['Desktop Safari'] },
          },
        ]
      : []),
  ],
});

One hack going to work if I include the nock call in the API routes itself but that would change the production code. The problem is when I am intercepting like below it would run in browser runtime, not in node runtime so I am not able to mock 3rd party calls.

  test.describe('GET api/query', () => {
    test('should answer query properly using AI', async ({
      request,
    }) => {
      nock(/.+openai.+/)
        .get('/api')
        .reply(200, {
          choices: [
            {
              message: {
                content: 'Here is your AI query answer',
              },
            },
          ],
        });

      const response = await request.get(
        `/api/query`,
      );
      expect(response.status()).toBe(HttpStatusCode.Ok);

      const responseJson = await response.json();
      expect(responseJson).toHaveProperty('query');
      expect(responseJson.query).toContain("Here is your AI query answer");
    });
  });

I think one way could be when I start pnpm run dev from the playwright, If I have any way to mock OpenAI dependency there itself or start a different server like pnpm run test:dev this command would start the same server but only mocking OpenAI and rest of the routes would work as a same.

I am not sure if pnpm allows us to do that mock some interfaces of dependencies in package.json

0

There are 0 best solutions below