Add karma-runner and convert some tests to run with karma

The following changes are included in this change:
* karma-runner is added to the polygerrit-ui/package.json file
* bazel rule for karma tests is added to the polygerrit-ui/BUILD file
* The run_test.sh script is updated - it runs both deprecated
  web-component-tester(WCT) tests and karma tests
* Commands to run separately karma and wct tests are added to the top
  level package.json file
* The common-test-setup-karma.js file adds global functions to replace
  functionality provided by the WCT
* The postinstall step is added to the polygerrit-ui/package.json file
  to run 'selenium-standalone install' command.
  Note, that this is not a new command - it runs during the WCT
  install (see wct-local/scripts/postinstall.js), but sometimes it
  fails after switching between different branches. Calling it in the
  postinstall step of polygerrit-ui/package.json improves the
  situation.

Change-Id: Iaf480d22c5553d98eb7607a0e83a86b66f733caa
This commit is contained in:
Dmitrii Filippov
2020-04-02 10:31:43 +02:00
parent 6bf35b2ab6
commit acd39a2d9d
18 changed files with 2510 additions and 252 deletions

View File

@@ -26,7 +26,10 @@
"eslint": "npm run safe_bazelisk test polygerrit-ui/app:lint_test",
"eslintfix": "npm run safe_bazelisk run polygerrit-ui/app:lint_bin -- -- --fix $(pwd)/polygerrit-ui/app",
"test-template": "./polygerrit-ui/app/run_template_test.sh",
"polylint": "npm run safe_bazelisk test polygerrit-ui/app:polylint_test"
"polylint": "npm run safe_bazelisk test polygerrit-ui/app:polylint_test",
"test:karma:debug": "npm run safe_bazelisk run //polygerrit-ui:karma_bin -- -- start $(pwd)/polygerrit-ui/karma.conf.js --browsers ChromeDev --no-single-run --testFiles",
"test:karma": "npm run safe_bazelisk run //polygerrit-ui:karma_bin -- -- start $(pwd)/polygerrit-ui/karma.conf.js --testFiles",
"test:wct": "npm run test -- --test_tag_filters=wct"
},
"repository": {
"type": "git",

View File

@@ -1,5 +1,6 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary")
load("//tools/bzl:genrule2.bzl", "genrule2")
load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary")
package(default_visibility = ["//visibility:public"])
@@ -32,3 +33,43 @@ go_binary(
"@org_golang_x_tools//godoc/vfs/zipfs:go_default_library",
],
)
# Define a karma+plugins binary to run karma-mocha tests.
# Can be reused multiple time, if there are multiple karma test rules
sh_binary(
name = "karma_bin",
srcs = ["@ui_dev_npm//:node_modules/karma/bin/karma"],
data = [
"@ui_dev_npm//@open-wc/karma-esm",
"@ui_dev_npm//chai",
"@ui_dev_npm//karma-chrome-launcher",
"@ui_dev_npm//karma-mocha",
"@ui_dev_npm//karma-mocha-reporter",
"@ui_dev_npm//karma/bin:karma",
"@ui_dev_npm//mocha",
],
)
# Run all tests in one.
# TODO(dmfilippov): allow parallel tests for karma - either on the bazel level
# or on the karma level. For now single sh_test is enough.
sh_test(
name = "karma_test",
size = "enormous",
srcs = ["karma_test.sh"],
args = [
"$(location :karma_bin)",
"$(location karma.conf.js)",
],
data = [
"karma.conf.js",
":karma_bin",
"//polygerrit-ui/app:test-srcs-fg",
],
# Should not run sandboxed.
tags = [
"karma",
"local",
"manual",
],
)

View File

