Migrate from karma to web-test-runner

We want to get rid of the final remnants of karma from gerrit core.
The recommended way to run tests is with web-test-runner.

Depends-On: I4e9134e04475d7375d7a09d618892edbe0b555bc
Change-Id: I2da2603951304361ba9e47ca968316c5fb29c8b1
diff --git a/web/BUILD b/web/BUILD
index 5490c23..e0a9c78 100644
--- a/web/BUILD
+++ b/web/BUILD
@@ -1,5 +1,5 @@
 load("//tools/js:eslint.bzl", "plugin_eslint")
-load("//tools/bzl:js.bzl", "gerrit_js_bundle", "karma_test")
+load("//tools/bzl:js.bzl", "gerrit_js_bundle", "web_test_runner")
 load("@npm//@bazel/typescript:index.bzl", "ts_config", "ts_project")
 
 package_group(
@@ -52,10 +52,15 @@
     entry_point = "_bazel_ts_out/plugin.js",
 )
 
-karma_test(
-    name = "karma_test",
-    srcs = ["karma_test.sh"],
-    data = [":delete-project-ts-tests"],
+web_test_runner(
+    name = "web_test_runner",
+    srcs = ["web_test_runner.sh"],
+    data = [
+        ":tsconfig",
+        ":delete-project-ts-tests",
+        "@plugins_npm//:node_modules",
+        "@ui_dev_npm//:node_modules",
+    ],
 )
 
 plugin_eslint()
diff --git a/web/gr-delete-repo.ts b/web/gr-delete-repo.ts
index ff4e0d6..91c3649 100644
--- a/web/gr-delete-repo.ts
+++ b/web/gr-delete-repo.ts
@@ -60,8 +60,8 @@
 
   static override get styles() {
     return [
-      window.Gerrit.styles.font as CSSResult,
-      window.Gerrit.styles.modal as CSSResult,
+      window.Gerrit?.styles.font as CSSResult,
+      window.Gerrit?.styles.modal as CSSResult,
       css`
         :host {
           display: block;
@@ -80,7 +80,7 @@
   }
 
   get action(): ActionInfo | undefined {
-    return this.config.actions?.[this.actionId];
+    return this.config?.actions?.[this.actionId];
   }
 
   get actionId(): string {
diff --git a/web/gr-delete-repo_test.ts b/web/gr-delete-repo_test.ts
index 2da6b2b..45ed9ce 100644
--- a/web/gr-delete-repo_test.ts
+++ b/web/gr-delete-repo_test.ts
@@ -24,16 +24,18 @@
   HttpMethod,
   RepoName,
 } from '@gerritcodereview/typescript-api/rest-api';
+import {fixture, html, assert} from '@open-wc/testing';
+import sinon from 'sinon';
 
 suite('gr-delete-repo tests', () => {
   let element: GrDeleteRepo;
-  let sendStub: sinon.SinonStub;
+  let fetchStub: sinon.SinonStub;
 
   setup(async () => {
-    sendStub = sinon.stub();
-    sendStub.returns(Promise.resolve({}));
+    fetchStub = sinon.stub();
+    fetchStub.returns(Promise.resolve({}));
 
-    element = document.createElement('gr-delete-repo');
+    element = await fixture(html`<gr-delete-repo></gr-delete-repo>`);
     element.repoName = 'test-repo-name' as RepoName;
     element.config = {
       actions: {
@@ -49,26 +51,21 @@
       getPluginName: () => 'delete-project',
       restApi: () => {
         return {
-          send: sendStub,
+          fetch: fetchStub,
           invalidateReposCache: () => {},
         };
       },
     } as unknown as PluginApi;
-    document.body.appendChild(element);
     await element.updateComplete;
   });
 
-  teardown(() => {
-    document.body.removeChild(element);
-  });
-
   test('confirm and send', () => {
     const dialog = queryAndAssert<HTMLElement>(element, '#deleteRepoDialog');
     dialog.dispatchEvent(new CustomEvent('confirm'));
-    assert.isTrue(sendStub.called);
-    const method = sendStub.firstCall.args[0] as HttpMethod;
-    const endpoint = sendStub.firstCall.args[1] as string;
-    const json = sendStub.firstCall.args[2];
+    assert.isTrue(fetchStub.called);
+    const method = fetchStub.firstCall.args[0] as HttpMethod;
+    const endpoint = fetchStub.firstCall.args[1] as string;
+    const json = fetchStub.firstCall.args[2];
     assert.equal(method, HttpMethod.DELETE);
     assert.equal(endpoint, '/projects/test-repo-name/delete-project~delete');
     assert.deepEqual(json, {force: false, preserve: false});
diff --git a/web/karma_test.sh b/web/karma_test.sh
deleted file mode 100755
index 35430ad..0000000
--- a/web/karma_test.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/bash
-
-set -euo pipefail
-./$1 start $2 --single-run \
-  --root 'plugins/delete-project/web/_bazel_ts_out_tests/' \
-  --test-files '*_test.js'
diff --git a/web/plugin.ts b/web/plugin.ts
index 7355b50..f2e845c 100644
--- a/web/plugin.ts
+++ b/web/plugin.ts
@@ -17,6 +17,6 @@
 import '@gerritcodereview/typescript-api/gerrit';
 import './gr-delete-repo';
 
-window.Gerrit.install(plugin => {
+window.Gerrit?.install(plugin => {
   plugin.registerCustomComponent('repo-command', 'gr-delete-repo');
 });
diff --git a/web/test/test-setup.ts b/web/test/test-setup.ts
index 2196ebc..4f113a1 100644
--- a/web/test/test-setup.ts
+++ b/web/test/test-setup.ts
@@ -14,30 +14,28 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import 'chai/chai.js';
 import '@gerritcodereview/typescript-api/gerrit';
 import {css} from 'lit';
+import sinon from 'sinon';
 
 declare global {
   interface Window {
-    assert: typeof chai.assert;
-    expect: typeof chai.expect;
     sinon: typeof sinon;
   }
-  let assert: typeof chai.assert;
-  let expect: typeof chai.expect;
   let sinon: typeof sinon;
 }
-window.assert = chai.assert;
-window.expect = chai.expect;
 window.sinon = sinon;
 
 window.Gerrit = {
   install: () => {},
   styles: {
+    font: css``,
     form: css``,
+    icon: css``,
     menuPage: css``,
+    spinner: css``,
     subPage: css``,
     table: css``,
+    modal: css``,
   },
 };
diff --git a/web/tsconfig.json b/web/tsconfig.json
index d12f85e..de5b7f9 100644
--- a/web/tsconfig.json
+++ b/web/tsconfig.json
@@ -1,7 +1,7 @@
 {
   "extends": "../../tsconfig-plugins-base.json",
   "compilerOptions": {
-    "outDir": "../../../.ts-out/plugins/delete-project", /* overridden by bazel */
+    "outDir": "../../../.ts-out/plugins/delete-project" /* overridden by bazel */
   },
   "include": [
     "**/*.ts"
diff --git a/web/web_test_runner.sh b/web/web_test_runner.sh
new file mode 100755
index 0000000..60c35ba
--- /dev/null
+++ b/web/web_test_runner.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+set -euo pipefail
+./$1 --config $2 \
+  --dir 'plugins/delete-project/web/_bazel_ts_out_tests' \
+  --test-files 'plugins/delete-project/web/_bazel_ts_out_tests/*_test.js' \
+  --type-config="plugins/delete-project/web/tsconfig.json"