Skip to content

Logging Utility ​

A logging utility for Playwright tests that integrates with test reports, supports object logging, and provides step decorators.

Quick Start ​

typescript
import { log } from '@seontechnologies/playwright-utils'

// Basic logging
await log.info('Starting test')
await log.step('Test step shown in Playwright UI')
await log.success('Operation completed')
await log.warning('Something to note')
await log.error('Something went wrong')
await log.debug('Debug information')

Real Examples ​

From actual test files in this repository:

Basic Usage in Tests ​

typescript
// From playwright/tests/external/todo-with-logs.spec.ts
test.beforeEach(async ({ page }) => {
  await log.step('Navigate to TodoMVC app')
  await page.goto('https://demo.playwright.dev/todomvc')
})

test('Log demo', async () => {
  await log.info('Starting TodoMVC test suite with enhanced logging')

  // Object logging with debug level
  await log.debug({ timestamp: new Date(), recordCount: 42 })

  // Success logging
  await log.success('success!')

  // Step logging (shows in Playwright UI)
  await log.step(
    'You should not log an object here, steps only display strings'
  )

  // Objects work but show empty in test steps
  await log.info({ someText: 'objects will show empty in test steps' })
})

CRUD Operations with Auth Token ​

typescript
// From playwright/tests/sample-app/backend/crud-movie-event.spec.ts
test('should crud', async ({ authToken, addMovie, getAllMovies }) => {
  await log.info(authToken) // Log the auth token

  // Add movie with logging
  const { body: createResponse } = await addMovie(authToken, movie)
  const movieId = createResponse.data.id

  await log.step('isKafkaWorking: ' + isKafkaWorking)

  // Conditional logging based on environment
  if (isKafkaWorking) {
    await log.warning('Kafka is not working, skipping Kafka event checks')
  }
})

Auth Session Testing ​

typescript
// From playwright/tests/auth-session/auth-session-sanity.spec.ts
test('should have auth token available', async ({ authToken }) => {
  // Create safe token preview for logging
  const tokenPreview = createTokenPreview(authToken)
  await log.info(`Token available without explicit fetching: ${tokenPreview}`)
})

test('should reuse the same auth token', async ({ authToken }) => {
  const tokenPreview = createTokenPreview(authToken)
  await log.step(
    `Second test reuses the token without fetching again: ${tokenPreview}`
  )
})

Object Logging ​

Log objects directly for debugging:

typescript
// From real test examples
await log.debug({ timestamp: new Date(), recordCount: 42 })

// Object with success status
await log.success({
  todoItem: 'buy some cheese',
  count: 1
})

// Objects with custom options
await log.warning(
  { warning: 'API rate limit exceeded', code: 'WARN001' },
  { console: { enabled: true, colorize: true } }
)

File Logging ​

Enable file logging in your config:

typescript
// playwright/config/dev.config.ts
import { log, captureTestContext } from '@seontechnologies/playwright-utils'

// Configure file logging globally
log.configure({
  fileLogging: {
    enabled: true,
    outputDir: 'playwright-logs/organized-logs',
    forceConsolidated: false // One file per test
  }
})

// In your fixtures
base.beforeEach(async ({}, testInfo) => {
  captureTestContext(testInfo) // Required for file logging
})

Test Step Decorators ​

Create collapsible test steps in Playwright UI:

Page Object Methods ​

typescript
// From playwright/tests/external/todo-with-logs.spec.ts
class TodoPage {
  constructor(private page: Page) {
    this.name = 'TodoPage'
  }

  readonly name: string

  @methodTestStep('Add todo item')
  async addTodo(text: string) {
    await log.info(`Adding todo: ${text}`)
    const newTodo = this.page.getByPlaceholder('What needs to be done?')
    await newTodo.fill(text)
    await newTodo.press('Enter')
    await log.step('step within a decorator')
    await log.success(`Added todo: ${text}`)
  }

  @methodTestStep('Get all todos')
  async getTodos() {
    await log.info('Getting all todos')
    return this.page.getByTestId('todo-title')
  }
}

Function Helpers ​

typescript
// From real test files
const createDefaultTodos = functionTestStep(
  'Create default todos',
  async (page: Page) => {
    await log.info('Creating default todos')
    await log.step('step within a functionWrapper')
    const todoPage = new TodoPage(page)

    for (const item of TODO_ITEMS) {
      await todoPage.addTodo(item)
    }

    await log.success('Created all default todos')
  }
)

const checkNumberOfTodosInLocalStorage = functionTestStep(
  'Check total todos count fn-step',
  async (page: Page, expected: number) => {
    await log.info(`Verifying todo count: ${expected}`)
    const result = await page.waitForFunction(
      (e) => JSON.parse(localStorage['react-todos']).length === e,
      expected
    )
    await log.success(`Verified todo count: ${expected}`)
    return result
  }
)

Configuration ​

Defaults: console logging enabled, file logging disabled.

typescript
// Enable file logging in config
log.configure({
  console: true, // default
  fileLogging: {
    enabled: true,
    outputDir: 'playwright-logs',
    forceConsolidated: false // One file per test
  }
})

// Per-test override
await log.info('Message', {
  console: { enabled: false },
  fileLogging: { enabled: true }
})

Environment Variables ​

bash
# Disable all logging
SILENT=true

# Disable only file logging
DISABLE_FILE_LOGS=true

# Disable only console logging
DISABLE_CONSOLE_LOGS=true

Level Filtering ​

typescript
log.configure({
  level: 'warning' // Only warning, error levels will show
})

// Available levels (in priority order):
// debug < info < step < success < warning < error

Sync Methods ​

For non-test contexts (global setup, utility functions):

typescript
// Use sync methods when async/await isn't available
log.infoSync('Initializing configuration')
log.successSync('Environment configured')
log.errorSync('Setup failed')

Released under the Apache 2.0 License.