Skip to main content

TypeScript Integration

wdio-api-runner is built with TypeScript and provides full type support. All APIs are strongly typed, enabling IDE autocompletion, compile-time error checking, and self-documenting code.

Type Definitions

The package includes comprehensive TypeScript definitions that are automatically available when you import from wdio-api-runner.

Typed Responses

Generic Response Types

interface User {
id: number
name: string
email: string
}

// Type the response data
const response = await api.get<User>('/users/1')
console.log(response.data.name) // TypeScript knows this is string

Complex Types

interface PaginatedResponse<T> {
data: T[]
total: number
page: number
pageSize: number
}

interface User {
id: number
name: string
}

const response = await api.get<PaginatedResponse<User>>('/users?page=1')
console.log(response.data.data[0].name) // Fully typed
console.log(response.data.total) // number

API Response Type

import type { ApiResponse } from 'wdio-api-runner'

async function fetchUser(id: string): Promise<ApiResponse<User>> {
return api.get<User>(`/users/${id}`)
}

const response = await fetchUser('123')
// response.status: number
// response.data: User
// response.ok: boolean
// response.duration: number

Request Options Type

import type { RequestOptions } from 'wdio-api-runner'

const options: RequestOptions = {
headers: {
'X-Custom': 'value'
},
timeout: 5000,
retries: 3,
retryDelay: 1000
}

await api.get('/users', options)

GraphQL Types

import type { GraphQLResponse, GraphQLError } from 'wdio-api-runner'

interface GetUserQuery {
user: {
id: string
name: string
}
}

const response = await graphql.query<GetUserQuery>(`
query GetUser($id: ID!) {
user(id: $id) { id name }
}
`, { id: '123' })

if (response.isSuccess) {
const user = response.data.data.user // Typed as { id: string, name: string }
}

Extending Global Types

Add custom properties to the API client:

// types/wdio-api-runner.d.ts
declare module 'wdio-api-runner' {
interface ApiClient {
customMethod(data: MyData): Promise<ApiResponse<MyResult>>
}
}

Config Type Safety

// wdio.conf.ts
import type { Options } from '@wdio/types'

export const config: Options.Testrunner = {
runner: 'api',

apiRunner: {
baseUrl: 'https://api.example.com',
timeout: 30000,
headers: {
'Content-Type': 'application/json'
}
}
}

Type Guards

import type { ApiResponse } from 'wdio-api-runner'

function isSuccessResponse<T>(response: ApiResponse<T>): response is ApiResponse<T> & { ok: true } {
return response.ok
}

const response = await api.get<User>('/users/1')

if (isSuccessResponse(response)) {
// TypeScript knows response.ok is true here
console.log(response.data)
}

Utility Types

import type {
ApiResponse,
ApiClientOptions,
RequestInterceptor,
ResponseInterceptor
} from 'wdio-api-runner'

// Create a typed interceptor
const authInterceptor: RequestInterceptor = async (url, options) => {
return {
...options,
headers: {
...options.headers,
'Authorization': 'Bearer token'
}
}
}

// Create a typed response interceptor
const logInterceptor: ResponseInterceptor = async (response) => {
console.log(`${response.status}: ${response.duration}ms`)
return response
}

Strict Null Checks

The types are designed to work well with strictNullChecks:

const response = await api.get<User | null>('/users/maybe-exists')

if (response.data) {
// TypeScript knows response.data is User here
console.log(response.data.name)
}

Error Types

interface ApiError {
code: string
message: string
details?: Record<string, string[]>
}

const response = await api.post<User>('/users', invalidData)

if (!response.ok) {
const error = response.data as ApiError
console.log(error.message)
}

Generic Test Helpers

async function expectSuccess<T>(
response: ApiResponse<T>,
expectedStatus = 200
): asserts response is ApiResponse<T> & { ok: true } {
expect(response.status).toBe(expectedStatus)
expect(response.ok).toBe(true)
}

async function expectError<T>(
response: ApiResponse<T>,
expectedStatus: number
): void {
expect(response.status).toBe(expectedStatus)
expect(response.ok).toBe(false)
}

// Usage
const response = await api.get<User>('/users/1')
expectSuccess(response)
// TypeScript now knows response.ok is true
console.log(response.data.name)

tsconfig.json Recommendations

{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"esModuleInterop": true,
"strict": true,
"skipLibCheck": true,
"types": [
"node",
"@wdio/globals/types",
"@wdio/mocha-framework"
]
},
"include": [
"test/**/*.ts",
"wdio.conf.ts"
]
}