Skip to content

Commit 6f25323

Browse files
authored
Merge pull request #132 from eviltester/121-stringcounterstring
121 stringcounterstring
2 parents 0978e48 + 9cf0ab7 commit 6f25323

92 files changed

Lines changed: 6496 additions & 5751 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/web/src/tests/browser/app/functional/test-data/schema-grid-row-controls.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ test.describe('7. Test Data Generation', () => {
1818

1919
const schemaText = await appPage.testDataPanel.getSchemaText();
2020
expect(schemaText).toContain('New Column');
21-
expect(schemaText).toContain('literal()');
21+
expect(schemaText).toContain('literal("")');
2222
expectNoPageErrors(pageErrors);
2323
});
2424

docs-src/blog/2026-05-18-domain-abstraction-over-raw-faker.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ tags: [release, architecture, test-data, faker, domain]
66
date: 2026-05-18T10:30
77
---
88

9-
As AnyWayData usage grew across UI, CLI, API, and MCP, we found that directly exposing raw faker calls created avoidable fragility.
9+
As AnyWayData usage grew across UI, CLI, API, and MCP, we found that directly exposing raw faker calls created avoidable fragility.
10+
1011
We moved to a **domain abstraction layer** so schemas describe intent (`internet.email`, `number.int`, `date.recent`) instead of vendor-specific call shapes.
1112

1213
<!-- truncate -->
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
---
2+
slug: string-counterstring-domain-method
3+
title: "Added string.counterString to Domain Test Data"
4+
authors: [alan]
5+
tags: [release, test-data, domain]
6+
---
7+
8+
`string.counterString` is now available in the domain model.
9+
10+
This is the first `string.*` domain addition that is not backed directly by Faker, and is implemented as a custom domain delegate.
11+
12+
<!-- truncate -->
13+
14+
## Why add it?
15+
16+
Counterstrings are useful for field-length and truncation testing because each marker shows its position in the generated text.
17+
18+
Example pattern:
19+
20+
`*3*5*7*9*12*15*`
21+
22+
If we entered the above into a field that truncated to 14 we would see:
23+
24+
`*3*5*7*9*12*15` - this looks incorrect because I'm expecting to see a number before an `*`, if I see a number without an `*` then I know there has been some truncation.
25+
26+
## Usage
27+
28+
`string.counterString(min, max, delimiter="*")`
29+
30+
- If only one integer is supplied, it is used as both min and max.
31+
- If two integers are supplied, the lower value is used as min and the higher as max.
32+
- Lowest allowed min is `1`.
33+
- Delimiter defaults to `*`.
34+
- If a delimiter longer than one character is passed, only the first character is used.
35+
36+
Examples:
37+
38+
```txt
39+
Fixed15
40+
string.counterString(15)
41+
```
42+
43+
```txt
44+
Range5to12
45+
string.counterString(min=5, max=12)
46+
```
47+
48+
```txt
49+
HashDelimited
50+
string.counterString(12, 12, "#")
51+
```
52+
53+
## Take Care
54+
55+
We've added no limits to the length of the counterstrings to take care in your definitions. Sure you can create 1,000,000 rows with counterstrings that are 1,000,000 characters long, but I'm not sure if your computer is going to like generating that.
56+
57+
We default to a `1-25` character counterstring to mitigate this risk somewhat.
58+
59+
## Other counterstring resources
60+
61+
If you are interested in using CounterStrings in your testing then checkout this Chrome extension:
62+
63+
- https://www.eviltester.com/page/tools/counterstringjs/
64+
65+
It allows you to generate counterstrings and other data directly into the browser fields.
66+
67+
Also more information about CounterStrings here:
68+
69+
- https://www.satisfice.com/blog/archives/22
70+
- https://www.eviltester.com/blog/eviltester/news/counterstring-new-version-dec-2025/
71+
- https://www.eviltester.com/categories/counterstrings/

