Apply new web plugin code layout to delete-project And add basic karma testing capabilities. Change-Id: Ib9742c79da68cc9426afd3d2947b9f6ce8be9631
diff --git a/BUILD b/BUILD index 47d5db0..0dc7769 100644 --- a/BUILD +++ b/BUILD
@@ -1,14 +1,11 @@ load("@rules_java//java:defs.bzl", "java_library") load("//tools/bzl:junit.bzl", "junit_tests") -load("//tools/js:eslint.bzl", "eslint") load( "//tools/bzl:plugin.bzl", "PLUGIN_DEPS", "PLUGIN_TEST_DEPS", "gerrit_plugin", ) -load("//tools/bzl:js.bzl", "gerrit_js_bundle") -load("@npm//@bazel/typescript:index.bzl", "ts_config", "ts_project") gerrit_plugin( name = "delete-project", @@ -19,39 +16,11 @@ "Gerrit-HttpModule: com.googlesource.gerrit.plugins.deleteproject.HttpModule", "Gerrit-SshModule: com.googlesource.gerrit.plugins.deleteproject.SshModule", ], - resource_jars = [":gr-delete-repo"], + resource_jars = ["//plugins/delete-project/web:gr-delete-repo"], resources = glob(["src/main/resources/Documentation/*.md"]), deps = ["@commons-io//jar"], ) -ts_config( - name = "tsconfig", - src = "tsconfig.json", - deps = [ - "//plugins:tsconfig-plugins-base.json", - ], -) - -ts_project( - name = "gr-delete-repo-ts", - srcs = glob([ - "gr-delete-repo/**/*.ts", - ]), - incremental = True, - tsc = "//tools/node_tools:tsc-bin", - tsconfig = ":tsconfig", - deps = [ - "@plugins_npm//@gerritcodereview/typescript-api", - "@plugins_npm//lit", - ], -) - -gerrit_js_bundle( - name = "gr-delete-repo", - srcs = [":gr-delete-repo-ts"], - entry_point = "gr-delete-repo/plugin.js", -) - junit_tests( name = "delete-project_tests", srcs = glob(["src/test/java/**/*.java"]), @@ -71,28 +40,3 @@ "@mockito//jar", ], ) - -# The eslint macro creates 2 rules: lint_test and lint_bin. Typical usage: -# bazel test $DIR:lint_test -# bazel run $DIR:lint_bin -- --fix $PATH_TO_SRCS -eslint( - name = "lint", - srcs = glob(["gr-delete-repo/**/*"]), - config = ".eslintrc.js", - data = [ - "tsconfig.json", - "//plugins:.eslintrc.js", - "//plugins:.prettierrc.js", - "//plugins:tsconfig-plugins-base.json", - ], - extensions = [".ts"], - ignore = "//plugins:.eslintignore", - plugins = [ - "@npm//eslint-config-google", - "@npm//eslint-plugin-html", - "@npm//eslint-plugin-import", - "@npm//eslint-plugin-jsdoc", - "@npm//eslint-plugin-prettier", - "@npm//gts", - ], -)
diff --git a/README.md b/README.md index 1444d1a..5a87b38 100644 --- a/README.md +++ b/README.md
@@ -5,3 +5,24 @@ [](https://gerrit-ci.gerritforge.com/view/Plugins-master/job/plugin-delete-project-bazel-master/) + +## JavaScript Plugin Development + +For running unit tests execute: + + bazel test --test_output=all //plugins/delete-project/web:karma_test + +For checking or fixing eslint formatter problems run: + + bazel test //plugins/delete-project/web:lint_test + bazel run //plugins/delete-project/web:lint_bin -- --fix "$(pwd)/plugins/delete-project/web" + +For testing the plugin with +[Gerrit FE Dev Helper](https://gerrit.googlesource.com/gerrit-fe-dev-helper/) +build the JavaScript bundle and copy it to the `plugins/` folder: + + bazel build //plugins/delete-project/web:gr-delete-repo + cp -f bazel-bin/plugins/delete-project/web/gr-delete-repo.js plugins/ + +and let the Dev Helper redirect from `.+/plugins/delete-project/static/gr-delete-repo.js` to +`http://localhost:8081/plugins_/gr-delete-repo.js`.
diff --git a/package.json b/package.json deleted file mode 100644 index 5a46795..0000000 --- a/package.json +++ /dev/null
@@ -1,13 +0,0 @@ -{ - "name": "delete-project", - "description": "Delete project plugin", - "browser": true, - "scripts": { - "safe_bazelisk": "if which bazelisk >/dev/null; then bazel_bin=bazelisk; else bazel_bin=bazel; fi && $bazel_bin", - "eslint": "npm run safe_bazelisk test :lint_test", - "eslintfix": "npm run safe_bazelisk run :lint_bin -- -- --fix $(pwd)" - }, - "devDependencies": {}, - "license": "Apache-2.0", - "private": true -}
diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index 9be4292..0000000 --- a/tsconfig.json +++ /dev/null
@@ -1,6 +0,0 @@ -{ - "extends": "../tsconfig-plugins-base.json", - "include": [ - "gr-delete-repo/**/*", - ] -}
diff --git a/.eslintrc.js b/web/.eslintrc.js similarity index 89% rename from .eslintrc.js rename to web/.eslintrc.js index 30df322..ee166d3 100644 --- a/.eslintrc.js +++ b/web/.eslintrc.js
@@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -__plugindir = 'delete-project'; +__plugindir = 'delete-project/web'; module.exports = { - extends: '../.eslintrc.js', + extends: '../../.eslintrc.js', };
diff --git a/web/BUILD b/web/BUILD new file mode 100644 index 0000000..5490c23 --- /dev/null +++ b/web/BUILD
@@ -0,0 +1,61 @@ +load("//tools/js:eslint.bzl", "plugin_eslint") +load("//tools/bzl:js.bzl", "gerrit_js_bundle", "karma_test") +load("@npm//@bazel/typescript:index.bzl", "ts_config", "ts_project") + +package_group( + name = "visibility", + packages = ["//plugins/delete-project/..."], +) + +package(default_visibility = [":visibility"]) + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + deps = [ + "//plugins:tsconfig-plugins-base.json", + ], +) + +ts_project( + name = "delete-project-ts", + srcs = glob( + ["**/*.ts"], + exclude = ["**/*test*"], + ), + incremental = True, + out_dir = "_bazel_ts_out", + tsc = "//tools/node_tools:tsc-bin", + tsconfig = ":tsconfig", + deps = [ + "@plugins_npm//@gerritcodereview/typescript-api", + "@plugins_npm//lit", + ], +) + +ts_project( + name = "delete-project-ts-tests", + srcs = glob(["**/*.ts"]), + incremental = True, + out_dir = "_bazel_ts_out_tests", + tsc = "//tools/node_tools:tsc-bin", + tsconfig = ":tsconfig", + deps = [ + "@plugins_npm//:node_modules", + "@ui_dev_npm//:node_modules", + ], +) + +gerrit_js_bundle( + name = "gr-delete-repo", + srcs = [":delete-project-ts"], + entry_point = "_bazel_ts_out/plugin.js", +) + +karma_test( + name = "karma_test", + srcs = ["karma_test.sh"], + data = [":delete-project-ts-tests"], +) + +plugin_eslint()
diff --git a/gr-delete-repo/gr-delete-repo.ts b/web/gr-delete-repo.ts similarity index 98% rename from gr-delete-repo/gr-delete-repo.ts rename to web/gr-delete-repo.ts index e16cefb..dec8efe 100644 --- a/gr-delete-repo/gr-delete-repo.ts +++ b/web/gr-delete-repo.ts
@@ -36,7 +36,7 @@ } @customElement('gr-delete-repo') -class GrDeleteRepo extends LitElement { +export class GrDeleteRepo extends LitElement { @query('#deleteRepoOverlay') deleteRepoOverlay?: GrOverlay;
diff --git a/web/gr-delete-repo_test.ts b/web/gr-delete-repo_test.ts new file mode 100644 index 0000000..2da6b2b --- /dev/null +++ b/web/gr-delete-repo_test.ts
@@ -0,0 +1,76 @@ +/** + * @license + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import './test/test-setup'; +import './gr-delete-repo'; +import {queryAndAssert} from './test/test-util'; +import {PluginApi} from '@gerritcodereview/typescript-api/plugin'; +import {GrDeleteRepo} from './gr-delete-repo'; +import { + ConfigInfo, + HttpMethod, + RepoName, +} from '@gerritcodereview/typescript-api/rest-api'; + +suite('gr-delete-repo tests', () => { + let element: GrDeleteRepo; + let sendStub: sinon.SinonStub; + + setup(async () => { + sendStub = sinon.stub(); + sendStub.returns(Promise.resolve({})); + + element = document.createElement('gr-delete-repo'); + element.repoName = 'test-repo-name' as RepoName; + element.config = { + actions: { + 'delete-project~delete': { + label: 'test-action-label', + title: 'test-aciton-title', + enabled: true, + method: HttpMethod.DELETE, + }, + }, + } as unknown as ConfigInfo; + element.plugin = { + getPluginName: () => 'delete-project', + restApi: () => { + return { + send: sendStub, + 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.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 new file mode 100755 index 0000000..35430ad --- /dev/null +++ b/web/karma_test.sh
@@ -0,0 +1,6 @@ +#!/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/gr-delete-repo/plugin.ts b/web/plugin.ts similarity index 100% rename from gr-delete-repo/plugin.ts rename to web/plugin.ts
diff --git a/web/test/test-setup.ts b/web/test/test-setup.ts new file mode 100644 index 0000000..ddeaf89 --- /dev/null +++ b/web/test/test-setup.ts
@@ -0,0 +1,43 @@ +/** + * @license + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import 'chai/chai'; +import '@gerritcodereview/typescript-api/gerrit'; +import {css} from 'lit'; + +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: { + form: css``, + menuPage: css``, + subPage: css``, + table: css``, + }, +};
diff --git a/web/test/test-util.ts b/web/test/test-util.ts new file mode 100644 index 0000000..25a1c79 --- /dev/null +++ b/web/test/test-util.ts
@@ -0,0 +1,42 @@ +/** + * @license + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export function queryAll<E extends Element = Element>( + el: Element, + selector: string +): NodeListOf<E> { + if (!el) throw new Error('element not defined'); + const root = el.shadowRoot ?? el; + return root.querySelectorAll<E>(selector); +} + +export function query<E extends Element = Element>( + el: Element | undefined, + selector: string +): E | undefined { + if (!el) return undefined; + const root = el.shadowRoot ?? el; + return root.querySelector<E>(selector) ?? undefined; +} + +export function queryAndAssert<E extends Element = Element>( + el: Element | undefined, + selector: string +): E { + const found = query<E>(el, selector); + if (!found) throw new Error(`selector '${selector}' did not match anything'`); + return found; +}
diff --git a/web/tsconfig.json b/web/tsconfig.json new file mode 100644 index 0000000..d12f85e --- /dev/null +++ b/web/tsconfig.json
@@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig-plugins-base.json", + "compilerOptions": { + "outDir": "../../../.ts-out/plugins/delete-project", /* overridden by bazel */ + }, + "include": [ + "**/*.ts" + ] +}