Skip to content

Commit 0ebaf94

Browse files
authored
chore: support retries for test mode
2 parents 5ef4e98 + ff749fe commit 0ebaf94

File tree

14 files changed

+181
-149
lines changed

14 files changed

+181
-149
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.20.0] - 2026-02-02
9+
10+
### Changed
11+
- Support for retries
12+
- Upgraded Go to 1.25.6
13+
814
## [0.19.1] - 2026-02-02
915

1016
### Changed
@@ -130,6 +136,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
130136
### Added
131137
- Initial release
132138

139+
[0.20.0]: https://github.com/gooddata/gooddata-neobackstop/compare/v0.19.1...v0.20.0
133140
[0.19.1]: https://github.com/gooddata/gooddata-neobackstop/compare/v0.19.0...v0.19.1
134141
[0.19.0]: https://github.com/gooddata/gooddata-neobackstop/compare/v0.18.0...v0.19.0
135142
[0.18.0]: https://github.com/gooddata/gooddata-neobackstop/compare/v0.17.0...v0.18.0

Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Stage 0: Build the base go system with playwright drivers
2-
FROM 020413372491.dkr.ecr.us-east-1.amazonaws.com/pullthrough/docker.io/library/golang:1.25.4-bookworm AS basesystem
2+
FROM 020413372491.dkr.ecr.us-east-1.amazonaws.com/pullthrough/docker.io/library/golang:1.25.6-bookworm AS basesystem
33
WORKDIR /
44

55
# Install CA certs & dependencies
@@ -14,7 +14,7 @@ RUN apt-get update && apt-get install -y \
1414
RUN GOOS=linux GOARCH=${TARGETARCH} go run github.com/playwright-community/playwright-go/cmd/playwright@latest install --with-deps chromium firefox
1515

1616
# Stage 1: Build the Go app
17-
FROM 020413372491.dkr.ecr.us-east-1.amazonaws.com/pullthrough/docker.io/library/golang:1.25.4-bookworm AS builder
17+
FROM 020413372491.dkr.ecr.us-east-1.amazonaws.com/pullthrough/docker.io/library/golang:1.25.6-bookworm AS builder
1818
WORKDIR /app
1919

2020
# Copy Go module files and download dependencies

README.md

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ go get github.com/gooddata/gooddata-neobackstop@latest
4141
### Building from Source
4242

4343
Prerequisites:
44-
- Go 1.25.4 or later
44+
- Go 1.25.6 or later
4545
- Playwright browsers (installed automatically on first run)
4646

4747
```bash
@@ -126,7 +126,7 @@ func main() {
126126

127127
// Convert to internal format
128128
internalScenarios := converters.ScenariosToInternal(
129-
cfg.Browsers, cfg.Viewports, scenarios,
129+
cfg.Browsers, cfg.Viewports, cfg.RetryCount, scenarios,
130130
)
131131

132132
// Install and run Playwright
@@ -192,7 +192,7 @@ func main() {
192192
json.Unmarshal(scenariosBytes, &scenarios)
193193

194194
internalScenarios := converters.ScenariosToInternal(
195-
cfg.Browsers, cfg.Viewports, scenarios,
195+
cfg.Browsers, cfg.Viewports, cfg.RetryCount, scenarios,
196196
)
197197

198198
// Find a specific scenario to debug
@@ -323,7 +323,8 @@ The main configuration file controls browser settings, viewports, output paths,
323323
]
324324
},
325325
"asyncCaptureLimit": 2,
326-
"asyncCompareLimit": 6
326+
"asyncCompareLimit": 6,
327+
"retryCount": 0
327328
}
328329
```
329330

@@ -342,6 +343,7 @@ The main configuration file controls browser settings, viewports, output paths,
342343
| `args` | object | Browser-specific launch arguments |
343344
| `asyncCaptureLimit` | number | Max concurrent screenshot captures |
344345
| `asyncCompareLimit` | number | Max concurrent image comparisons |
346+
| `retryCount` | number | Extra retries on mismatch in test mode |
345347

346348
#### Viewport Configuration
347349

@@ -376,24 +378,25 @@ Defines the test scenarios - which pages to capture and how to interact with the
376378

377379
#### Scenario Options
378380

379-
| Option | Type | Description |
380-
|-----------------------|------------------|---------------------------------------------|
381-
| `id` | string | Unique identifier for the scenario |
382-
| `label` | string | Human-readable label (used in reports) |
383-
| `url` | string | URL to navigate to |
384-
| `browsers` | string[] | Override global browsers for this scenario |
385-
| `viewports` | Viewport[] | Override global viewports for this scenario |
386-
| `readySelector` | string | CSS selector to wait for before capture |
387-
| `reloadAfterReady` | boolean | Reload page after ready selector appears |
388-
| `delay` | number \| object | Wait time after ready (see below) |
389-
| `keyPressSelector` | object | Element to focus and key to press |
390-
| `hoverSelector` | string | Single element to hover over |
391-
| `hoverSelectors` | array | Multiple elements to hover in sequence |
392-
| `clickSelector` | string | Single element to click |
393-
| `clickSelectors` | array | Multiple elements to click in sequence |
394-
| `postInteractionWait` | string \| number | Wait after interactions (selector or ms) |
395-
| `scrollToSelector` | string | Element to scroll into view |
396-
| `misMatchThreshold` | number | Allowed mismatch percentage (0-100) |
381+
| Option | Type | Description |
382+
|-----------------------|------------------|---------------------------------------------------|
383+
| `id` | string | Unique identifier for the scenario |
384+
| `label` | string | Human-readable label (used in reports) |
385+
| `url` | string | URL to navigate to |
386+
| `browsers` | string[] | Override global browsers for this scenario |
387+
| `viewports` | Viewport[] | Override global viewports for this scenario |
388+
| `readySelector` | string | CSS selector to wait for before capture |
389+
| `reloadAfterReady` | boolean | Reload page after ready selector appears |
390+
| `delay` | number \| object | Wait time after ready (see below) |
391+
| `keyPressSelector` | object | Element to focus and key to press |
392+
| `hoverSelector` | string | Single element to hover over |
393+
| `hoverSelectors` | array | Multiple elements to hover in sequence |
394+
| `clickSelector` | string | Single element to click |
395+
| `clickSelectors` | array | Multiple elements to click in sequence |
396+
| `postInteractionWait` | string \| number | Wait after interactions (selector or ms) |
397+
| `scrollToSelector` | string | Element to scroll into view |
398+
| `misMatchThreshold` | number | Allowed mismatch percentage (0-100) |
399+
| `retryCount` | number | Extra retries for the scenario (overrides global) |
397400