docs-src/docs/040-test-data/010-test-data-generation.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,6 @@ Both workflows support generation rules such as:
4545
- [Literal Data](/docs/test-data/literal-test-data)
4646
- [Regex Based Data](/docs/test-data/regex-test-data)
4747
- [Faker Based Data](/docs/test-data/faker-test-data)
48+
- [Counterstrings](/docs/test-data/counterstrings)
4849
- [Domain Test Data](/docs/test-data/domain/domain-test-data)
4950
- [All Pairs Combinatorial Testing](/docs/test-data/pairwise-testing) - Generate optimal test combinations from enum data
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
---
2+
sidebar_position: 30
3+
title: "Counterstrings"
4+
description: "Use counterstrings to test length limits, truncation, and boundary handling."
5+
---
6+
7+
A counterstring is a specially structured string where marker numbers show exact character positions.
8+
9+
Example of a 15-character counterstring:
10+
11+
```txt
12+
*3*5*7*9*12*15*
13+
```
14+
15+
Each `*` is preceded by the numeric position in the string. So the final `*` is at position 15.
16+
17+
This makes it easy to see where text is cut off, wrapped, or rejected.
18+
19+
## Why Use Counterstrings
20+
21+
Counterstrings are useful for:
22+
23+
- field length boundary testing
24+
- truncation behavior checks
25+
- UI clipping and overflow diagnostics
26+
- API validation and error-message checks
27+
28+
## AnyWayData Support
29+
30+
AnyWayData supports counterstrings through:
31+
32+
```txt
33+
string.counterString(min, max, delimiter="*")
34+
```
35+
36+
Behavior:
37+
38+
- one integer: fixed length (`min == max`)
39+
- two integers: range (smaller becomes min, larger becomes max)
40+
- minimum effective length is `1`
41+
- delimiter defaults to `*`
42+
- multi-character delimiter uses first character
43+
44+
Examples:
45+
46+
```txt
47+
string.counterString(15)
48+
```
49+
50+
```txt
51+
string.counterString(5, 12)
52+
```
53+
54+
```txt
55+
string.counterString(12, 12, "#")
56+
```
57+
58+
## Related Links
59+
60+
- [string domain reference](/docs/test-data/domain/string)
61+
- [Domain Test Data overview](/docs/test-data/domain/domain-test-data)
62+
- [Counterstring reference implementation](https://github.com/eviltester/counterstringjs/blob/master/extension/js/counterstring.js)
63+
- [James Bach on counterstrings](https://www.satisfice.com/blog/archives/22)
64+
- [CounterString Chrome Extension](https://www.eviltester.com/page/tools/counterstringjs/)
65+
- [Alan Richardson on counterstrings](https://www.eviltester.com/categories/counterstrings/)
66+
67+

docs-src/docs/040-test-data/domain/000-domain-test-data.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ Num
5151
number.int(min=32, max=47)
5252
```
5353

54+
## Migration
55+
56+
- Before (invalid): `domain.helpers.fake("...")`
57+
- After: `faker.helpers.fake("...")` (or `helpers.fake("...")` in faker contexts)
58+
5459
For faker helper templates and utility functions, use faker helpers:
5560
- [Faker Helpers](/docs/test-data/faker/helpers)
5661
- [fakerjs.dev/api/helpers](https://fakerjs.dev/api/helpers)

docs-src/docs/040-test-data/domain/020-airline.md

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ airline.aircraftType()
3030
```
3131

3232
Example return values:
33-
- `"narrowbody"`
33+
- `regional`
3434

3535
### `airline.airline`
3636

@@ -48,8 +48,7 @@ airline.airline()
4848
```
4949

5050
Example return values:
51-
- `{"name":"Air China","iataCode":"CA"}`
52-
- `{"name":"TUI Airways","iataCode":"BY"}`
51+
- `{"name":"American Airlines","iataCode":"AA"}`
5352

5453
### `airline.airline.iataCode`
5554

@@ -67,8 +66,7 @@ airline.airline.iataCode()
6766
```
6867

6968
Example return values:
70-
- `"PK"`
71-
- `"MN"`
69+
- `AA`
7270

7371
### `airline.airline.name`
7472

@@ -86,8 +84,7 @@ airline.airline.name()
8684
```
8785

8886
Example return values:
89-
- `"Tunisair"`
90-
- `"SunExpress"`
87+
- `Acme Air`
9188

9289
### `airline.airplane`
9390

@@ -105,8 +102,7 @@ airline.airplane()
105102
```
106103

107104
Example return values:
108-
- `{"name":"Airbus A380-800","iataTypeCode":"388"}`
109-
- `{"name":"Boeing 747-400","iataTypeCode":"744"}`
105+
- `{"name":"Airbus A320","iataTypeCode":"A320"}`
110106

111107
### `airline.airplane.iataTypeCode`
112108

@@ -124,8 +120,7 @@ airline.airplane.iataTypeCode()
124120
```
125121

126122
Example return values:
127-
- `"M81"`
128-
- `"732"`
123+
- `A320`
129124

130125
### `airline.airplane.name`
131126

@@ -143,8 +138,7 @@ airline.airplane.name()
143138
```
144139

145140
Example return values:
146-
- `"Boeing 737-200"`
147-
- `"Douglas DC-10"`
141+
- `Boeing 737`
148142

149143
### `airline.airport`
150144

@@ -162,8 +156,7 @@ airline.airport()
162156
```
163157

164158
Example return values:
165-
- `{"name":"Noumea Magenta Airport","iataCode":"GEA"}`
166-
- `{"name":"Melbourne International Airport","iataCode":"MEL"}`
159+
- `{"name":"Heathrow Airport","iataCode":"LHR"}`
167160

168161
### `airline.airport.iataCode`
169162

@@ -181,8 +174,7 @@ airline.airport.iataCode()
181174
```
182175

183176
Example return values:
184-
- `"HBA"`
185-
- `"AKL"`
177+
- `LHR`
186178

187179
### `airline.airport.name`
188180

@@ -200,8 +192,7 @@ airline.airport.name()
200192
```
201193

202194
Example return values:
203-
- `"Chicago O'Hare International Airport"`
204-
- `"Murtala Muhammed International Airport"`
195+
- `London Heathrow Airport`
205196

206197
### `airline.flightNumber`
207198

@@ -219,8 +210,7 @@ airline.flightNumber()
219210
```
220211

221212
Example return values:
222-
- `"99"`
223-
- `"15"`
213+
- `1`
224214

225215
### `airline.recordLocator`
226216

@@ -238,8 +228,7 @@ airline.recordLocator()
238228
```
239229

240230
Example return values:
241-
- `"HSRWTV"`
242-
- `"BKENFS"`
231+
- `TCSJCN`
243232

244233
### `airline.seat`
245234

@@ -263,5 +252,4 @@ airline.seat(aircraftType="narrowbody")
263252
```
264253

265254
Example return values:
266-
- `"23D"`
267-
- `"9E"`
255+
- `17F`

0 commit comments

Comments
 (0)