Test backend APIs
In this guide, we’ll show you how to test backend APIs with Playwright. We will use Kinde refresh tokens for maintaining authenticated sessions in automated tests, including token rotation. Learn more about testing backend APIs with Kinde.
What you need
Link to this section- Completed the Playwright setup
- A test user and a running Kinde application.
Configure Kinde refresh tokens
Link to this section-
Update your
.envfile with therefresh token. You can obtain the refresh token by following this step.# ...your other environment variables...KINDE_REFRESH_TOKEN=your-kinde-refresh-tokenImportant: Make sure to add
.envto your.gitignorefile to prevent committing tokens to source control. -
Create an API setup file:
Terminal window mkdir tests/apitouch tests/api/api.setup.ts -
Add the following to the file to refresh tokens before tests run:
tests/api/api.setup.ts import { test as setup, expect } from '@playwright/test'import { writeFileSync, mkdirSync } from 'fs'import { join, dirname } from 'path'setup('refresh API tokens', async ({ request }) => {const response = await request.post(`${process.env.KINDE_ISSUER_URL}/oauth2/token`,{form: {client_id: process.env.KINDE_CLIENT_ID!,grant_type: 'refresh_token',refresh_token: process.env.KINDE_REFRESH_TOKEN!,},})expect(response.ok()).toBeTruthy()const tokens = await response.json()// Store access token in a fileconst tokenPath = join(__dirname, '../../playwright/.auth/api-token.json')const tokenDir = dirname(tokenPath)// Ensure directory existsmkdirSync(tokenDir, { recursive: true })writeFileSync(tokenPath,JSON.stringify({access_token: tokens.access_token,refresh_token: tokens.refresh_token,expires_at: Date.now() + tokens.expires_in * 1000,},null,2))// Important: Update your secrets manager with the new refresh token// for subsequent test runs// const newRefreshToken = tokens.refresh_token}) -
Update the
playwright.config.tsprojects configuration to add the following:playwright.config.ts //... previous code ...projects: [// API setup project - refreshes tokens{name: 'setup',testMatch: /api\/.*\.setup\.ts/,},// API tests - use refreshed tokens{name: 'api-tests',testMatch: /api\/.*\.spec\.ts/,dependencies: ['setup'],},]
Create and run sample tests
Link to this sectionIf you are starting from scratch, you can run sample tests using the Kinde starter test application.
-
Create a test file:
Terminal window touch tests/api/kinde-api.spec.ts -
Open
kinde-api.spec.tsand add the following example tests:tests/api/kinde-api.spec.ts import { test, expect } from '@playwright/test'import { readFileSync } from 'fs'import { join } from 'path'test.describe('Kinde API Tests', () => {let accessToken: stringtest.beforeAll(() => {// Load access token from file created by api.setup.tsconst tokenPath = join(__dirname, '../../playwright/.auth/api-token.json')const tokenData = JSON.parse(readFileSync(tokenPath, 'utf-8'))accessToken = tokenData.access_token})test('can fetch user profile', async ({ request }) => {const response = await request.get('/api/profile', {headers: {Authorization: `Bearer ${accessToken}`,},})expect(response.ok()).toBeTruthy()const data = await response.json()expect(data.email).toBe(process.env.TEST_USER_EMAIL)})test('cannot fetch user profile with invalid token', async ({ request }) => {const response = await request.get('/api/profile', {headers: {Authorization: `Bearer invalid-token`,},})expect(response.status()).toBe(401)})test('can update user settings', async ({ request }) => {const response = await request.patch('/api/settings', {headers: {Authorization: `Bearer ${accessToken}`,},data: {theme: 'dark',},})expect(response.ok()).toBeTruthy()})}) -
Run the tests using the following command:
Terminal window npx playwright test --uiYou should see the tests pass.
You have successfully run the tests and validated that the API is working as expected. Use this approach to test your API endpoints and ensure they are working as expected.
CI/CD integration
Link to this sectionFor CI/CD environments, use environment variables instead of .env:
name: API Tests
on: push: branches: [main]
jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 - name: Install dependencies run: npm ci - name: Install Playwright browsers run: npx playwright install --with-deps - name: Run Playwright API tests run: npx playwright test --project=api-tests env: KINDE_ISSUER_URL: ${{ secrets.KINDE_ISSUER_URL }} KINDE_CLIENT_ID: ${{ secrets.KINDE_CLIENT_ID }} TEST_APP_URL: ${{ secrets.TEST_APP_URL }} TEST_USER_EMAIL: ${{ secrets.TEST_USER_EMAIL }} KINDE_REFRESH_TOKEN: ${{ secrets.KINDE_REFRESH_TOKEN }}