398401
## Scenario Examples
399402

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.19.1
1+
0.20.0

config/types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,5 @@ type Config struct {
2121
AsyncCaptureLimit int `json:"asyncCaptureLimit"`
2222
AsyncCompareLimit int `json:"asyncCompareLimit"`
2323
RequireSameDimensions bool `json:"requireSameDimensions"`
24+
RetryCount int `json:"retryCount"`
2425
}

converters/converters.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ import (
99
"github.com/gooddata/gooddata-neobackstop/viewport"
1010
)
1111

12-
func scenarioToInternal(b browser.Browser, v viewport.Viewport, s scenario.Scenario) internals.Scenario {
12+
func scenarioToInternal(b browser.Browser, v viewport.Viewport, rc int, s scenario.Scenario) internals.Scenario {
13+
retryCount := rc
14+
if s.RetryCount != nil {
15+
retryCount = *s.RetryCount
16+
}
17+
1318
return internals.Scenario{
1419
Browser: b,
1520
Viewport: v,
@@ -28,34 +33,35 @@ func scenarioToInternal(b browser.Browser, v viewport.Viewport, s scenario.Scena
2833
PostInteractionWait: s.PostInteractionWait,
2934
ScrollToSelector: s.ScrollToSelector,
3035
MisMatchThreshold: s.MisMatchThreshold,
36+
RetryCount: retryCount,
3137
}
3238
}
3339

34-
func ScenariosToInternal(browsers []browser.Browser, viewports []viewport.Viewport, scenarios []scenario.Scenario) []internals.Scenario {
40+
func ScenariosToInternal(browsers []browser.Browser, viewports []viewport.Viewport, retryCount int, scenarios []scenario.Scenario) []internals.Scenario {
3541
output := make([]internals.Scenario, 0) // we could pre-calculate this, but until we do multi-browser testing, it's not worth it
3642

3743
for _, s := range scenarios {
3844
if s.Browsers == nil {
3945
for _, b := range browsers {
4046
if s.Viewports == nil {
4147
for _, v := range viewports {
42-
output = append(output, scenarioToInternal(b, v, s))
48+
output = append(output, scenarioToInternal(b, v, retryCount, s))
4349
}
4450
} else {
4551
for _, v := range s.Viewports {
46-
output = append(output, scenarioToInternal(b, v, s))
52+
output = append(output, scenarioToInternal(b, v, retryCount, s))
4753
}
4854
}
4955
}
5056
} else {
5157
for _, b := range s.Browsers {
5258
if s.Viewports == nil {
5359
for _, v := range viewports {
54-
output = append(output, scenarioToInternal(b, v, s))
60+
output = append(output, scenarioToInternal(b, v, retryCount, s))
5561
}
5662
} else {
5763
for _, v := range s.Viewports {
58-
output = append(output, scenarioToInternal(b, v, s))
64+
output = append(output, scenarioToInternal(b, v, retryCount, s))
5965
}
6066
}
6167
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/gooddata/gooddata-neobackstop
22

3-
go 1.25.4
3+
go 1.25.6
44

55
require github.com/playwright-community/playwright-go v0.5200.1
66

internals/types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,5 @@ type Scenario struct {
2626
PostInteractionWait *scenario.SelectorThenDelay `json:"postInteractionWait"`
2727
ScrollToSelector *string `json:"scrollToSelector"`
2828
MisMatchThreshold *float64 `json:"misMatchThreshold"`
29+
RetryCount int `json:"retryCount"`
2930
}

main.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ func main() {
9494
}
9595

9696
// build internal scenarios
97-
internalScenarios := converters.ScenariosToInternal(configuration.Browsers, configuration.Viewports, scenarios)
97+
internalScenarios := converters.ScenariosToInternal(configuration.Browsers, configuration.Viewports, configuration.RetryCount, scenarios)
9898

9999
numInternalScenarios := len(internalScenarios)
100100
fmt.Println("Generated", numInternalScenarios, "internal scenarios")
@@ -205,6 +205,9 @@ func main() {
205205
if compareResult.HasReference {
206206
r.ReferenceFileName = compareResult.ScreenshotterResult.FileName
207207
r.MatchesReference = &compareResult.MatchesReference
208+
if compareResult.ScreenshotterResult.RetriesUsed != nil && *compareResult.ScreenshotterResult.RetriesUsed > 0 {
209+
r.RetriesUsed = compareResult.ScreenshotterResult.RetriesUsed
210+
}
208211

209212
if !compareResult.MatchesReference {
210213
// diff will exist

result/types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ type Result struct {
1212
MatchesReference *bool `json:"matches_reference"`
1313
DiffFileName *string `json:"diff_file_name"`
1414
MisMatchPercentage *float64 `json:"misMatchPercentage"`
15+
RetriesUsed *int `json:"retriesUsed,omitempty"`
1516
}

0 commit comments

Comments
 (0)