Working with strings and dates
Working with text is daily business in test code: normalising a string read from the UI, pulling an ID out of it, building unique test data.
Strings are immutable — every method returns a NEW string and leaves the original alone:
trim()— strips surrounding whitespace; almost always needed before asserting on UI textsplit(separator)andjoin(separator)— convert between string and array:'a,b,c'.split(',')slice(from, to)— extracts a part; a negative index counts from the end:'ORD123'.slice(-3)→'123'replace(a, b)— replaces only the FIRST match; for all of them usereplaceAll(a, b)or a global regexincludes/startsWith/endsWith— boolean checks; more readable thanindexOf(...) !== -1toLowerCase()— for case-insensitive comparison
A template literal (backticks) is always more readable than string concatenation: Order ${id} — ${status}.
| Expression | Result | Note |
|---|---|---|
| ' Paid '.trim() | 'Paid' | only outer whitespace is removed, inner stays |
| 'a-b-c'.replace('-', '+') | 'a+b-c' | only the FIRST match — a commonly missed detail |
| 'a-b-c'.replaceAll('-', '+') | 'a+b+c' | replaces all of them |
| 'ORD-1042'.split('-')[1] | '1042' | simple parsing without regex |
| ['a','b'].join(', ') | 'a, b' | for assembling expected text |
| '12.50'.trim() === 12.50 | false | string vs number comparison — convert with Number() |
Date work is built on the Date object:
new Date()— the current moment;Date.now()— that moment as a millisecond timestamp (a plain number)new Date('2026-03-14T22:30:00Z')— building a date from an ISO 8601 string (the most reliable way)toISOString()— a standard string ALWAYS in UTC:'2026-03-14T22:30:00.000Z'toLocaleDateString(locale, options)— a human format; the result depends on the machine's locale and timezone settings- Date arithmetic goes through milliseconds:
new Date(Date.now() + 24 * 60 * 60 * 1000)— tomorrow
Assertion rule: check the machine-readable form (toISOString(), a timestamp, the date part via slice(0, 10)). Only assert on formatted text when locale and timeZone are stated explicitly (Intl.DateTimeFormat).
Timezones are the classic way to break tests: the developer sits in Baku (UTC+4) while the CI runner runs in UTC — late in the day toLocaleDateString() is a day off and the test fails only in the evenings. The fix: pin timeZone with Intl.DateTimeFormat, or set use: { timezoneId: 'Asia/Baku', locale: 'az-AZ' } in the Playwright config. In an interview this "fails only at night" story lands very well.
For unique test data Date.now() is simple and reliable: qa_${Date.now()}@test.local — it stops parallel tests from colliding on the same user.
📚 Sources and documentation
- Stringofficialdeveloper.mozilla.org
- Intl.DateTimeFormatofficialdeveloper.mozilla.org