Skip to content

Citi Playwright Testing Interview Questions & Answers

Curated interview practice questions with answers. These are practice scenarios, not a verified list of past interview questions.

About Citi hiring for Playwright Testing roles

Citi is a global bank serving corporations, institutions and individuals through services, markets, banking and wealth businesses. Its India technology and operations centres in Pune, Chennai and Mumbai support global functions. It hires for software engineers, QA engineers, data engineers, data analysts and risk analysts.

For Playwright Testing roles, this Citi practice set focuses most on JavaScript and TypeScript (6), Network Mocking (5), Visual & Accessibility Testing (5), API Testing (5). It has 7 easy, 30 medium, 3 hard questions, so you can start easy and work up to the harder ones.

Company type
Banking & finance
Headquarters
New York, USA
Main India offices
Pune, Chennai, Mumbai, Bengaluru, Gurugram

Citi Playwright Testing interview process

  1. Online assessment (aptitude + coding)
  2. Technical round 1
  3. Technical round 2
  4. Managerial round
  5. HR round

Typical pattern based on public candidate experiences. Rounds vary by role, team and year.

Solved for CitiStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
3 questions free Unlock the rest in seconds
01

Why should you start waitForResponse before the action that triggers it?

Save to ▾
Show answer
If you click first and then wait, the response may already have arrived, so the wait misses it and times out. Create the promise first, then act, then await it: const resp = page.waitForResponse('**/api/cart'); await addButton.click(); await resp. waitForRequest works the same way for outgoing requests.
02

What is an ARIA snapshot and how does toMatchAriaSnapshot work?

Save to ▾
Show answer
An ARIA snapshot is a YAML description of the accessibility tree for a part of the page: roles, names and states such as checked or level. toMatchAriaSnapshot compares the live tree of a locator against that template, and partial templates or regular expressions can be used for changing text. It tests structure and semantics, so it survives styling changes that would break a pixel screenshot.
03

What is the difference between workerIndex and parallelIndex?

Save to ▾
Show answer
workerIndex is a unique number for every worker process started during the run, so it keeps growing when a worker is restarted after a failure. parallelIndex is a slot number from 0 to workers minus 1, and a restarted worker reuses its slot. Use parallelIndex, also exposed as TEST_PARALLEL_INDEX, to pick a fixed test account or database per slot.
04

How do you handle token refresh in long API test runs?

Save to ▾
Show answer
Fetch tokens in a fixture with expiry tracking and refresh it when it is about to expire, keeping tests unaware of the details.
05

Write a typed helper that retries an async function a few times.

Save to ▾
Show answer
async function retry<T>(fn: () => Promise<T>, times = 3): Promise<T> { let lastError: unknown; for (let i = 0; i < times; i++) { try { return await fn(); } catch (e) { lastError = e; } } throw lastError; }
06

Write a GitHub Actions job that runs the suite in four shards.

Save to ▾
Show answer
jobs: e2e: runs-on: ubuntu-latest strategy: fail-fast: false matrix: shard: [1, 2, 3, 4] steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 - run: npm ci && npx playwright install --with-deps - run: npx playwright test --shard=${{ matrix.shard }}/4 --reporter=blob - uses: actions/upload-artifact@v4 with: name: blob-${{ matrix.shard }} path: blob-report
07

How do you validate JSON schema?

Save to ▾
Show answer
Use a library such as zod or ajv to define the expected schema and parse the response to fail on missing or wrongly typed fields.
08

How do you run one group of tests serially while the rest of the suite runs in parallel?

Save to ▾
Show answer
Put the group in its own project with fullyParallel: false and limit it to one worker, which recent versions allow with a workers setting on the project, or run it in a separate CI step with --project=serial --workers=1. Inside a file, test.describe.configure({ mode: 'serial' }) keeps order. Use project dependencies if the group must run after the parallel tests.
09

Tell me about a time you refactored duplicated setup into fixtures.

Save to ▾
Show answer
Situation: forty test files each repeated twenty lines of login and data setup. Task: reduce duplication and maintenance. Action: I created fixtures for the logged-in page, a test customer and page objects, migrated files in small reviewed pull requests and wrote a short guide. Result: test files became half the size and setup changes now touch one file.
10

Visual tests pass on developers' laptops but fail in CI with tiny font differences. Why, and how do you fix it?

Save to ▾
Show answer
Font rendering, anti-aliasing and installed fonts differ between Windows, macOS and Linux, so the same page produces slightly different pixels. The fix is to generate and compare baselines in one fixed environment, usually the official Playwright Docker image used in CI. Developers update baselines by running that container locally or through a CI job, not from their own machines. Loosening thresholds should be the last resort.
11

What is Playwright component testing?

Save to ▾
Show answer
Component testing mounts a single UI component, such as a React or Vue button or form, in a real browser page and tests it with the normal Playwright API. Playwright bundles the component with Vite, serves it on a small page and gives you a mount fixture. You get real browser rendering and events, which unit tests in jsdom cannot give, while staying much faster than full end-to-end flows. The feature is still marked experimental.
12

