1717
1818package org .openqa .selenium ;
1919
20+ import static java .time .Instant .ofEpochMilli ;
21+ import static java .time .ZoneId .systemDefault ;
2022import static java .util .concurrent .TimeUnit .SECONDS ;
2123import static org .assertj .core .api .Assertions .assertThat ;
2224import static org .assertj .core .api .Assertions .assertThatThrownBy ;
2325import static org .openqa .selenium .support .ui .ExpectedConditions .visibilityOf ;
2426
2527import java .time .Duration ;
28+ import java .time .format .DateTimeFormatter ;
29+ import java .util .List ;
2630import java .util .concurrent .CompletableFuture ;
31+ import java .util .concurrent .CopyOnWriteArrayList ;
2732import java .util .concurrent .CountDownLatch ;
2833import java .util .concurrent .ExecutionException ;
2934import java .util .concurrent .TimeUnit ;
3035import java .util .concurrent .TimeoutException ;
31- import java .util .concurrent .atomic .AtomicReference ;
3236import java .util .function .Consumer ;
33- import org .assertj .core .api .Assertions ;
3437import org .junit .jupiter .api .Test ;
3538import org .openqa .selenium .bidi .log .ConsoleLogEntry ;
3639import org .openqa .selenium .bidi .log .JavascriptLogEntry ;
3740import org .openqa .selenium .bidi .log .LogLevel ;
3841import org .openqa .selenium .remote .DomMutation ;
3942import org .openqa .selenium .remote .RemoteWebDriver ;
43+ import org .openqa .selenium .remote .Script ;
4044import org .openqa .selenium .support .ui .WebDriverWait ;
4145import org .openqa .selenium .testing .JupiterTestBase ;
4246import org .openqa .selenium .testing .NeedsFreshDriver ;
4347
4448class WebScriptTest extends JupiterTestBase {
4549
46- String page ;
50+ private String page ;
4751
4852 @ Test
4953 @ NeedsFreshDriver
@@ -182,58 +186,52 @@ void canAddMultipleHandlers() throws ExecutionException, InterruptedException, T
182186
183187 @ Test
184188 @ NeedsFreshDriver
185- void canAddDomMutationHandler () throws InterruptedException {
186- AtomicReference <DomMutation > seen = new AtomicReference <>();
187- CountDownLatch latch = new CountDownLatch (1 );
189+ void canAddDomMutationHandler () {
190+ List <String > mutations = new CopyOnWriteArrayList <>();
188191
189- ((RemoteWebDriver ) driver )
190- .script ()
191- .addDomMutationHandler (
192- mutation -> {
193- seen .set (mutation );
194- latch .countDown ();
195- });
192+ Script script = ((RemoteWebDriver ) driver ).script ();
193+ script .addDomMutationHandler (mutationHandler (mutations ));
196194
197195 driver .get (pages .dynamicPage );
196+ triggerDomMutation ();
198197
199- WebElement reveal = driver .findElement (By .id ("reveal" ));
200- reveal .click ();
201- WebElement revealed = driver .findElement (By .id ("revealed" ));
202-
203- new WebDriverWait (driver , Duration .ofSeconds (10 )).until (visibilityOf (revealed ));
204-
205- Assertions .assertThat (latch .await (10 , SECONDS )).isTrue ();
206- assertThat (seen .get ().getAttributeName ()).isEqualTo ("style" );
207- assertThat (seen .get ().getCurrentValue ()).isEmpty ();
208- assertThat (seen .get ().getOldValue ()).isEqualTo ("display:none;" );
198+ assertThat (mutations ).isNotEmpty ();
199+ assertThat (lastOf (mutations )).isEqualTo ("style: 'display:none;' -> ''" );
209200 }
210201
211202 @ Test
212203 @ NeedsFreshDriver
213- void canRemoveDomMutationHandler () throws InterruptedException {
214- AtomicReference <DomMutation > seen = new AtomicReference <>();
215- CountDownLatch latch = new CountDownLatch (1 );
216-
217- long id =
218- ((RemoteWebDriver ) driver )
219- .script ()
220- .addDomMutationHandler (
221- mutation -> {
222- seen .set (mutation );
223- latch .countDown ();
224- });
204+ void canRemoveDomMutationHandler () {
205+ List <String > mutations = new CopyOnWriteArrayList <>();
206+ Script script = ((RemoteWebDriver ) driver ).script ();
207+ long id = script .addDomMutationHandler (mutationHandler (mutations ));
225208
226209 driver .get (pages .dynamicPage );
210+ triggerDomMutation ();
211+ assertThat (mutations ).isNotEmpty ();
212+
213+ script .removeDomMutationHandler (id );
227214
228- ((RemoteWebDriver ) driver ).script ().removeDomMutationHandler (id );
215+ mutations .clear ();
216+ driver .get (pages .dynamicPage );
217+ triggerDomMutation ();
218+ assertThat (mutations ).isEmpty ();
219+ }
229220
221+ private void triggerDomMutation () {
230222 WebElement reveal = driver .findElement (By .id ("reveal" ));
231223 reveal .click ();
232224 WebElement revealed = driver .findElement (By .id ("revealed" ));
233-
234225 new WebDriverWait (driver , Duration .ofSeconds (10 )).until (visibilityOf (revealed ));
226+ }
235227
236- Assertions .assertThat (latch .await (10 , SECONDS )).isFalse ();
228+ private static Consumer <DomMutation > mutationHandler (List <String > mutations ) {
229+ return mutation -> {
230+ mutations .add (
231+ String .format (
232+ "%s: '%s' -> '%s'" ,
233+ mutation .getAttributeName (), mutation .getOldValue (), mutation .getCurrentValue ()));
234+ };
237235 }
238236
239237 @ Test
@@ -257,27 +255,46 @@ void canPinScript() throws ExecutionException, InterruptedException, TimeoutExce
257255
258256 @ Test
259257 @ NeedsFreshDriver
260- void canUnpinScript () {
261- CountDownLatch latch = new CountDownLatch (2 );
258+ void canUnpinScript () throws InterruptedException {
259+ List <String > logs = new CopyOnWriteArrayList <>();
260+ CountDownLatch latch = new CountDownLatch (1 );
261+
262+ Script script = ((RemoteWebDriver ) driver ).script ();
263+ String pinnedScript = script .pin ("() => { console.log('Hello!'); }" );
262264
263- String pinnedScript =
264- (( RemoteWebDriver ) driver ). script (). pin ( "() => { console.log('Hello!'); }" );
265+ DateTimeFormatter formatter =
266+ DateTimeFormatter . ofPattern ( "HH:mm:ss:SSS" ). withZone ( systemDefault () );
265267
266268 long id =
267- ((RemoteWebDriver ) driver )
268- .script ()
269- .addConsoleMessageHandler (consoleLogEntry -> latch .countDown ());
269+ script .addConsoleMessageHandler (
270+ log -> {
271+ String time = formatter .format (ofEpochMilli (log .getTimestamp ()));
272+ String message = String .format ("%s %s" , log .getText (), time );
273+ logs .add (message );
274+ latch .countDown ();
275+ });
270276
271- page = appServer .whereIs ("/bidi/logEntryAdded.html" );
277+ try {
278+ page = appServer .whereIs ("/bidi/logEntryAdded.html" );
279+ assertThat (logs ).hasSize (0 );
272280
273- driver .get (page );
281+ driver .get (page );
282+ assertThat (latch .await (10 , SECONDS )).isTrue ();
274283
275- ((RemoteWebDriver ) driver ).script ().unpin (pinnedScript );
284+ assertThat (logs ).as ("Chrome logs once, FireFox logs twice" ).isNotEmpty ();
285+ assertThat (logs .get (0 )).startsWith ("Hello!" );
276286
277- driver . get ( page );
287+ script . unpin ( pinnedScript );
278288
279- assertThat (latch .getCount ()).isEqualTo (1L );
289+ logs .clear ();
290+ driver .get (page );
291+ assertThat (logs ).as ("Script has been unpinned, no logs anymore." ).isEmpty ();
292+ } finally {
293+ script .removeConsoleMessageHandler (id );
294+ }
295+ }
280296
281- ((RemoteWebDriver ) driver ).script ().removeConsoleMessageHandler (id );
297+ private static <T > T lastOf (List <T > list ) {
298+ return list .get (list .size () - 1 );
282299 }
283300}
0 commit comments