Skip to content
Karthik Kodati, home

Case study 01 · Enterprise HCM, Payroll, Finance, and Integrations

A tenant-aware Playwright framework for global Workday

Architecture of a scalable Playwright and TypeScript framework covering Workday HCM, Payroll, Finance, and Integrations across countries and tenants.

Organisation
Zensar Technologies
Role
PlaceholderConfirm your role on this engagement (e.g. framework architect, automation lead)
Period
PlaceholderAdd engagement dates
Stack
  • Playwright
  • TypeScript
  • Workday
  • REST
  • SOAP
  • CI/CD

PlaceholderAdd one verified headline outcome (e.g. regression cycle time, coverage, countries supported)

Business problem

A global Workday programme spans HCM, Payroll, Finance, and Integrations. Each area changes on its own release cadence, and each country brings its own rules, data, and configuration.

Regression coverage has to keep pace with those changes without a separate suite for every country and tenant.

Constraints

  • Workday generates much of its UI at runtime, so static selectors are brittle.
  • The same business process behaves differently per country and per tenant.
  • Integration behaviour has to be verified, not only what appears on screen.
  • Suites must run fast enough to be useful inside CI, across more than one browser.

Architectural approach

  • Treat the framework as a product: a stable core, a clear extension model, and conventions that let other engineers contribute tests without touching the core.
  • Move country and tenant differences out of test code and into configuration, so one test expresses a business process once.
  • Combine UI flows with API integration checks so failures point to the layer that broke.
  • Design for parallel and cross-browser execution from the start rather than retrofitting it.

Architecture

  1. 01 · Configuration

    • Country profiles
    • Tenant targets
    • Test data
  2. 02 · Framework core

    • Fixtures
    • Dynamic locators
    • Page objects
  3. 03 · Suites

    • HCM
    • Payroll
    • Finance
    • Integrations
  4. 04 · Execution

    • Parallel workers
    • Cross-browser
    • CI/CD
  5. 05 · Evidence

    • Reports
    • Traces
    • API results
Conceptual flow based on the components described. It does not represent any client’s internal architecture.

Framework components

Reusable page objects
Business-level actions over Workday screens, shared across HCM, Payroll, and Finance suites.
Dynamic locator strategy
Locators resolved from stable attributes and accessible labels rather than generated IDs.
Multi-country configuration
Country-specific data and rules supplied through configuration instead of branching test code.
Tenant-aware execution
Tests target a tenant by configuration, so the same suite runs against different environments.
Parallel, cross-browser runner
Execution split across workers and browsers to keep feedback inside the CI window.
API integration coverage
REST and SOAP checks that verify integrations directly, alongside the UI flows that depend on them.

Key decisions

Playwright with TypeScript as the foundation
Auto-waiting, browser contexts for isolation, built-in parallelism, and type safety across a large shared codebase.
Configuration over branching
Country and tenant variation in data files keeps test logic readable and avoids duplicated suites.
API checks inside the same framework
One reporting model and shared fixtures for UI and integration evidence.

Integrations

  • Workday HCM
  • Workday Payroll
  • Workday Finance
  • Workday Integrations (REST, SOAP)
  • CI/CD pipeline

Evidence

Tenant- and country-aware fixtureIllustrative
import { test as base } from "@playwright/test";
import { loadProfile, type CountryProfile } from "./config";

type Fixtures = { profile: CountryProfile };

export const test = base.extend<Fixtures>({
  profile: async ({}, use, testInfo) => {
    // Country and tenant come from the project, not from the test body.
    const { country, tenant } = testInfo.project.metadata;
    await use(loadProfile({ country, tenant }));
  },
});

test("hire an employee", async ({ page, profile }) => {
  await page.goto(profile.baseUrl);
  // One business process, expressed once, driven by configuration.
});

Synthetic illustration of the pattern. Not taken from any client codebase.

PlaceholderAdd a sanitized diagram at public/media/workday-automation-framework/architecture.svg
Sanitized framework architectureArchitecture diagram
PlaceholderAdd a sanitized pipeline view (no internal hostnames or job names)
CI/CD execution pipelineCI/CD pipeline
PlaceholderAdd verified, non-confidential metrics only
Execution metricsPerformance metrics

Outcomes

  • PlaceholderAdd verified outcome: regression execution time before and after
  • PlaceholderAdd verified outcome: number of countries or tenants covered
  • PlaceholderAdd verified outcome: adoption (teams or engineers contributing tests)

Lessons learned

  • PlaceholderAdd a lesson learned from this engagement, in your own words
  • PlaceholderAdd a second lesson learned

Repository and confidentiality

PlaceholderLink a public, sanitized reference implementation if you publish one

Client configuration, data, screens, and code are not shown. The diagram and sample describe the general pattern only.