What are fixtures in Playwright?

Save to ▾
Show answer
Reusable setup/teardown units injected into tests (page, context, request). You can extend test with custom fixtures such as loggedInPage.
13

How do you check colour contrast in Playwright tests?

Save to ▾
Show answer
Playwright has no built-in contrast assertion, so you run axe-core through @axe-core/playwright, whose color-contrast rule checks text against WCAG ratios such as 4.5 to 1 for normal text. Scan pages in each theme, for example after emulating dark mode with colorScheme. Axe may report some elements as needing review, for example text over images, and those need a manual look.
14

interface vs type in TypeScript?

Save to ▾
Show answer
Both describe object shapes. Interfaces can be extended and merged; type aliases can also describe unions and primitives. Use interfaces for page or test-data shapes, types for unions.
15

Which frameworks does Playwright component testing support?

Save to ▾
Show answer
Official packages exist for React, Vue and Svelte, named like @playwright/experimental-ct-react and @playwright/experimental-ct-vue. Each package provides the mount fixture and hooks in the style of its framework, such as slots and events for Vue. Support has changed between versions and the feature is experimental, so check the current docs and pin the package version alongside @playwright/test.
16

What is UI mode and how is it different from --debug?

Save to ▾
Show answer
UI mode, opened with npx playwright test --ui, is a dashboard to run, filter and watch tests, with a trace-like timeline for each one and a watch mode that reruns on file changes. --debug opens the Inspector to step through a single run live. Use UI mode for daily development and --debug for stepping through a specific action.
17

A fixture mocks every /api call, but one test needs a different response for /api/cart. How do you override it?

Save to ▾
Show answer
Register a new page.route for /api/cart inside that test. Handlers run in reverse order of registration, so the newer one runs first. Fulfil the cart request with the special data, and for anything else call route.fallback() so the request moves on to the fixture's general handler. This keeps the shared mock untouched and makes the override local and easy to read.
18

Write a test that checks keyboard Tab order through a login form.

Save to ▾
Show answer
test('login form is keyboard friendly', async ({ page }) => { await page.goto('/login'); await page.getByLabel('Email').focus(); await page.keyboard.press('Tab'); await expect(page.getByLabel('Password')).toBeFocused(); await page.keyboard.press('Tab'); await expect(page.getByRole('button', { name: 'Sign in' })).toBeFocused(); await page.keyboard.press('Enter'); });
19

How do you wait for a network response in Playwright?

Save to ▾
Show answer
Use page.waitForResponse(res => res.url().includes('/api/orders') && res.ok()) together with the action that triggers it.
20

Explain the event loop.

Save to ▾
Show answer
JavaScript runs one call stack and uses queues for async work; the event loop pushes callbacks from the microtask (promises) and task queues when the stack is empty.
21

How do you filter a list of locators by text or by a child element?

Save to ▾
Show answer
// pick one product card from many const card = page.getByRole('listitem') .filter({ hasText: 'Wireless Mouse' }) .filter({ has: page.getByRole('button', { name: 'Add to cart' }) }); await card.getByRole('button', { name: 'Add to cart' }).click(); // hasNotText and hasNot exclude matches
22

How do you read environment variables safely in a TypeScript test project?

Save to ▾
Show answer
Load a .env file with a package like dotenv in playwright.config, then read process.env.BASE_URL. Values are string | undefined, so validate them early and throw a clear error if a required one is missing. Keep .env out of git and commit an .env.example instead. In CI, set the same names as secret variables.
23

How do you share cookies between API login and UI?

Save to ▾
Show answer
Log in with request.post, call request.storageState(), and create a browser context using that state.
24

How do you test a dropdown component's keyboard support in a component test?

Save to ▾
Show answer
Mount the dropdown, focus the trigger and press Enter or ArrowDown to open it. Assert the listbox is visible and the first option has aria-selected or focus. Press ArrowDown again and check the active option moves, then press Enter and assert the trigger shows the chosen value and the list is closed. Finally press Escape on an open list to confirm it closes without changing the value.
25

How do you attach axe results to the Playwright HTML report?

Save to ▾
Show answer
test('cart is accessible', async ({ page }, testInfo) => { await page.goto('/cart'); const results = await new AxeBuilder({ page }).analyze(); await testInfo.attach('axe-results', { body: JSON.stringify(results.violations, null, 2), contentType: 'application/json', }); expect(results.violations).toEqual([]); });
26

How does URL matching work in page.route?

Save to ▾
Show answer
The first argument can be a glob string, a regular expression or a function that receives a URL object. Globs like '**/api/users*' are simple but * does not cross slashes and ** does. Regex gives precise control over query strings. A predicate function suits complex rules, for example matching host plus a specific search parameter.
27

What is the difference between synchronous and asynchronous code?

