diff --git a/ci/test.mk b/ci/test.mk
index b86abb704d0db1139d28a0fe4514001aaf7f4f03..8d46c94a61a0022078952928e76d2022a0094f4c 100644
--- a/ci/test.mk
+++ b/ci/test.mk
@@ -1,4 +1,4 @@
-test: gotest gotest-wasm
+test: gotest
 
 gotest: _gotest htmlcov
 ifdef CI
@@ -12,15 +12,8 @@ codecov: _gotest
 	curl -s https://codecov.io/bash | bash -s -- -Z -f ci/out/coverage.prof
 
 _gotest:
-	echo "--- gotest" && go test -parallel=32 -coverprofile=ci/out/coverage.prof -coverpkg=./... $$TESTFLAGS ./...
+	go test -parallel=32 -coverprofile=ci/out/coverage.prof -coverpkg=./... $$TESTFLAGS ./...
 	sed -i '/_stringer\.go/d' ci/out/coverage.prof
-	sed -i '/wsjstest\/main\.go/d' ci/out/coverage.prof
 	sed -i '/wsecho\.go/d' ci/out/coverage.prof
 	sed -i '/assert\.go/d' ci/out/coverage.prof
 	sed -i '/wsgrace\.go/d' ci/out/coverage.prof
-
-gotest-wasm: wsjstest
-	echo "--- wsjstest" && ./ci/wasmtest.sh
-
-wsjstest:
-	go install ./internal/wsjstest
diff --git a/ci/wasmtest.sh b/ci/wasmtest.sh
deleted file mode 100755
index f285fdf42ba12004f904b7d7bacc9abc8b845e16..0000000000000000000000000000000000000000
--- a/ci/wasmtest.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/env bash
-
-set -euo pipefail
-
-wsjstestOut="$(mktemp -d)/wsjstestOut"
-mkfifo "$wsjstestOut"
-timeout 45s wsjstest > "$wsjstestOut" &
-
-WS_ECHO_SERVER_URL="$(head -n 1 "$wsjstestOut")"
-export WS_ECHO_SERVER_URL
-
-GOOS=js GOARCH=wasm go test -exec=wasmbrowsertest ./...
-
-kill %%
-if ! wait %% ; then
-  echo "wsjstest exited unsuccessfully"
-  exit 1
-fi
diff --git a/conn_test.go b/conn_test.go
index 8413c4c2afc2ae27df72612669d07452dbc6aff6..4c7d139021651b0fcfc7267e1f66ed5eded06e97 100644
--- a/conn_test.go
+++ b/conn_test.go
@@ -2337,3 +2337,38 @@ func checkWSTestIndex(t *testing.T, path string) {
 		}
 	}
 }
+
+func TestWASM(t *testing.T) {
+	t.Parallel()
+
+	s, closeFn := testServer(t, func(w http.ResponseWriter, r *http.Request) error {
+		c, err := websocket.Accept(w, r, &websocket.AcceptOptions{
+			Subprotocols:       []string{"echo"},
+			InsecureSkipVerify: true,
+		})
+		if err != nil {
+			return err
+		}
+		defer c.Close(websocket.StatusInternalError, "")
+
+		err = wsecho.Loop(r.Context(), c)
+		if websocket.CloseStatus(err) != websocket.StatusNormalClosure {
+			return err
+		}
+		return nil
+	}, false)
+	defer closeFn()
+
+	wsURL := strings.Replace(s.URL, "http", "ws", 1)
+
+	ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
+	defer cancel()
+
+	cmd := exec.CommandContext(ctx, "go", "test", "-exec=wasmbrowsertest", "./...")
+	cmd.Env = append(os.Environ(), "GOOS=js", "GOARCH=wasm", fmt.Sprintf("WS_ECHO_SERVER_URL=%v", wsURL))
+
+	b, err := cmd.CombinedOutput()
+	if err != nil {
+		t.Fatalf("wasm test binary failed: %v:\n%s", err, b)
+	}
+}
diff --git a/internal/wsjstest/main.go b/internal/wsjstest/main.go
deleted file mode 100644
index 96eee2c0543c23a8e72ed9df5201bd34f9574705..0000000000000000000000000000000000000000
--- a/internal/wsjstest/main.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// +build !js
-
-package main
-
-import (
-	"fmt"
-	"log"
-	"net/http"
-	"net/http/httptest"
-	"os"
-	"os/signal"
-	"strings"
-	"syscall"
-
-	"nhooyr.io/websocket"
-	"nhooyr.io/websocket/internal/wsecho"
-	"nhooyr.io/websocket/internal/wsgrace"
-)
-
-func main() {
-	log.SetPrefix("wsecho")
-
-	s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		c, err := websocket.Accept(w, r, &websocket.AcceptOptions{
-			Subprotocols:       []string{"echo"},
-			InsecureSkipVerify: true,
-		})
-		if err != nil {
-			log.Fatalf("echo server: failed to accept: %+v", err)
-		}
-		defer c.Close(websocket.StatusInternalError, "")
-
-		err = wsecho.Loop(r.Context(), c)
-		if websocket.CloseStatus(err) != websocket.StatusNormalClosure {
-			log.Fatalf("unexpected echo loop error: %+v", err)
-		}
-	}))
-	closeFn := wsgrace.Grace(s.Config)
-	defer func() {
-		err := closeFn()
-		if err != nil {
-			log.Fatal(err)
-		}
-	}()
-
-	wsURL := strings.Replace(s.URL, "http", "ws", 1)
-	fmt.Printf("%v\n", wsURL)
-
-	sigs := make(chan os.Signal, 1)
-	signal.Notify(sigs, syscall.SIGTERM)
-
-	<-sigs
-}