| package semantic |
|
|
| import "strings" |
|
|
| |
| |
| type FailureType int |
|
|
| const ( |
| |
| FailureUnknown FailureType = iota |
|
|
| |
| |
| FailureElementNotFound |
|
|
| |
| |
| FailureElementStale |
|
|
| |
| |
| FailureElementNotInteractable |
|
|
| |
| |
| FailureNavigation |
|
|
| |
| |
| FailureNetwork |
| ) |
|
|
| |
| func (f FailureType) String() string { |
| switch f { |
| case FailureElementNotFound: |
| return "element_not_found" |
| case FailureElementStale: |
| return "element_stale" |
| case FailureElementNotInteractable: |
| return "element_not_interactable" |
| case FailureNavigation: |
| return "navigation" |
| case FailureNetwork: |
| return "network" |
| default: |
| return "unknown" |
| } |
| } |
|
|
| |
| |
| func (f FailureType) Recoverable() bool { |
| switch f { |
| case FailureElementNotFound, |
| FailureElementStale, |
| FailureElementNotInteractable, |
| FailureNavigation: |
| return true |
| default: |
| return false |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| func ClassifyFailure(err error) FailureType { |
| if err == nil { |
| return FailureUnknown |
| } |
| e := strings.ToLower(err.Error()) |
|
|
| |
| notFoundPatterns := []string{ |
| "could not find node", |
| "node with given id", |
| "no node", |
| "ref not found", |
| "node not found", |
| "backend node id", |
| "no node with given", |
| } |
| for _, p := range notFoundPatterns { |
| if strings.Contains(e, p) { |
| return FailureElementNotFound |
| } |
| } |
|
|
| |
| |
| stalePatterns := []string{ |
| "stale", |
| "orphan", |
| "object reference", |
| "node is detached", |
| "execution context was destroyed", |
| "context was destroyed", |
| "target closed", |
| } |
| for _, p := range stalePatterns { |
| if strings.Contains(e, p) { |
| return FailureElementStale |
| } |
| } |
| |
| if strings.Contains(e, "detached") && !strings.Contains(e, "frame") { |
| return FailureElementStale |
| } |
|
|
| |
| interactablePatterns := []string{ |
| "not interactable", |
| "not clickable", |
| "element is not visible", |
| "not visible", |
| "element is disabled", |
| "overlapped", |
| "overlapping", |
| "obscured", |
| "pointer-events: none", |
| "cannot focus", |
| "outside of the viewport", |
| "outside the viewport", |
| } |
| for _, p := range interactablePatterns { |
| if strings.Contains(e, p) { |
| return FailureElementNotInteractable |
| } |
| } |
|
|
| |
| navPatterns := []string{ |
| "navigat", |
| "page crashed", |
| "page was destroyed", |
| "inspected target", |
| "frame was detached", |
| "frame detached", |
| } |
| for _, p := range navPatterns { |
| if strings.Contains(e, p) { |
| return FailureNavigation |
| } |
| } |
|
|
| |
| networkPatterns := []string{ |
| "net::", |
| "connection refused", |
| "could not connect", |
| "timeout", |
| "deadline exceeded", |
| "websocket", |
| "eof", |
| "broken pipe", |
| } |
| for _, p := range networkPatterns { |
| if strings.Contains(e, p) { |
| return FailureNetwork |
| } |
| } |
|
|
| return FailureUnknown |
| } |
|
|