Save to ▾
Show answer
Synchronous code runs line by line and blocks; asynchronous code starts a task and continues, handling the result later with promises or await.
28

What are higher-order functions?

Save to ▾
Show answer
Functions that take other functions as arguments or return them, such as map, filter and reduce, or a helper that wraps retry logic around a test step.
29

What are projects in playwright.config?

Save to ▾
Show answer
Named configurations that run the same tests across different browsers, devices or environments.
30

How do you test API error scenarios?

Save to ▾
Show answer
Send invalid payloads or missing auth and assert 400, 401 or 404 codes and the error message bodies.
31

How do you handle authentication to avoid logging in every test?

Save to ▾
Show answer
Log in once in a setup project, save storageState to a file and reuse it in other projects or tests.
32

What do locator.and() and locator.or() do?

Save to ▾
Show answer
and() returns a locator that matches elements satisfying both locators, for example a button that also has a certain title. or() matches either locator, which helps when the UI may show one of two states, such as a New email button or a security dialog. With or(), wrap the assertion carefully, because if both appear the strict check fails.
33

How do you run tests on three browsers in parallel?

Save to ▾
Show answer
Define projects for chromium, firefox and webkit in playwright.config.ts, set workers, then run: npx playwright test
34

How can you run only the tests affected by a code change?

Save to ▾
Show answer
Use npx playwright test --only-changed=origin/main. It looks at files changed against that git reference and runs the test files that changed or that import changed files. It suits fast pull request feedback in a large suite. It cannot see backend or config changes that tests do not import, so still run the full suite before release.
35

What does page.route do?

Save to ▾
Show answer
page.route registers a handler for requests whose URL matches a pattern. Inside the handler you can let the request continue, change it, return a fake response or abort it. It lets you test the UI against controlled data without depending on a real backend. Register routes before the action that triggers the request, usually before page.goto.
36

How do you record a trace manually with the tracing API?

Save to ▾
Show answer
Call await context.tracing.start({ screenshots: true, snapshots: true }) before the steps, and await context.tracing.stop({ path: 'trace.zip' }) after them. This is useful in scripts that use the library without the test runner, or when you want a trace of only part of a flow. tracing.group can label sections of steps.
37

How is toBeVisible different from toBeAttached?

Save to ▾
Show answer
toBeAttached only checks that the element exists in the DOM. toBeVisible also needs it to have a non-empty bounding box and no visibility:hidden style. A hidden modal can be attached but not visible. Use toBeVisible for anything a user should see, and toBeAttached for hidden inputs or elements whose presence matters more than appearance.
38

What is a browser context and why is it cheap?

Save to ▾
Show answer
A browser context is an isolated session inside one browser, like a fresh incognito profile with its own cookies, storage and cache. Creating one takes milliseconds, unlike launching a new browser. Playwright gives every test a new context, so tests do not leak state into each other, and you can open several contexts to simulate different users.
39

How do you validate an API response in Playwright?

Save to ▾
Show answer
Assert the status with expect(res.status()).toBe(200), parse res.json() and check fields, using schema validation for the structure.
40

Two test files edit the same global settings page and break each other when run in parallel. How do you handle it?

Save to ▾
Show answer
The best fix is to remove the shared resource, for example by giving each test its own tenant or user whose settings it can change. If that is impossible, put those tests in one file with test.describe.configure({ mode: 'serial' }), or in a separate project that runs with one worker after the main project. Document why, so the exception does not quietly spread.

Tips to crack the Citi Playwright Testing interview

  • Revise Java, SQL and data structures, which are commonly tested for Citi technology analyst roles.
  • Learn basics of treasury and trade services, payments and capital markets, which are core Citi businesses.
  • Prepare examples of handling pressure and attention to detail in a controlled, regulated environment.
  • Keep a one-minute story ready for every project on your CV: problem, your part, tools, result.
  • Practise the hard questions on this page aloud; Citi interviewers usually ask follow-ups on your first answer.

Frequently asked questions

How many rounds are there in the Citi Playwright Testing interview?

Candidates usually go through 5 stages: Online assessment (aptitude + coding); Technical round 1; Technical round 2; Managerial round; HR round. The exact rounds change with the role, team, location and your experience, so confirm the process with the recruiter.

Which topics should I prepare for the Citi Playwright Testing interview?

This practice set leans on JavaScript and TypeScript (6), Network Mocking (5), Visual & Accessibility Testing (5), API Testing (5). Revise those first, then practise explaining one or two of your own projects end to end, because most Citi interviewers ask you to walk through real work.

Are these the exact questions asked at Citi?

No. These are curated practice questions that match the skills and difficulty usually tested in banking & finance interviews like Citi's. They are not a leaked or verified list of past questions.

Where does Citi hire Playwright Testing professionals in India?

Citi has large teams in Pune, Chennai, Mumbai, Bengaluru, Gurugram. Openings and locations change often, so check the Citi careers page and filter by city and experience.

Playwright Testing questions for similar companies