@@ -3,22 +3,104 @@ import { ResultsCollector } from './page-objects/results-collector.js';
33
44const HTML = '/breakage-reporting/index.html' ;
55const CONFIG = './integration-test/test-pages/breakage-reporting/config/config.json' ;
6- test ( 'Breakage Reporting Feature' , async ( { page } , testInfo ) => {
7- const collector = ResultsCollector . create ( page , testInfo . project . use ) ;
8- await collector . load ( HTML , CONFIG ) ;
9-
10- const breakageFeature = new BreakageReportingSpec ( page ) ;
11- await breakageFeature . navigate ( ) ;
12-
13- await collector . simulateSubscriptionMessage ( 'breakageReporting' , 'getBreakageReportValues' , { } ) ;
14- await collector . waitForMessage ( 'breakageReportResult' ) ;
15- const calls = await collector . outgoingMessages ( ) ;
16-
17- expect ( calls . length ) . toBe ( 1 ) ;
18- const result = /** @type {import("@duckduckgo/messaging").NotificationMessage } */ ( calls [ 0 ] . payload ) ;
19- expect ( result . params ?. jsPerformance . length ) . toBe ( 1 ) ;
20- expect ( result . params ?. jsPerformance [ 0 ] ) . toBeGreaterThan ( 0 ) ;
21- expect ( result . params ?. referrer ) . toBe ( 'http://localhost:3220/breakage-reporting/index.html' ) ;
6+
7+ test . describe ( 'Breakage Reporting Feature' , ( ) => {
8+ test ( 'collects basic metrics without detectors' , async ( { page } , testInfo ) => {
9+ const collector = ResultsCollector . create ( page , testInfo . project . use ) ;
10+ await collector . load ( HTML , CONFIG ) ;
11+
12+ const breakageFeature = new BreakageReportingSpec ( page ) ;
13+ await breakageFeature . navigate ( ) ;
14+
15+ await collector . simulateSubscriptionMessage ( 'breakageReporting' , 'getBreakageReportValues' , { } ) ;
16+ await collector . waitForMessage ( 'breakageReportResult' ) ;
17+ const calls = await collector . outgoingMessages ( ) ;
18+
19+ expect ( calls . length ) . toBe ( 1 ) ;
20+ const result = /** @type {import("@duckduckgo/messaging").NotificationMessage } */ ( calls [ 0 ] . payload ) ;
21+ expect ( result . params ?. jsPerformance . length ) . toBe ( 1 ) ;
22+ expect ( result . params ?. jsPerformance [ 0 ] ) . toBeGreaterThan ( 0 ) ;
23+ expect ( result . params ?. referrer ) . toBe ( 'http://localhost:3220/breakage-reporting/index.html' ) ;
24+ } ) ;
25+
26+ test ( 'detects no challenges on clean page' , async ( { page } , testInfo ) => {
27+ const collector = ResultsCollector . create ( page , testInfo . project . use ) ;
28+ await collector . load ( HTML , CONFIG ) ;
29+
30+ const breakageFeature = new BreakageReportingSpec ( page ) ;
31+ await breakageFeature . navigateToPage ( '/breakage-reporting/pages/no-challenge.html' ) ;
32+
33+ await collector . simulateSubscriptionMessage ( 'breakageReporting' , 'getBreakageReportValues' , { } ) ;
34+ await collector . waitForMessage ( 'breakageReportResult' ) ;
35+ const calls = await collector . outgoingMessages ( ) ;
36+
37+ const result = /** @type {import("@duckduckgo/messaging").NotificationMessage } */ ( calls [ 0 ] . payload ) ;
38+ expect ( result . params ?. detectorData ) . toBeDefined ( ) ;
39+ expect ( result . params ?. detectorData ?. botDetection . detected ) . toBe ( false ) ;
40+ expect ( result . params ?. detectorData ?. fraudDetection . detected ) . toBe ( false ) ;
41+ } ) ;
42+
43+ test ( 'detects Cloudflare challenge' , async ( { page } , testInfo ) => {
44+ const collector = ResultsCollector . create ( page , testInfo . project . use ) ;
45+ await collector . load ( HTML , CONFIG ) ;
46+
47+ const breakageFeature = new BreakageReportingSpec ( page ) ;
48+ await breakageFeature . navigateToPage ( '/breakage-reporting/pages/captcha-cloudflare.html' ) ;
49+
50+ await collector . simulateSubscriptionMessage ( 'breakageReporting' , 'getBreakageReportValues' , { } ) ;
51+ await collector . waitForMessage ( 'breakageReportResult' ) ;
52+ const calls = await collector . outgoingMessages ( ) ;
53+
54+ const result = /** @type {import("@duckduckgo/messaging").NotificationMessage } */ ( calls [ 0 ] . payload ) ;
55+ expect ( result . params ?. detectorData ) . toBeDefined ( ) ;
56+ expect ( result . params ?. detectorData ?. botDetection . detected ) . toBe ( true ) ;
57+ expect ( result . params ?. detectorData ?. botDetection . results . length ) . toBeGreaterThan ( 0 ) ;
58+
59+ const cloudflareResult = result . params ?. detectorData ?. botDetection . results [ 0 ] ;
60+ expect ( cloudflareResult . vendor ) . toBe ( 'Cloudflare' ) ;
61+ expect ( cloudflareResult . challengeType ) . toBe ( 'cloudflare' ) ;
62+ expect ( cloudflareResult . detected ) . toBe ( true ) ;
63+ } ) ;
64+
65+ test ( 'detects reCAPTCHA challenge' , async ( { page } , testInfo ) => {
66+ const collector = ResultsCollector . create ( page , testInfo . project . use ) ;
67+ await collector . load ( HTML , CONFIG ) ;
68+
69+ const breakageFeature = new BreakageReportingSpec ( page ) ;
70+ await breakageFeature . navigateToPage ( '/breakage-reporting/pages/captcha-recaptcha.html' ) ;
71+
72+ await collector . simulateSubscriptionMessage ( 'breakageReporting' , 'getBreakageReportValues' , { } ) ;
73+ await collector . waitForMessage ( 'breakageReportResult' ) ;
74+ const calls = await collector . outgoingMessages ( ) ;
75+
76+ const result = /** @type {import("@duckduckgo/messaging").NotificationMessage } */ ( calls [ 0 ] . payload ) ;
77+ expect ( result . params ?. detectorData ) . toBeDefined ( ) ;
78+ expect ( result . params ?. detectorData ?. botDetection . detected ) . toBe ( true ) ;
79+
80+ const recaptchaResult = result . params ?. detectorData ?. botDetection . results . find ( ( r ) => r . challengeType === 'recaptcha' ) ;
81+ expect ( recaptchaResult ) . toBeDefined ( ) ;
82+ expect ( recaptchaResult . vendor ) . toBe ( 'reCAPTCHA' ) ;
83+ expect ( recaptchaResult . detected ) . toBe ( true ) ;
84+ } ) ;
85+
86+ test ( 'detects Fraud challenge (PerimeterX)' , async ( { page } , testInfo ) => {
87+ const collector = ResultsCollector . create ( page , testInfo . project . use ) ;
88+ await collector . load ( HTML , CONFIG ) ;
89+
90+ const breakageFeature = new BreakageReportingSpec ( page ) ;
91+ await breakageFeature . navigateToPage ( '/breakage-reporting/pages/fraud-px.html' ) ;
92+
93+ await collector . simulateSubscriptionMessage ( 'breakageReporting' , 'getBreakageReportValues' , { } ) ;
94+ await collector . waitForMessage ( 'breakageReportResult' ) ;
95+ const calls = await collector . outgoingMessages ( ) ;
96+
97+ const result = /** @type {import("@duckduckgo/messaging").NotificationMessage } */ ( calls [ 0 ] . payload ) ;
98+ expect ( result . params ?. detectorData ) . toBeDefined ( ) ;
99+ expect ( result . params ?. detectorData ?. fraudDetection . detected ) . toBe ( true ) ;
100+
101+ const fraudResult = result . params ?. detectorData ?. fraudDetection . results [ 0 ] ;
102+ expect ( fraudResult . alertId ) . toBe ( 'px' ) ;
103+ } ) ;
22104} ) ;
23105
24106export class BreakageReportingSpec {
@@ -30,10 +112,14 @@ export class BreakageReportingSpec {
30112 }
31113
32114 async navigate ( ) {
33- await this . page . evaluate ( ( ) => {
34- window . location . href = '/breakage-reporting/pages/ref.html' ;
35- } ) ;
36- await this . page . waitForURL ( '**/ref.html' ) ;
115+ await this . navigateToPage ( '/breakage-reporting/pages/ref.html' ) ;
116+ }
117+
118+ async navigateToPage ( url ) {
119+ await this . page . evaluate ( ( targetUrl ) => {
120+ window . location . href = targetUrl ;
121+ } , url ) ;
122+ await this . page . waitForURL ( `**${ url } ` ) ;
37123
38124 // Wait for first paint event to ensure we can get the performance metrics
39125 await this . page . evaluate ( ( ) => {
0 commit comments