Skip to content

UI Test IDs (data-test)

This guide describes how the frontend is instrumented for automated UI tests (e.g. browser-based end-to-end tools). The underlying decision is documented in ADR-010.

Goal

Provide stable, text-independent selectors for every relevant UI element so that end-to-end tests do not break when styling, DOM structure or copy changes.

The attribute

  • We use the attribute data-test.
  • Test tools select elements via the CSS selector [data-test='<id>'].
  • For raw input access use [data-test='<id>'] input, [data-test='<id>'] textarea etc., because Vuetify renders a wrapper around the native control.
java
// Example with a CSS selector based UI test tool
driver.findElement(By.cssSelector("[data-test='nwk-create-dialog-open-btn']")).click();
driver.findElement(By.cssSelector("[data-test='nwk-vorname-input'] input")).sendKeys("Max");

Central source of truth

All IDs live in praktikumsplaner-frontend/src/testIds.ts as typed constants grouped by area. Templates import testIds and bind them:

vue
<script setup lang="ts">
import { testIds } from "@/testIds";
</script>

<template>
  <v-btn :data-test="testIds.nwk.createDialogOpenBtn" />
</template>

Never inline raw data-test string literals in a template. Always add a constant to testIds.ts first and reference it. This keeps the IDs discoverable, typo-free and refactor-safe.

Naming convention

  • kebab-case values.
  • Hierarchical, from area to concrete element: <area>-<component>-<element>.
  • Suffix by element type where helpful: -btn, -input, -select, -checkbox, -radio, -dialog, -table, -row, -link.

Examples:

ConstantRendered data-test value
testIds.nav.nachwuchskraeftenav-nachwuchskraefte
testIds.nwk.createDialogOpenBtnnwk-create-dialog-open-btn
testIds.nwk.vornameInputnwk-vorname-input
testIds.common.dataTableSearchdata-table-search
testIds.dialog.yesNoYesBtnyesno-dialog-yes-btn

What gets an ID

Instrumented:

  • interactive elements: buttons, text fields, text areas, selects, autocompletes, checkboxes, radio groups, file inputs, date pickers;
  • structural anchors: dialogs, data tables + rows, navigation entries, page title, list cards, the global snackbar and error dialog.

Not instrumented:

  • purely decorative elements (icons, tooltips, spacers, dividers).

Reusable components

Wrapper components such as NameInput or DienststellenInput carry a fixeddata-test. This is intentional and safe: the same wrapper never appears twice on screen at the same time, because the dialogs and views that host them are mutually exclusive. A test therefore always addresses a unique element.

Adding a new element

  1. Add a constant to the appropriate area object in src/testIds.ts.
  2. Bind it in the template via :data-test="testIds.<area>.<name>".
  3. For inputs, remember tests select the inner control via [data-test='...'] input.
Contact and Imprint
Made with 💛 in Munich