@@ -148,10 +148,13 @@ $(bazel info output_base)/external/local_jdk/bin/java \
## Running Tests
For daily development you typically only want to run and debug individual tests.
Run the local [Go proxy server](#go-server) and navigate for example to
<http://localhost:8081/elements/shared/gr-account-entry/gr-account-entry_test.html>.
Check "Disable cache" in the "Network" tab of Chrome's dev tools, so code
changes are picked up on "reload".
There are 2 types of fronted tests in gerrit:
- Karma tests - all tests matches `*_test.js` pattern
- web-component-tester(WCT) tests - all tests matches the `*_test.html` pattern.
**Note:** WCT tests are deprecated. We are migrating to Karma tests now. If you are going to change
something in a WCT test file, we strongly recommend to convert it to Karma tests before making
any change. See [Converting WCT tests to Karma](#wct-to-karma).
Our CI integration ensures that all tests are run when you upload a change to
Gerrit, but you can also run all tests locally in headless mode:
@@ -160,6 +163,44 @@ Gerrit, but you can also run all tests locally in headless mode:
npm test
```
### Running Karma tests
There are several ways to run Karma tests:
* Run all Karma tests in headless mode:
```sh
npm run test:karma
```
* Run all Karma tests in debug mode (the command opens Chrome browser with
the default Karma page; you should click the "Debug" button to start testing):
```sh
npm test:karma:debug
```
* Run a single test file:
```
# Headless mode
npm run test:karma async-foreach-behavior_test.js
# Debug mode
npm run test:karma:debug async-foreach-behavior_test.js
```
* You can run tests in IDE:
- [IntelliJ: running unit tests on Karma](https://www.jetbrains.com/help/idea/running-unit-tests-on-karma.html#ws_karma_running)
### Running WCT tests
Run the local [Go proxy server](#go-server) and navigate for example to
<http://localhost:8081/elements/shared/gr-account-entry/gr-account-entry_test.html>.
Check "Disable cache" in the "Network" tab of Chrome's dev tools, so code
changes are picked up on "reload".
You can also run all WCT tests locally in headless mode:
```sh
npm test:wct
```
To allow the tests to run in Safari:
* In the Advanced preferences tab, check "Show Develop menu in menu bar".
@@ -171,6 +212,96 @@ To run Chrome tests in headless mode:
WCT_HEADLESS_MODE=1 WCT_ARGS='--verbose -l chrome' ./polygerrit-ui/app/run_test.sh
```
### <a name="wct-to-karma"></a>Converting WCT tests to Karma
If you are want to change a WCT test file (any `..._test.html` file), please convert the file to a
Karma test file before making any changes. It is better to make a conversion in a separate change,
so any conversion-related problems can be catch at this step.
Usually, our WCT tests files have the following structure:
```Html
<!-- Test header: meta, title, wct scripts -->
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<meta charset="utf-8">
<title>gr-account-link</title>
<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
<script src="/components/wct-browser-legacy/browser.js"></script>
<!-- Templates for test fixtures (optional) -->
<test-fixture id="basic">
<template>
<gr-account-link></gr-account-link>
</template>
</test-fixture>
<test-fixture id="other">
<template>
<gr-dialog>
<span>Hello!</span>
</gr-dialog>
</template>
</test-fixture>
<!-- Tests -->
<script type="module">
// One or more imports:
import '../../../test/common-test-setup.js';
import ...;
// Tests - one or more suites
suite(..., () => {
...
// instantiate 'basic' template:
element = fixture('basic');
...
// instantiate 'other' template:
otherElements = fixture('other');
);
</script>
```
A conversion requires the following changes:
* Rename the `..._test.html` file to the `..._test.js` file.
* Remove test header (see a WCT test example above)
* Remove all `<script...>` and `</script>` tags, but preserve javascript code
* Change imports - use `test/common-test-setup-karma.js` instead of `test/common-test-setup.js`.
Ensure, that the `common-test-setup-karma.js` import is placed above any other imports.
* If there are test fixtures in the html file, move them inside a `<script>` tag and use
the `fixtureFromTemplate` or `fixtureFromElement` (if there is only one element in a template)
to define a test fixture template.
* Use `instantiate` method instead of `fixture` method.
After conversion, the Karma test file for the example above can look like:
```Javascript
import '../../../test/common-test-setup-karma.js';
// Other imports:
import ...
// Define test fixtures templates:
const fixture =
fixtureFromElement('gr-account-link');
const otherFixture = fixtureFromTemplate(html`<gr-dialog>
<span>Hello!</span>
</gr-dialog>
`);
// Tests - one or more suites
suite(..., () => {
...
// instantiate 'basic' template:
element = fixture.instantiate();
...
// instantiate 'other' template:
otherElements = otherFixture.instantiate();
);
```
## Style guide
We follow the [Google JavaScript Style Guide](https://google.github.io/styleguide/javascriptguide.xml)
@@ -299,4 +430,4 @@ npm run clean
// install all dependencies and start the server
npm start
```
```

View File

@@ -180,7 +180,7 @@ module.exports = {
},
},
{
"files": ["*.html", "common-test-setup.js"],
"files": ["*.html", "common-test-setup.js", "common-test-setup-karma.js", "*_test.js"],
// Additional global variables allowed in tests
"globals": {
// Global variables from 3rd party test libraries/frameworks.
@@ -201,6 +201,8 @@ module.exports = {
"suiteSetup": "readonly",
"teardown": "readonly",
"test": "readonly",
"fixtureFromElement": "readonly",
"fixtureFromTemplate": "readonly",
}
},
{

View File

@@ -58,6 +58,7 @@ filegroup(
name = "test-srcs-fg",
srcs = [
"test/common-test-setup.js",
"test/common-test-setup-karma.js",
"test/index.html",
":pg_code",
"@ui_dev_npm//:node_modules",

View File

@@ -1,31 +1,21 @@
<!DOCTYPE html>
<!--
@license
Copyright (C) 2017 The Android Open Source Project
/**
* @license
* Copyright (C) 2017 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.
*/
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.
-->
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<meta charset="utf-8">
<title>async-foreach-behavior</title>
<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
<script src="/components/wct-browser-legacy/browser.js"></script>
<script type="module">
import '../../test/common-test-setup.js';
import '../../test/common-test-setup-karma.js';
import {AsyncForeachBehavior} from './async-foreach-behavior.js';
suite('async-foreach-behavior tests', () => {
test('loops over each item', () => {
@@ -53,4 +43,3 @@ suite('async-foreach-behavior tests', () => {
});
});
});
</script>

View File

@@ -1,47 +1,32 @@
<!DOCTYPE html>
<!--
@license
Copyright (C) 2017 The Android Open Source Project
/**
* @license
* Copyright (C) 2017 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.
*/
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.
-->
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<meta charset="utf-8">
<title>gr-access-section</title>
<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
<script src="/node_modules/page/page.js"></script>
<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
<script src="/components/wct-browser-legacy/browser.js"></script>
<test-fixture id="basic">
<template>
<gr-access-section></gr-access-section>
</template>
</test-fixture>
<script type="module">
import '../../../test/common-test-setup.js';
import '../../../test/common-test-setup-karma.js';
import './gr-access-section.js';
const fixture = fixtureFromElement('gr-access-section');
suite('gr-access-section tests', () => {
let element;
let sandbox;
setup(() => {
sandbox = sinon.sandbox.create();
element = fixture('basic');
element = fixture.instantiate();
});
teardown(() => {
@@ -553,4 +538,3 @@ suite('gr-access-section tests', () => {
});
});
});
</script>

View File

@@ -1,45 +1,21 @@
<!DOCTYPE html>
<!--
@license
Copyright (C) 2015 The Android Open Source Project
/**
* @license
* Copyright (C) 2015 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.
*/
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.
-->
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<meta charset="utf-8">
<title>gr-change-view</title>
<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
<script src="/components/wct-browser-legacy/browser.js"></script>
<script src="/node_modules/page/page.js"></script>
<test-fixture id="basic">
<template>
<gr-change-view></gr-change-view>
</template>
</test-fixture>
<test-fixture id="blank">
<template>
<div></div>
</template>
</test-fixture>
<script type="module">
import '../../../test/common-test-setup.js';
import '../../../test/common-test-setup-karma.js';
import '../../edit/gr-edit-constants.js';
import './gr-change-view.js';
import {PrimaryTab, SecondaryTab, ChangeStatus} from '../../../constants/constants.js';
@@ -53,7 +29,10 @@ import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
import {pluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit.js';
import 'lodash/lodash.js';
const pluginApi = _testOnly_initGerritPluginApi();
const fixture = fixtureFromElement('gr-change-view');
suite('gr-change-view tests', () => {
const kb = KeyboardShortcutBinder;
@@ -314,7 +293,7 @@ suite('gr-change-view tests', () => {
getDiffDrafts() { return Promise.resolve({}); },
_fetchSharedCacheURL() { return Promise.resolve({}); },
});
element = fixture('basic');
element = fixture.instantiate();
sandbox.stub(element.$.actions, 'reload').returns(Promise.resolve());
pluginLoader.loadPlugins([]);
pluginApi.install(
@@ -2401,4 +2380,3 @@ suite('gr-change-view tests', () => {
});
});
});
</script>

View File

@@ -1,32 +1,25 @@
<!DOCTYPE html>
<!--
@license
Copyright (C) 2016 The Android Open Source Project
/**
* @license
* Copyright (C) 2016 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.
*/
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
import '../../../test/common-test-setup-karma.js';
import './gr-cursor-manager.js';
import {html} from '@polymer/polymer/lib/utils/html-tag.js';
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.
-->
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<meta charset="utf-8">
<title>gr-cursor-manager</title>
<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
<script src="/components/wct-browser-legacy/browser.js"></script>
<test-fixture id="basic">
<template>
const basicTestFixutre = fixtureFromTemplate(html`
<gr-cursor-manager cursor-target-class="targeted"></gr-cursor-manager>
<ul>
<li>A</li>
@@ -34,12 +27,8 @@ limitations under the License.
<li>C</li>
<li>D</li>
</ul>
</template>
</test-fixture>
`);
<script type="module">
import '../../../test/common-test-setup.js';
import './gr-cursor-manager.js';
suite('gr-cursor-manager tests', () => {
let sandbox;
let element;
@@ -47,7 +36,7 @@ suite('gr-cursor-manager tests', () => {
setup(() => {
sandbox = sinon.sandbox.create();
const fixtureElements = fixture('basic');
const fixtureElements = basicTestFixutre.instantiate();
element = fixtureElements[0];
list = fixtureElements[1];
});
@@ -300,4 +289,3 @@ suite('gr-cursor-manager tests', () => {
});
});
});
</script>

View File

@@ -124,6 +124,7 @@ def _wct_test(name, srcs, split_index, split_count):
tags = [
"local",
"manual",
"wct",
],
)

View File

@@ -14,4 +14,5 @@ ${bazel_bin} test \
--test_env="DISPLAY=${DISPLAY}" \
--test_env="WCT_HEADLESS_MODE=${WCT_HEADLESS_MODE}" \
"$@" \
//polygerrit-ui/app:wct_test
//polygerrit-ui/app:wct_test \
//polygerrit-ui:karma_test

View File

@@ -0,0 +1,145 @@
/**
* @license
* Copyright (C) 2020 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 './common-test-setup.js';
import '@polymer/test-fixture/test-fixture.js';
import 'chai/chai.js';
self.assert = window.chai.assert;
/**
* Triggers a flush of any pending events, observations, etc and calls you back
* after they have been processed.
*
* @param {function()} callback
*/
function flush(callback) {
// Ideally, this function would be a call to Polymer.dom.flush, but that
// doesn't support a callback yet
// (https://github.com/Polymer/polymer-dev/issues/851)
window.Polymer.dom.flush();
window.setTimeout(callback, 0);
}
self.flush = flush;
class TestFixtureIdProvider {
static get instance() {
if (!TestFixtureIdProvider._instance) {
TestFixtureIdProvider._instance = new TestFixtureIdProvider();
}
return TestFixtureIdProvider._instance;
}
constructor() {
this.fixturesCount = 1;
}
generateNewFixtureId() {
this.fixturesCount++;
return `fixture-${this.fixturesCount}`;
}
}
class TestFixture {
constructor(fixtureId) {
this.fixtureId = fixtureId;
}
/**
* Create an instance of a fixture's template.
*
* @param {Object} model - see Data-bound sections at
* https://www.webcomponents.org/element/@polymer/test-fixture
* @return {HTMLElement | HTMLElement[]} - if the fixture's template contains
* a single element, returns the appropriated instantiated element.
* Otherwise, it return an array of all instantiated elements from the
* template.
*/
instantiate(model) {
// The window.fixture method is defined in common-test-setup.js
return window.fixture(this.fixtureId, model);
}
}
/**
* Wraps provided template to a test-fixture tag and adds test-fixture to
* the document. You can use the html function to create a template.
*
* Example:
* import {html} from '@polymer/polymer/lib/utils/html-tag.js';
*
* // Create fixture at the root level of a test file
* const basicTestFixture = fixtureFromTemplate(html`
* <gr-cursor-manager cursor-target-class="targeted"></gr-cursor-manager>
* <ul>
* <li>A</li>
* <li>B</li>
* <li>C</li>
* <li>D</li>
* </ul>
* `);
* ...
* // Instantiate fixture when needed:
*
* suite('example') {
* let elements;
* setup(() => {
* elements = basicTestFixture.instantiate();
* });
* }
*
* @param {HTMLTemplateElement} template - a template for a fixture
* @return {TestFixture} - the instance of TestFixture class
*/
function fixtureFromTemplate(template) {
const fixtureId = TestFixtureIdProvider.instance.generateNewFixtureId();
const testFixture = document.createElement('test-fixture');
testFixture.setAttribute('id', fixtureId);
testFixture.appendChild(template);
document.body.appendChild(testFixture);
return new TestFixture(fixtureId);
}
/**
* Wraps provided tag to a test-fixture/template tags and adds test-fixture
* to the document.
*
* Example:
*
* // Create fixture at the root level of a test file
* const basicTestFixture = fixtureFromElement('gr-diff-view');
* ...
* // Instantiate fixture when needed:
*
* suite('example') {
* let element;
* setup(() => {
* element = basicTestFixture.instantiate();
* });
* }
*
* @param {HTMLTemplateElement} template - a template for a fixture
* @return {TestFixture} - the instance of TestFixture class
*/
function fixtureFromElement(tagName) {
const template = document.createElement('template');
template.innerHTML = `<${tagName}></${tagName}>`;
return fixtureFromTemplate(template);
}
window.fixtureFromTemplate = fixtureFromTemplate;
window.fixtureFromElement = fixtureFromElement;

View File

@@ -27,6 +27,12 @@ import {appContext} from '../services/app-context.js';
import {initAppContext} from '../services/app-context-init.js';
import {_testOnly_resetPluginLoader} from '../elements/shared/gr-js-api-interface/gr-plugin-loader.js';
import {grReportingMock} from '../services/gr-reporting/gr-reporting_mock.js';
// Returns true if tests run under the Karma
function isKarmaTest() {
return window.__karma__ !== undefined;
}
security.polymer_resin.install({
allowedIdentifierPrefixes: [''],
reportHandler(isViolation, fmt, ...args) {
@@ -61,13 +67,19 @@ security.polymer_resin.install({
// Note, that fixture(...) and stub(..) methods are registered different by
// WCT. This is why these methods implemented slightly different here.
const cleanups = [];
if (!window.fixture) {
if (isKarmaTest() || !window.fixture) {
// For karma always set our implementation
// (karma doesn't provide the fixture method)
window.fixture = function(fixtureId, model) {
// This method is inspired by WCT method
cleanups.push(() => document.getElementById(fixtureId).restore());
return document.getElementById(fixtureId).create(model);
};
} else {
// The following error is important for WCT tests.
// If window.fixture already installed by WCT at this point, WCT tests
// performance decreases rapidly.
// It allows to catch performance problems earlier.
throw new Error('window.fixture must be set before wct sets it');
}
@@ -91,7 +103,9 @@ setup(() => {
setMock('reportingService', grReportingMock);
});
if (window.stub) {
if (isKarmaTest() || window.stub) {
// For karma always set our implementation
// (karma doesn't provide the stub method)
window.stub = function(tagName, implementation) {
// This method is inspired by WCT method
const proto = document.createElement(tagName).constructor.prototype;
@@ -104,6 +118,10 @@ if (window.stub) {
});
};
} else {
// The following error is important for WCT tests.
// If window.fixture already installed by WCT at this point, WCT tests
// performance decreases rapidly.
// It allows to catch performance problems earlier.
throw new Error('window.stub must be set after wct sets it');
}

View File

@@ -27,7 +27,6 @@ const elements = [
// This seemed to be flakey when it was farther down the list. Keep at the
// beginning.
'gr-app_test.html',
'admin/gr-access-section/gr-access-section_test.html',
'admin/gr-admin-group-list/gr-admin-group-list_test.html',
'admin/gr-admin-view/gr-admin-view_test.html',
'admin/gr-confirm-delete-item-dialog/gr-confirm-delete-item-dialog_test.html',
@@ -62,7 +61,6 @@ const elements = [
'change/gr-change-metadata/gr-change-metadata-it_test.html',
'change/gr-change-metadata/gr-change-metadata_test.html',
'change/gr-change-requirements/gr-change-requirements_test.html',
'change/gr-change-view/gr-change-view_test.html',
'change/gr-comment-list/gr-comment-list_test.html',
'change/gr-commit-info/gr-commit-info_test.html',
'change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog_test.html',
@@ -165,7 +163,6 @@ const elements = [
'shared/gr-comment/gr-comment_test.html',
'shared/gr-copy-clipboard/gr-copy-clipboard_test.html',
'shared/gr-count-string-formatter/gr-count-string-formatter_test.html',
'shared/gr-cursor-manager/gr-cursor-manager_test.html',
'shared/gr-date-formatter/gr-date-formatter_test.html',
'shared/gr-dialog/gr-dialog_test.html',
'shared/gr-diff-preferences/gr-diff-preferences_test.html',
@@ -221,7 +218,6 @@ for (let file of elements) {
// Behaviors tests.
/* eslint-disable max-len */
const behaviors = [
'async-foreach-behavior/async-foreach-behavior_test.html',
'base-url-behavior/base-url-behavior_test.html',
'docs-url-behavior/docs-url-behavior_test.html',
'dom-util-behavior/dom-util-behavior_test.html',

150
polygerrit-ui/karma.conf.js Normal file
View File

@@ -0,0 +1,150 @@
/**
* @license
* Copyright (C) 2020 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.
*/
const runUnderBazel = !!process.env["RUNFILES_DIR"];
const path = require('path');
function getModulesDir() {
if(runUnderBazel) {
// Run under bazel
return [
`external/ui_npm/node_modules`,
`external/ui_dev_npm/node_modules`
];
}
// Run from intellij or npm run test:kdebug
return [
path.join(__dirname, 'app/node_modules'),
path.join(__dirname, 'node_modules'),
];
}
function getSinonPath() {
if(runUnderBazel) {
return "external/ui_dev_npm/node_modules/sinon/pkg/sinon.js";
}
else {
return "polygerrit-ui/node_modules/sinon/pkg/sinon.js"
}
}
module.exports = function(config) {
const testFilesLocationPattern =
'polygerrit-ui/app/**/!(template_test_srcs)/';
// Use --test-files to specify pattern for a test files.
// It can be just a file name, without a path:
// --test-files async-foreach-behavior_test.js
// If you specify --test-files without pattern, it gets true value
// In this case we ill run all tests (usefull for package.json "debugtest"
// script)
const testFilesPattern = (typeof config.testFiles == 'string') ?
testFilesLocationPattern + config.testFiles :
testFilesLocationPattern + '*_test.js';
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '../',
plugins: [
// Do not use karma-* to load all installed plugin
// This can lead to unexpected behavior under bazel
// if you forget to add a plugin in a bazel rule.
require.resolve('@open-wc/karma-esm'),
'karma-mocha',
'karma-chrome-launcher',
'karma-mocha-reporter',
],
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['mocha', 'esm'],
// list of files / patterns to load in the browser
files: [
getSinonPath(),
{ pattern: testFilesPattern, type: 'module' },
],
esm: {
nodeResolve: true,
moduleDirs: getModulesDir(),
// Bazel and yarn uses symlinks for files.
// preserveSymlinks is necessary for correct modules paths resolving
preserveSymlinks: true,
// By default, esm-dev-server uses 'auto' compatibility mode.
// In the 'auto' mode it incorrectly applies polyfills and
// breaks tests in some browser versions
// (for example, Chrome 69 on gerrit-ci).
compatibility: 'none',
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['mocha'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ["CustomChromeHeadless"],
browserForDebugging: "CustomChromeHeadlessWithDebugPort",
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: true,
// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity,
client: {
mocha: {
ui: 'tdd'
}
},
customLaunchers: {
// Based on https://developers.google.com/web/updates/2017/06/headless-karma-mocha-chai
"CustomChromeHeadless": {
base: 'ChromeHeadless',
flags: ['--disable-translate', '--disable-extensions'],
},
"ChromeDev": {
base: 'Chrome',
flags: ['--disable-extensions', ' --auto-open-devtools-for-tabs'],
},
"CustomChromeHeadlessWithDebugPort": {
base: 'CustomChromeHeadless',
flags: ['--remote-debugging-port=9222'],
}
}
});
};

4
polygerrit-ui/karma_test.sh Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/bash
set -euo pipefail
./$1 start $2 --single-run

View File

@@ -4,12 +4,22 @@
"browser": true,
"dependencies": {},
"devDependencies": {
"@open-wc/karma-esm": "^2.13.21",
"@polymer/iron-test-helpers": "^3.0.1",
"@polymer/test-fixture": "^4.0.2",
"chai": "^4.2.0",
"mocha": "^6.2.2",
"karma": "^4.4.1",
"karma-chrome-launcher": "^3.1.0",
"karma-mocha": "^2.0.1",
"karma-mocha-reporter": "^2.2.5",
"lodash": "^4.17.15",
"mocha": "^7.1.1",
"wct-browser-legacy": "^1.0.2",
"web-component-tester": "^6.9.2"
},
"scripts": {
"postinstall": "selenium-standalone install"
},
"license": "Apache-2.0",
"private": true
}

File diff suppressed because it is too large Load Diff