1
0
mirror of synced 2026-05-22 18:53:15 +00:00

fix(api): remove Listener interface from public API (#219)

This commit is contained in:
Yury Semikhatsky
2021-01-20 19:32:53 -08:00
committed by GitHub
parent 2ba2706104
commit 3376836752
48 changed files with 155 additions and 297 deletions
@@ -48,12 +48,6 @@ public interface Browser {
}
}
enum EventType {
DISCONNECTED,
}
void addListener(EventType type, Listener<EventType> listener);
void removeListener(EventType type, Listener<EventType> listener);
void onDisconnected(Runnable handler);
void offDisconnected(Runnable handler);
@@ -94,13 +94,6 @@ public interface BrowserContext {
}
}
enum EventType {
CLOSE,
PAGE,
}
void addListener(EventType type, Listener<EventType> listener);
void removeListener(EventType type, Listener<EventType> listener);
void onClose(Runnable handler);
void offClose(Runnable handler);
@@ -74,30 +74,6 @@ public interface Page {
String stack();
}
enum EventType {
CLOSE,
CONSOLE,
CRASH,
DIALOG,
DOMCONTENTLOADED,
DOWNLOAD,
FILECHOOSER,
FRAMEATTACHED,
FRAMEDETACHED,
FRAMENAVIGATED,
LOAD,
PAGEERROR,
POPUP,
REQUEST,
REQUESTFAILED,
REQUESTFINISHED,
RESPONSE,
WEBSOCKET,
WORKER,
}
void addListener(EventType type, Listener<EventType> listener);
void removeListener(EventType type, Listener<EventType> listener);
void onClose(Runnable handler);
void offClose(Runnable handler);
@@ -29,15 +29,6 @@ public interface WebSocket {
String text();
}
enum EventType {
CLOSE,
FRAMERECEIVED,
FRAMESENT,
SOCKETERROR,
}
void addListener(EventType type, Listener<EventType> listener);
void removeListener(EventType type, Listener<EventType> listener);
void onClose(Runnable handler);
void offClose(Runnable handler);
@@ -25,12 +25,6 @@ import java.util.function.Consumer;
* worker is gone.
*/
public interface Worker {
enum EventType {
CLOSE,
}
void addListener(EventType type, Listener<EventType> listener);
void removeListener(EventType type, Listener<EventType> listener);
void onClose(Consumer<Worker> handler);
void offClose(Consumer<Worker> handler);
@@ -21,7 +21,6 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.microsoft.playwright.*;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
@@ -46,6 +45,11 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
final TimeoutSettings timeoutSettings = new TimeoutSettings();
Path videosDir;
enum EventType {
CLOSE,
PAGE,
}
BrowserContextImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
super(parent, type, guid, initializer);
if (parent instanceof BrowserImpl) {
@@ -55,16 +59,6 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
}
}
@Override
public void addListener(EventType type, Listener<EventType> listener) {
listeners.add(type, listener);
}
@Override
public void removeListener(EventType type, Listener<EventType> listener) {
listeners.remove(type, listener);
}
@Override
public void onClose(Runnable handler) {
listeners.add(EventType.CLOSE, handler);
@@ -359,7 +353,7 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
private String errorMessage;
WaitableContextClose() {
addListener(EventType.CLOSE, this);
listeners.add(EventType.CLOSE, this);
}
@Override
@@ -384,7 +378,7 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
@Override
public void dispose() {
removeListener(EventType.CLOSE, this);
listeners.remove(EventType.CLOSE, this);
}
}
@@ -37,20 +37,14 @@ class BrowserImpl extends ChannelOwner implements Browser {
private final ListenerCollection<EventType> listeners = new ListenerCollection<>();
private boolean isConnected = true;
enum EventType {
DISCONNECTED,
}
BrowserImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
super(parent, type, guid, initializer);
}
@Override
public void addListener(EventType type, Listener<EventType> listener) {
listeners.add(type, listener);
}
@Override
public void removeListener(EventType type, Listener<EventType> listener) {
listeners.remove(type, listener);
}
@Override
public void onDisconnected(Runnable handler) {
listeners.add(EventType.DISCONNECTED, handler);
@@ -14,7 +14,9 @@
* limitations under the License.
*/
package com.microsoft.playwright;
package com.microsoft.playwright.impl;
import com.microsoft.playwright.Event;
public interface Listener<EventType> {
void handle(Event<EventType> event);
@@ -17,7 +17,6 @@
package com.microsoft.playwright.impl;
import com.microsoft.playwright.Event;
import com.microsoft.playwright.Listener;
import java.util.*;
import java.util.function.Consumer;
@@ -89,7 +88,7 @@ class ListenerCollection <EventType> {
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RunnableWrapper<?> that = (RunnableWrapper<?>) o;
ConsumerWrapper<?> that = (ConsumerWrapper<?>) o;
return Objects.equals(callback, that.callback);
}
@@ -18,15 +18,12 @@ package com.microsoft.playwright.impl;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import com.microsoft.playwright.*;
import java.nio.file.Path;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.regex.Pattern;
import static com.microsoft.playwright.impl.Serialization.gson;
@@ -68,6 +65,28 @@ public class PageImpl extends ChannelOwner implements Page {
private final TimeoutSettings timeoutSettings;
private VideoImpl video;
enum EventType {
CLOSE,
CONSOLE,
CRASH,
DIALOG,
DOMCONTENTLOADED,
DOWNLOAD,
FILECHOOSER,
FRAMEATTACHED,
FRAMEDETACHED,
FRAMENAVIGATED,
LOAD,
PAGEERROR,
POPUP,
REQUEST,
REQUESTFAILED,
REQUESTFINISHED,
RESPONSE,
WEBSOCKET,
WORKER,
}
PageImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
super(parent, type, guid, initializer);
browserContext = (BrowserContextImpl) parent;
@@ -217,16 +236,6 @@ public class PageImpl extends ChannelOwner implements Page {
sendMessage("setFileChooserInterceptedNoReply", params);
}
@Override
public void addListener(EventType type, Listener<EventType> listener) {
listeners.add(type, listener);
}
@Override
public void removeListener(EventType type, Listener<EventType> listener) {
listeners.remove(type, listener);
}
@Override
public void onClose(Runnable handler) {
listeners.add(EventType.CLOSE, handler);
@@ -1207,7 +1216,7 @@ public class PageImpl extends ChannelOwner implements Page {
WaitablePageClose() {
subscribedEvents = Arrays.asList(EventType.CLOSE, EventType.CRASH);
for (EventType e : subscribedEvents) {
addListener(e, this);
listeners.add(e, this);
}
}
@@ -1236,7 +1245,7 @@ public class PageImpl extends ChannelOwner implements Page {
@Override
public void dispose() {
for (EventType e : subscribedEvents) {
removeListener(e, this);
listeners.remove(e, this);
}
}
}
@@ -17,8 +17,6 @@
package com.microsoft.playwright.impl;
import com.microsoft.playwright.Event;
import com.microsoft.playwright.Listener;
import com.microsoft.playwright.Page;
import java.util.function.Predicate;
@@ -31,21 +31,18 @@ class WebSocketImpl extends ChannelOwner implements WebSocket {
private final PageImpl page;
private boolean isClosed;
public WebSocketImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
enum EventType {
CLOSE,
FRAMERECEIVED,
FRAMESENT,
SOCKETERROR,
}
WebSocketImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
super(parent, type, guid, initializer);
page = (PageImpl) parent;
}
@Override
public void addListener(EventType type, Listener<EventType> listener) {
listeners.add(type, listener);
}
@Override
public void removeListener(EventType type, Listener<EventType> listener) {
listeners.remove(type, listener);
}
@Override
public void onClose(Runnable handler) {
listeners.add(EventType.CLOSE, handler);
@@ -127,7 +124,7 @@ class WebSocketImpl extends ChannelOwner implements WebSocket {
WaitableWebSocketError() {
subscribedEvents = Arrays.asList(EventType.CLOSE, EventType.SOCKETERROR);
for (EventType e : subscribedEvents) {
addListener(e, this);
listeners.add(e, this);
}
}
@@ -156,7 +153,7 @@ class WebSocketImpl extends ChannelOwner implements WebSocket {
@Override
public void dispose() {
for (EventType e : subscribedEvents) {
removeListener(e, this);
listeners.remove(e, this);
}
}
}
@@ -32,20 +32,14 @@ class WorkerImpl extends ChannelOwner implements Worker {
private final ListenerCollection<EventType> listeners = new ListenerCollection<>();
PageImpl page;
enum EventType {
CLOSE,
}
WorkerImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
super(parent, type, guid, initializer);
}
@Override
public void addListener(EventType type, Listener<EventType> listener) {
listeners.add(type, listener);
}
@Override
public void removeListener(EventType type, Listener<EventType> listener) {
listeners.remove(type, listener);
}
@Override
public void onClose(Consumer<Worker> handler) {
listeners.add(EventType.CLOSE, handler);
@@ -16,7 +16,10 @@
package com.microsoft.playwright;
import org.junit.jupiter.api.*;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import java.io.IOException;
@@ -22,8 +22,6 @@ import org.junit.jupiter.api.Test;
import java.io.OutputStreamWriter;
import java.util.List;
import static com.microsoft.playwright.BrowserContext.EventType.PAGE;
import static com.microsoft.playwright.Page.EventType.POPUP;
import static org.junit.jupiter.api.Assertions.*;
public class TestBrowserContextBasic extends TestBase {
@@ -181,7 +179,7 @@ public class TestBrowserContextBasic extends TestBase {
}
});
Page[] popup = {null};
context.addListener(PAGE, event -> popup[0] = (Page) event.data());
context.onPage(page1 -> popup[0] = page1);
page.navigate(server.EMPTY_PAGE);
page.click("'Click me'");
context.close();
@@ -19,7 +19,6 @@ package com.microsoft.playwright;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIf;
import static com.microsoft.playwright.Utils.getOS;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -20,7 +20,6 @@ import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import static java.util.Arrays.asList;
@@ -23,11 +23,9 @@ import org.junit.jupiter.api.condition.EnabledIf;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import static com.microsoft.playwright.Keyboard.Modifier.SHIFT;
import static com.microsoft.playwright.Mouse.Button.RIGHT;
import static com.microsoft.playwright.Page.EventType.CONSOLE;
import static org.junit.jupiter.api.Assertions.*;
public class TestClick extends TestBase {
@@ -141,7 +139,7 @@ public class TestClick extends TestBase {
void shouldClickOffscreenButtons() {
page.navigate(server.PREFIX + "/offscreenbuttons.html");
List<String> messages = new ArrayList<>();
page.addListener(CONSOLE, event -> messages.add(((ConsoleMessage) event.data()).text()));
page.onConsole(message -> messages.add(message.text()));
for (int i = 0; i < 11; ++i) {
// We might've scrolled to click a button - reset to (0, 0).
page.evaluate("() => window.scrollTo(0, 0)");
@@ -223,7 +223,7 @@ public class TestDefaultBrowserContext2 extends TestBase {
void shouldFireCloseEventForAPersistentContext() {
launchPersistent();
boolean[] closed = {false};
persistentContext.addListener(BrowserContext.EventType.CLOSE, event -> closed[0] = true);
persistentContext.onClose(() -> closed[0] = true);
closePersistentContext();
assertTrue(closed[0]);
}
@@ -18,11 +18,9 @@ package com.microsoft.playwright;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIf;
import org.junit.jupiter.api.condition.EnabledIf;
import static com.microsoft.playwright.Dialog.Type.ALERT;
import static com.microsoft.playwright.Dialog.Type.PROMPT;
import static com.microsoft.playwright.Page.EventType.DIALOG;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
@@ -30,8 +28,7 @@ public class TestDialog extends TestBase {
@Test
void shouldFire() {
page.addListener(DIALOG, event -> {
Dialog dialog = (Dialog) event.data();
page.onDialog(dialog -> {
assertEquals(ALERT, dialog.type());
assertEquals( "", dialog.defaultValue());
assertEquals( "yo", dialog.message());
@@ -42,8 +39,7 @@ public class TestDialog extends TestBase {
@Test
void shouldAllowAcceptingPrompts() {
page.addListener(DIALOG, event -> {
Dialog dialog = (Dialog) event.data();
page.onDialog(dialog -> {
assertEquals(PROMPT, dialog.type());
assertEquals("yes.", dialog.defaultValue());
assertEquals("question?", dialog.message());
@@ -55,8 +51,7 @@ public class TestDialog extends TestBase {
@Test
void shouldDismissThePrompt() {
page.addListener(DIALOG, event -> {
Dialog dialog = (Dialog) event.data();
page.onDialog(dialog -> {
dialog.dismiss();
});
Object result = page.evaluate("() => prompt('question?')");
@@ -65,8 +60,7 @@ public class TestDialog extends TestBase {
@Test
void shouldAcceptTheConfirmPrompt() {
page.addListener(DIALOG, event -> {
Dialog dialog = (Dialog) event.data();
page.onDialog(dialog -> {
dialog.accept();
});
Object result = page.evaluate("() => confirm('boolean?')");
@@ -75,8 +69,7 @@ public class TestDialog extends TestBase {
@Test
void shouldDismissTheConfirmPrompt() {
page.addListener(DIALOG, event -> {
Dialog dialog = (Dialog) event.data();
page.onDialog(dialog -> {
dialog.dismiss();
});
Object result = page.evaluate("() => confirm('boolean?')");
@@ -19,7 +19,8 @@ package com.microsoft.playwright;
import org.junit.jupiter.api.Test;
import static com.microsoft.playwright.Utils.mapOf;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
public class TestDispatchEvent extends TestBase {
@@ -21,8 +21,10 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIf;
import org.junit.jupiter.api.condition.EnabledIf;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -30,7 +32,6 @@ import java.time.Duration;
import java.time.Instant;
import static com.microsoft.playwright.Keyboard.Modifier.ALT;
import static com.microsoft.playwright.Page.EventType.DOWNLOAD;
import static com.microsoft.playwright.Utils.copy;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.nio.file.Files.readAllBytes;
@@ -249,16 +250,15 @@ public class TestDownload extends TestBase {
Page page = browser.newPage(new Browser.NewPageOptions().withAcceptDownloads(true));
page.setContent("<a href='" + server.PREFIX + "/download'>download</a>");
@SuppressWarnings("unchecked")
Event<Page.EventType>[] event = new Event[]{null};
page.addListener(DOWNLOAD, e -> event[0] = e);
Download[] download = {null};
page.onDownload(d -> download[0] = d);
page.click("a");
Instant start = Instant.now();
while (event[0] == null) {
while (download[0] == null) {
page.waitForTimeout(100);
assertTrue(Duration.between(start, Instant.now()).getSeconds() < 30, "Timed out");
}
Download download = (Download) event[0].data();
Path path = download.path();
Path path = download[0].path();
assertTrue(Files.exists(path));
byte[] bytes = readAllBytes(path);
assertEquals("Hello world", new String(bytes, UTF_8));
@@ -269,17 +269,16 @@ public class TestDownload extends TestBase {
void shouldReportDownloadPathWithinPageOnDownloadHandlerForBlobs() throws IOException {
Page page = browser.newPage(new Browser.NewPageOptions().withAcceptDownloads(true));
@SuppressWarnings("unchecked")
Event<Page.EventType>[] event = new Event[]{null};
page.addListener(DOWNLOAD, e -> event[0] = e);
Download[] download = {null};
page.onDownload(d -> download[0] = d);
page.navigate(server.PREFIX + "/download-blob.html");
page.click("a");
Instant start = Instant.now();
while (event[0] == null) {
while (download[0] == null) {
page.waitForTimeout(100);
assertTrue(Duration.between(start, Instant.now()).getSeconds() < 1, "Timed out");
}
Download download = (Download) event[0].data();
Path path = download.path();
Path path = download[0].path();
assertTrue(Files.exists(path));
byte[] bytes = readAllBytes(path);
assertEquals("Hello world", new String(bytes, UTF_8));
@@ -2,9 +2,6 @@ package com.microsoft.playwright;
import org.junit.jupiter.api.Test;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.junit.jupiter.api.Assertions.*;
public class TestElementHandleSelectText extends TestBase {
@@ -21,8 +21,6 @@ import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import static com.microsoft.playwright.Page.EventType.CONSOLE;
import static com.microsoft.playwright.Page.EventType.POPUP;
import static com.microsoft.playwright.Utils.mapOf;
import static java.util.Arrays.asList;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -111,7 +109,7 @@ public class TestGeolocation extends TestBase {
context.grantPermissions(asList("geolocation"));
page.navigate(server.EMPTY_PAGE);
List<String> messages = new ArrayList<>();
page.addListener(CONSOLE, event -> messages.add(((ConsoleMessage) event.data()).text()));
page.onConsole(message -> messages.add(message.text()));
context.setGeolocation(new Geolocation());
page.evaluate("() => {\n" +
" navigator.geolocation.watchPosition(pos => {\n" +
@@ -19,12 +19,10 @@ package com.microsoft.playwright;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.stream.JsonReader;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
@@ -28,8 +28,6 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.stream.Collectors;
import static com.microsoft.playwright.Page.EventType.REQUEST;
import static com.microsoft.playwright.Page.EventType.RESPONSE;
import static com.microsoft.playwright.Utils.attachFrame;
import static com.microsoft.playwright.Utils.mapOf;
import static org.junit.jupiter.api.Assertions.*;
@@ -38,7 +36,7 @@ public class TestNetworkRequest extends TestBase {
@Test
void shouldWorkForMainFrameNavigationRequest() {
List<Request> requests = new ArrayList<>();
page.addListener(REQUEST, event -> requests.add((Request) event.data()));
page.onRequest(request -> requests.add(request));
page.navigate(server.EMPTY_PAGE);
assertEquals(1, requests.size());
assertEquals(page.mainFrame(), requests.get(0).frame());
@@ -48,7 +46,7 @@ public class TestNetworkRequest extends TestBase {
void shouldWorkForSubframeNavigationRequest() {
page.navigate(server.EMPTY_PAGE);
List<Request> requests = new ArrayList<>();
page.addListener(REQUEST, event -> requests.add((Request) event.data()));
page.onRequest(request -> requests.add(request));
attachFrame(page, "frame1", server.EMPTY_PAGE);
assertEquals(1, requests.size());
assertEquals(page.frames().get(1), requests.get(0).frame());
@@ -58,7 +56,7 @@ public class TestNetworkRequest extends TestBase {
void shouldWorkForFetchRequests() {
page.navigate(server.EMPTY_PAGE);
List<Request> requests = new ArrayList<>();
page.addListener(REQUEST, event -> requests.add((Request) event.data()));
page.onRequest(request -> requests.add(request));
page.evaluate("() => fetch('/digits/1.png')");
assertEquals(1, requests.size());
assertEquals(page.mainFrame(), requests.get(0).frame());
@@ -68,7 +66,7 @@ public class TestNetworkRequest extends TestBase {
void shouldWorkForARedirect() {
server.setRedirect("/foo.html", "/empty.html");
List<Request> requests = new ArrayList<>();
page.addListener(REQUEST, event -> requests.add((Request) event.data()));
page.onRequest(request -> requests.add(request));
page.navigate(server.PREFIX + "/foo.html");
assertEquals(2, requests.size());
@@ -152,7 +150,7 @@ public class TestNetworkRequest extends TestBase {
exchange.getResponseBody().close();
});
Request[] request = {null};
page.addListener(REQUEST, event -> request[0] = (Request) event.data());
page.onRequest(r -> request[0] = r);
page.evaluate("() => fetch('./post', { method: 'POST', body: JSON.stringify({foo: 'bar'})})");
assertNotNull(request[0]);
assertEquals("{\"foo\":\"bar\"}", request[0].postData());
@@ -166,7 +164,7 @@ public class TestNetworkRequest extends TestBase {
exchange.getResponseBody().close();
});
Request[] request = {null};
page.addListener(REQUEST, event -> request[0] = (Request) event.data());
page.onRequest(r -> request[0] = r);
page.evaluate("async () => {\n" +
" await fetch('./post', { method: 'POST', body: new Uint8Array(Array.from(Array(256).keys())) });\n" +
"}");
@@ -186,7 +184,7 @@ public class TestNetworkRequest extends TestBase {
exchange.getResponseBody().close();
});
Request[] request = {null};
page.addListener(REQUEST, event -> request[0] = (Request) event.data());
page.onRequest(r -> request[0] = r);
page.route("/post", route -> route.continue_());
page.evaluate("async () => {\n" +
" await fetch('./post', { method: 'POST', body: new Uint8Array(Array.from(Array(256).keys())) });\n" +
@@ -228,7 +226,7 @@ public class TestNetworkRequest extends TestBase {
// 2. Subscribe to page request events.
page.navigate(server.EMPTY_PAGE);
List<Request> requests = new ArrayList<>();
page.addListener(REQUEST, event -> requests.add((Request) event.data()));
page.onRequest(request -> requests.add(request));
// 3. Connect to EventSource in browser and return first message.
Object result = page.evaluate("() => {\n" +
" const eventSource = new EventSource('/sse');\n" +
@@ -243,8 +241,7 @@ public class TestNetworkRequest extends TestBase {
@Test
void shouldReturnNavigationBit() {
Map<String, Request> requests = new HashMap<>();
page.addListener(REQUEST, event -> {
Request request = (Request) event.data();
page.onRequest(request -> {
String name = request.url();
int lastSlash = name.lastIndexOf('/');
if (lastSlash != -1) {
@@ -264,7 +261,7 @@ public class TestNetworkRequest extends TestBase {
@Test
void shouldReturnNavigationBitWhenNavigatingToImage() {
List<Request> requests = new ArrayList<>();
page.addListener(REQUEST, event -> requests.add((Request) event.data()));
page.onRequest(request -> requests.add(request));
page.navigate(server.PREFIX + "/pptr.png");
assertTrue(requests.get(0).isNavigationRequest());
}
@@ -24,12 +24,8 @@ import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.Semaphore;
import java.util.regex.Pattern;
import static com.microsoft.playwright.Page.EventType.REQUESTFINISHED;
import static com.microsoft.playwright.Page.EventType.RESPONSE;
import static org.junit.jupiter.api.Assertions.*;
public class TestNetworkResponse extends TestBase {
@@ -102,8 +98,8 @@ public class TestNetworkResponse extends TestBase {
});
// Setup page to trap response.
boolean[] requestFinished = {false};
page.addListener(REQUESTFINISHED, event -> {
requestFinished[0] |= ((Request) event.data()).url().contains("/get");
page.onRequestFinished(request -> {
requestFinished[0] |= request.url().contains("/get");
});
// send request and wait for server response
Response pageResponse = page.waitForResponse(() -> page.evaluate("() => fetch('./get', { method: 'GET'})"));
@@ -25,7 +25,6 @@ import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static com.microsoft.playwright.Page.EventType.*;
import static com.microsoft.playwright.Page.LoadState.DOMCONTENTLOADED;
import static com.microsoft.playwright.Page.LoadState.LOAD;
import static org.junit.jupiter.api.Assertions.*;
@@ -91,7 +90,7 @@ public class TestPageBasic extends TestBase {
// fire.
newPage.click("body");
boolean[] didShowDialog = {false};
newPage.addListener(DIALOG, event -> didShowDialog[0] = true);
newPage.onDialog(dialog -> didShowDialog[0] = true);
newPage.close();
assertFalse(didShowDialog[0]);
}
@@ -265,7 +264,7 @@ public class TestPageBasic extends TestBase {
void pagePressShouldWorkForEnter() {
page.setContent("<input onkeypress='console.log(\"press\")'></input>");
List<ConsoleMessage> messages = new ArrayList<>();
page.addListener(CONSOLE, event -> messages.add((ConsoleMessage) event.data()));
page.onConsole(message -> messages.add(message));
page.press("input", "Enter");
assertEquals("press", messages.get(0).text());
}
@@ -23,7 +23,6 @@ import java.util.function.Supplier;
import static com.microsoft.playwright.ColorScheme.DARK;
import static com.microsoft.playwright.ColorScheme.LIGHT;
import static com.microsoft.playwright.Page.EmulateMediaParams.Media.PRINT;
import static com.microsoft.playwright.Page.EventType.POPUP;
import static com.microsoft.playwright.Utils.attachFrame;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -18,11 +18,9 @@ package com.microsoft.playwright;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIf;
import org.junit.jupiter.api.condition.EnabledIf;
import java.util.Map;
import static com.microsoft.playwright.Page.EventType.FRAMENAVIGATED;
import static com.microsoft.playwright.Utils.mapOf;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyMap;
@@ -174,8 +172,7 @@ public class TestPageEvaluate extends TestBase {
@Test
void shouldWorkRightAfterFramenavigated() {
Object[] frameEvaluation = {null};
page.addListener(FRAMENAVIGATED, event -> {
Frame frame = (Frame) event.data();
page.onFrameNavigated(frame -> {
frameEvaluation[0] = frame.evaluate("() => 6 * 7");
});
page.navigate(server.EMPTY_PAGE);
@@ -186,8 +183,7 @@ public class TestPageEvaluate extends TestBase {
void shouldWorkRightAfterACrossOriginNavigation() {
page.navigate(server.EMPTY_PAGE);
Object[] frameEvaluation = {null};
page.addListener(FRAMENAVIGATED, event -> {
Frame frame = (Frame) event.data();
page.onFrameNavigated(frame -> {
frameEvaluation[0] = frame.evaluate("() => 6 * 7");
});
page.navigate(server.CROSS_PROCESS_PREFIX + "/empty.html");
@@ -21,7 +21,6 @@ import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import static com.microsoft.playwright.Page.EventType.*;
import static java.util.Arrays.asList;
import static org.junit.jupiter.api.Assertions.*;
@@ -29,7 +28,7 @@ public class TestPageEventNetwork extends TestBase {
@Test
void PageEventsRequest() {
List<Request> requests = new ArrayList<>();
page.addListener(REQUEST, event -> requests.add((Request) event.data()));
page.onRequest(request -> requests.add(request));
page.navigate(server.EMPTY_PAGE);
assertEquals(1, requests.size());
assertEquals(server.EMPTY_PAGE, requests.get(0).url());
@@ -43,7 +42,7 @@ public class TestPageEventNetwork extends TestBase {
@Test
void PageEventsResponse() {
List<Response> responses = new ArrayList<>();
page.addListener(RESPONSE, event -> responses.add((Response) event.data()));
page.onResponse(response -> responses.add(response));
page.navigate(server.EMPTY_PAGE);
assertEquals(1, responses.size());
assertEquals(server.EMPTY_PAGE, responses.get(0).url());
@@ -56,7 +55,7 @@ public class TestPageEventNetwork extends TestBase {
void PageEventsRequestFailed() {
server.setRoute("/one-style.css", exchange -> exchange.getResponseBody().close());
List<Request> failedRequests = new ArrayList<>();
page.addListener(REQUESTFAILED, event -> failedRequests.add((Request) event.data()));
page.onRequestFailed(request -> failedRequests.add(request));
page.navigate(server.PREFIX + "/one-style.html");
assertEquals(1, failedRequests.size());
assertTrue(failedRequests.get(0).url().contains("one-style.css"));
@@ -96,8 +95,8 @@ public class TestPageEventNetwork extends TestBase {
@Test
void shouldFireEventsInProperOrder() {
List<String> events = new ArrayList<>();
page.addListener(REQUEST, event -> events.add("request"));
page.addListener(RESPONSE, event -> events.add("response"));
page.onRequest(request -> events.add("request"));
page.onResponse(response -> events.add("response"));
Response response = page.navigate(server.EMPTY_PAGE);
assertNull(response.finished());
events.add("requestfinished");
@@ -107,20 +106,16 @@ public class TestPageEventNetwork extends TestBase {
@Test
void shouldSupportRedirects() {
List<String> events = new ArrayList<>();
page.addListener(REQUEST, event -> {
Request request = (Request) event.data();
page.onRequest(request -> {
events.add(request.method() + " " + request.url());
});
page.addListener(RESPONSE,event -> {
Response response = (Response) event.data();
page.onResponse(response -> {
events.add(response.status() + " " + response.url());
});
page.addListener(REQUESTFINISHED, event -> {
Request request = (Request) event.data();
page.onRequestFinished(request -> {
events.add("DONE " + request.url());
});
page.addListener(REQUESTFAILED, event -> {
Request request = (Request) event.data();
page.onRequestFailed(request -> {
events.add("FAIL " + request.url());
});
server.setRedirect("/foo.html", "/empty.html");
@@ -18,18 +18,18 @@ package com.microsoft.playwright;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIf;
import org.junit.jupiter.api.condition.EnabledIf;
import java.io.OutputStreamWriter;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.regex.Pattern;
import static com.microsoft.playwright.Page.EventType.REQUEST;
import static com.microsoft.playwright.Page.EventType.REQUESTFAILED;
import static com.microsoft.playwright.Utils.mapOf;
import static java.util.Arrays.asList;
import static org.junit.jupiter.api.Assertions.*;
@@ -198,8 +198,7 @@ public class TestPageRoute extends TestBase {
void shouldBeAbortable() {
page.route(Pattern.compile(".*\\.css$"), route -> route.abort());
boolean[] failed = {false};
page.addListener(REQUESTFAILED, event -> {
Request request = (Request) event.data();
page.onRequestFailed(request -> {
if (request.url().contains(".css"))
failed[0] = true;
});
@@ -212,19 +211,19 @@ public class TestPageRoute extends TestBase {
@Test
void shouldBeAbortableWithCustomErrorCodes() {
page.route("**/*", route -> route.abort("internetdisconnected"));
Request[] failedRequest = {null};
page.addListener(REQUESTFAILED, event -> failedRequest[0] = (Request) event.data());
try {
page.navigate(server.EMPTY_PAGE);
} catch (PlaywrightException e) {
}
assertNotNull(failedRequest[0]);
Request failedRequest = page.waitForRequestFailed(() -> {
try {
page.navigate(server.EMPTY_PAGE);
} catch (PlaywrightException e) {
}
});
assertNotNull(failedRequest);
if (isWebKit())
assertEquals("Request intercepted", failedRequest[0].failure().errorText());
assertEquals("Request intercepted", failedRequest.failure().errorText());
else if (isFirefox())
assertEquals("NS_ERROR_OFFLINE", failedRequest[0].failure().errorText());
assertEquals("NS_ERROR_OFFLINE", failedRequest.failure().errorText());
else
assertEquals("net::ERR_INTERNET_DISCONNECTED", failedRequest[0].failure().errorText());
assertEquals("net::ERR_INTERNET_DISCONNECTED", failedRequest.failure().errorText());
}
@Test
@@ -18,7 +18,6 @@ package com.microsoft.playwright;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -18,7 +18,6 @@ package com.microsoft.playwright;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Duration;
@@ -26,6 +25,7 @@ import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;
import static java.util.Arrays.asList;
import static org.junit.jupiter.api.Assertions.*;
@@ -79,11 +79,11 @@ public class TestPageSetInputFiles extends TestBase {
void shouldEmitEventAddListenerRemoveListener() {
page.setContent("<input type=file>");
FileChooser[] chooser = { null };
page.addListener(Page.EventType.FILECHOOSER, new Listener<Page.EventType>() {
page.onFileChooser(new Consumer<FileChooser>() {
@Override
public void handle(Event<Page.EventType> event) {
chooser[0] = (FileChooser) event.data();
page.removeListener(Page.EventType.FILECHOOSER, this);
public void accept(FileChooser fileChooser) {
chooser[0] = fileChooser;
page.offFileChooser(this);
}
});
page.click("input");
@@ -198,8 +198,7 @@ public class TestPageSetInputFiles extends TestBase {
@Test
void shouldBeAbleToReadSelectedFile() {
page.setContent("<input type=file>");
page.addListener(Page.EventType.FILECHOOSER, event -> {
FileChooser fileChooser = (FileChooser) event.data();
page.onFileChooser(fileChooser -> {
fileChooser.setFiles(FILE_TO_UPLOAD);
});
Object content = page.evalOnSelector("input", "async picker => {\n" +
@@ -216,12 +215,11 @@ public class TestPageSetInputFiles extends TestBase {
@Test
void shouldBeAbleToResetSelectedFilesWithEmptyFileList() {
page.setContent("<input type=file>");
page.addListener(Page.EventType.FILECHOOSER, new Listener<Page.EventType>() {
page.onFileChooser(new Consumer<FileChooser>() {
@Override
public void handle(Event<Page.EventType> event) {
FileChooser fileChooser = (FileChooser) event.data();
public void accept(FileChooser fileChooser) {
fileChooser.setFiles(FILE_TO_UPLOAD);
page.removeListener(Page.EventType.FILECHOOSER, this);
page.offFileChooser(this);
}
});
Object fileLength1 = page.evalOnSelector("input", "async picker => {\n" +
@@ -231,12 +229,11 @@ public class TestPageSetInputFiles extends TestBase {
"}");
assertEquals(1, fileLength1);
page.addListener(Page.EventType.FILECHOOSER, new Listener<Page.EventType>() {
page.onFileChooser(new Consumer<FileChooser>() {
@Override
public void handle(Event<Page.EventType> event) {
FileChooser fileChooser = (FileChooser) event.data();
public void accept(FileChooser fileChooser) {
fileChooser.setFiles(new Path[0]);
page.removeListener(Page.EventType.FILECHOOSER, this);
page.offFileChooser(this);
}
});
Object fileLength2 = page.evalOnSelector("input", "async picker => {\n" +
@@ -20,12 +20,10 @@ import org.junit.jupiter.api.Test;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
import static com.microsoft.playwright.Page.EventType.FRAMENAVIGATED;
import static com.microsoft.playwright.Utils.*;
import static com.microsoft.playwright.Utils.expectedSSLError;
import static org.junit.jupiter.api.Assertions.*;
public class TestPageWaitForNavigation extends TestBase {
@@ -135,10 +133,9 @@ public class TestPageWaitForNavigation extends TestBase {
void shouldWorkWhenSubframeIssuesWindowStop() {
server.setRoute("/frames/style.css", exchange -> {});
boolean[] frameWindowStopCalled = {false};
page.addListener(Page.EventType.FRAMEATTACHED, event -> {
Frame frame = (Frame) event.data();
page.addListener(FRAMENAVIGATED, event1 -> {
if (frame.equals(event1.data())) {
page.onFrameAttached(frame -> {
page.onFrameNavigated(frame1 -> {
if (frame.equals(frame1)) {
frame.evaluate("window.stop()");
frameWindowStopCalled[0] = true;
}
@@ -20,7 +20,6 @@ import org.junit.jupiter.api.Test;
import java.util.regex.Pattern;
import static com.microsoft.playwright.Page.EventType.REQUEST;
import static org.junit.jupiter.api.Assertions.*;
public class TestPageWaitForRequest extends TestBase {
@@ -18,8 +18,6 @@ package com.microsoft.playwright;
import org.junit.jupiter.api.Test;
import static com.microsoft.playwright.Page.EventType.REQUEST;
import static com.microsoft.playwright.Page.EventType.RESPONSE;
import static org.junit.jupiter.api.Assertions.*;
public class TestPageWaitForResponse extends TestBase {
@@ -21,7 +21,6 @@ import org.junit.jupiter.api.condition.DisabledIf;
import org.junit.jupiter.api.condition.EnabledIf;
import org.junit.jupiter.api.io.TempDir;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -24,7 +24,6 @@ import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import static com.microsoft.playwright.Page.EventType.POPUP;
import static com.microsoft.playwright.Page.LoadState.DOMCONTENTLOADED;
import static com.microsoft.playwright.Utils.mapOf;
import static org.junit.jupiter.api.Assertions.*;
@@ -24,7 +24,6 @@ import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import static com.microsoft.playwright.Page.EventType.RESPONSE;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.jupiter.api.Assertions.*;
@@ -19,7 +19,6 @@ package com.microsoft.playwright;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIf;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
@@ -16,7 +16,6 @@
package com.microsoft.playwright;
import com.microsoft.playwright.impl.ElementHandleImpl;
import org.junit.jupiter.api.Test;
import java.nio.file.Paths;
@@ -23,7 +23,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicBoolean;
import static com.microsoft.playwright.Utils.mapOf;
import static java.util.Arrays.asList;
@@ -23,7 +23,6 @@ import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import static com.microsoft.playwright.Page.EventType.CONSOLE;
import static com.microsoft.playwright.Utils.mapOf;
import static java.util.Arrays.asList;
import static org.junit.jupiter.api.Assertions.*;
@@ -73,7 +72,7 @@ public class TestWaitForFunction extends TestBase {
@Test
void shouldAvoidSideEffectsAfterTimeout() {
int[] counter = { 0 };
page.addListener(CONSOLE, event -> ++counter[0]);
page.onConsole(message -> ++counter[0]);
try {
JSHandle result = page.waitForFunction("() => {\n" +
@@ -239,8 +238,7 @@ public class TestWaitForFunction extends TestBase {
void shouldNotBeCalledAfterFinishingSuccessfully() {
page.navigate(server.EMPTY_PAGE);
List<String> messages = new ArrayList<>();
page.addListener(CONSOLE, event -> {
ConsoleMessage msg = (ConsoleMessage) event.data();
page.onConsole(msg -> {
if (msg.text().startsWith("waitForFunction")) {
messages.add(msg.text());
}
@@ -266,10 +264,10 @@ public class TestWaitForFunction extends TestBase {
void shouldNotBeCalledAfterFinishingUnsuccessfully() {
page.navigate(server.EMPTY_PAGE);
List<String> messages = new ArrayList<>();
page.addListener(CONSOLE, event -> {
ConsoleMessage msg = (ConsoleMessage) event.data();
if (msg.text().startsWith("waitForFunction"))
page.onConsole(msg -> {
if (msg.text().startsWith("waitForFunction")) {
messages.add(msg.text());
}
});
try {
page.waitForFunction("() => {\n" +
@@ -17,11 +17,7 @@
package com.microsoft.playwright;
import org.java_websocket.WebSocket;
import org.java_websocket.drafts.Draft;
import org.java_websocket.exceptions.InvalidDataException;
import org.java_websocket.framing.Framedata;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.handshake.ServerHandshakeBuilder;
import org.java_websocket.server.WebSocketServer;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
@@ -29,14 +25,11 @@ import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import static com.microsoft.playwright.Page.EventType.WEBSOCKET;
import static com.microsoft.playwright.WebSocket.EventType.*;
import static java.util.Arrays.asList;
import static org.junit.jupiter.api.Assertions.*;
@@ -105,11 +98,10 @@ public class TestWebSocket extends TestBase {
boolean[] socketClosed = {false};
List<String> log = new ArrayList<>();
com.microsoft.playwright.WebSocket[] webSocket = {null};
page.addListener(WEBSOCKET, event -> {
com.microsoft.playwright.WebSocket ws = (com.microsoft.playwright.WebSocket) event.data();
page.onWebSocket(ws -> {
log.add("open<" + ws.url() + ">");
webSocket[0] = ws;
ws.addListener(com.microsoft.playwright.WebSocket.EventType.CLOSE, closeEvent -> {
ws.onClose(() -> {
log.add("close");
socketClosed[0] = true;
});
@@ -127,12 +119,11 @@ public class TestWebSocket extends TestBase {
void shouldEmitFrameEvents() {
boolean[] socketClosed = {false};
List<String> log = new ArrayList<>();
page.addListener(WEBSOCKET, event -> {
com.microsoft.playwright.WebSocket ws = (com.microsoft.playwright.WebSocket) event.data();
page.onWebSocket(ws -> {
log.add("open");
ws.addListener(FRAMESENT, e -> log.add("sent<" + ((com.microsoft.playwright.WebSocket.FrameData) e.data()).text() + ">"));
ws.addListener(FRAMERECEIVED, e -> log.add("received<" + ((com.microsoft.playwright.WebSocket.FrameData) e.data()).text() + ">"));
ws.addListener(CLOSE, e -> { log.add("close"); socketClosed[0] = true; });
ws.onFrameSent(frameData -> log.add("sent<" + frameData.text() + ">"));
ws.onFrameReceived(frameData -> log.add("received<" + frameData.text() + ">"));
ws.onClose(() -> { log.add("close"); socketClosed[0] = true; });
});
page.evaluate("port => {\n" +
" const ws = new WebSocket('ws://localhost:' + port + '/ws');\n" +
@@ -154,10 +145,9 @@ public class TestWebSocket extends TestBase {
void shouldEmitBinaryFrameEvents() {
boolean[] socketClosed = {false};
List<com.microsoft.playwright.WebSocket.FrameData> sent = new ArrayList<>();
page.addListener(WEBSOCKET, event -> {
com.microsoft.playwright.WebSocket ws = (com.microsoft.playwright.WebSocket) event.data();
ws.addListener(CLOSE, e -> { socketClosed[0] = true; });
ws.addListener(FRAMESENT, e -> sent.add((com.microsoft.playwright.WebSocket.FrameData) e.data()));
page.onWebSocket(ws -> {
ws.onClose(() -> { socketClosed[0] = true; });
ws.onFrameSent(frameData -> sent.add(frameData));
});
page.evaluate("port => {\n" +
" const ws = new WebSocket('ws://localhost:' + port + '/ws');\n" +
@@ -181,10 +171,9 @@ public class TestWebSocket extends TestBase {
void shouldEmitError() {
boolean[] socketError = {false};
String[] error = {null};
page.addListener(WEBSOCKET, event -> {
com.microsoft.playwright.WebSocket ws = (com.microsoft.playwright.WebSocket) event.data();
ws.addListener(SOCKETERROR, e -> {
error[0] = (String) e.data();
page.onWebSocket(ws -> {
ws.onSocketError(e -> {
error[0] = e;
socketError[0] = true;
});
});
@@ -207,7 +196,7 @@ public class TestWebSocket extends TestBase {
"}", webSocketServer.getPort());
});
boolean[] error = {false};
ws.addListener(SOCKETERROR, e -> error[0] = true);
ws.onSocketError(e -> error[0] = true);
ws.waitForFrameReceived(() -> {});
page.evaluate("window.ws.close()");
assertFalse(error[0]);
@@ -20,7 +20,6 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIf;
import org.junit.jupiter.api.condition.EnabledIf;
import static com.microsoft.playwright.Page.EventType.*;
import static com.microsoft.playwright.Utils.attachFrame;
import static org.junit.jupiter.api.Assertions.*;
@@ -110,7 +109,7 @@ public class TestWorkers extends TestBase {
"() => new Worker(URL.createObjectURL(new Blob(['console.log(1)'], {type: 'application/javascript'})))"));
assertEquals(1, page.workers().size());
boolean[] destroyed = {false};
worker.addListener(Worker.EventType.CLOSE, event -> destroyed[0] = true);
worker.onClose(worker1 -> destroyed[0] = true);
page.navigate(server.CROSS_PROCESS_PREFIX + "/empty.html");
assertTrue(destroyed[0]);
assertEquals(0, page.workers().size());
@@ -23,7 +23,6 @@ import com.google.gson.JsonParser;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@@ -1075,16 +1075,6 @@ class Interface extends TypeDefinition {
if (events.isEmpty()) {
return;
}
output.add(offset + "enum EventType {");
for (int i = 0; i < events.size(); i++) {
String comma = i == events.size() ? "" : ",";
output.add(offset + " " + events.get(i).jsonName.toUpperCase() + comma);
}
output.add(offset + "}");
output.add("");
output.add(offset + "void addListener(EventType type, Listener<EventType> listener);");
output.add(offset + "void removeListener(EventType type, Listener<EventType> listener);");
for (Event e : events) {
output.add("");
e.writeListenerMethods(output, offset);