Convert polygerrit to es6-modules
This change replace all HTML imports with es6-modules. The only exceptions are: * gr-app.html file, which can be deleted only after updating the gerrit/httpd/raw/PolyGerritIndexHtml.soy file. * dark-theme.html which is loaded via importHref. Must be updated manually later in a separate change. This change was produced automatically by ./es6-modules-converter.sh script. No manual changes were made. Change-Id: I0c447dd8c05757741e2c940720652d01d9fb7d67
This commit is contained in:
@@ -1,21 +1,19 @@
|
||||
<!--
|
||||
@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.
|
||||
-->
|
||||
|
||||
<script>
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
(function(window) {
|
||||
'use strict';
|
||||
|
||||
@@ -63,4 +61,3 @@ limitations under the License.
|
||||
};
|
||||
}
|
||||
})(window);
|
||||
</script>
|
||||
|
||||
@@ -19,40 +19,42 @@ limitations under the License.
|
||||
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
|
||||
<title>async-foreach-behavior</title>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/bower_components/web-component-tester/browser.js"></script>
|
||||
<script src="../../test/test-pre-setup.js"></script>
|
||||
<link rel="import" href="../../test/common-test-setup.html"/>
|
||||
<link rel="import" href="async-foreach-behavior.html">
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/components/wct-browser-legacy/browser.js"></script>
|
||||
<script type="module" src="../../test/test-pre-setup.js"></script>
|
||||
<script type="module" src="../../test/common-test-setup.js"></script>
|
||||
<script type="module" src="./async-foreach-behavior.js"></script>
|
||||
|
||||
<script>
|
||||
suite('async-foreach-behavior tests', async () => {
|
||||
await readyToTest();
|
||||
test('loops over each item', () => {
|
||||
const fn = sinon.stub().returns(Promise.resolve());
|
||||
return Gerrit.AsyncForeachBehavior.asyncForeach([1, 2, 3], fn)
|
||||
.then(() => {
|
||||
assert.isTrue(fn.calledThrice);
|
||||
assert.equal(fn.getCall(0).args[0], 1);
|
||||
assert.equal(fn.getCall(1).args[0], 2);
|
||||
assert.equal(fn.getCall(2).args[0], 3);
|
||||
});
|
||||
});
|
||||
|
||||
test('halts on stop condition', () => {
|
||||
const stub = sinon.stub();
|
||||
const fn = (e, stop) => {
|
||||
stub(e);
|
||||
stop();
|
||||
return Promise.resolve();
|
||||
};
|
||||
return Gerrit.AsyncForeachBehavior.asyncForeach([1, 2, 3], fn)
|
||||
.then(() => {
|
||||
assert.isTrue(stub.calledOnce);
|
||||
assert.equal(stub.lastCall.args[0], 1);
|
||||
});
|
||||
});
|
||||
<script type="module">
|
||||
import '../../test/test-pre-setup.js';
|
||||
import '../../test/common-test-setup.js';
|
||||
import './async-foreach-behavior.js';
|
||||
suite('async-foreach-behavior tests', () => {
|
||||
test('loops over each item', () => {
|
||||
const fn = sinon.stub().returns(Promise.resolve());
|
||||
return Gerrit.AsyncForeachBehavior.asyncForeach([1, 2, 3], fn)
|
||||
.then(() => {
|
||||
assert.isTrue(fn.calledThrice);
|
||||
assert.equal(fn.getCall(0).args[0], 1);
|
||||
assert.equal(fn.getCall(1).args[0], 2);
|
||||
assert.equal(fn.getCall(2).args[0], 3);
|
||||
});
|
||||
});
|
||||
|
||||
test('halts on stop condition', () => {
|
||||
const stub = sinon.stub();
|
||||
const fn = (e, stop) => {
|
||||
stub(e);
|
||||
stop();
|
||||
return Promise.resolve();
|
||||
};
|
||||
return Gerrit.AsyncForeachBehavior.asyncForeach([1, 2, 3], fn)
|
||||
.then(() => {
|
||||
assert.isTrue(stub.calledOnce);
|
||||
assert.equal(stub.lastCall.args[0], 1);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
<!--
|
||||
@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.
|
||||
-->
|
||||
|
||||
<script>
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
(function(window) {
|
||||
'use strict';
|
||||
|
||||
@@ -46,4 +44,3 @@ limitations under the License.
|
||||
};
|
||||
}
|
||||
})(window);
|
||||
</script>
|
||||
|
||||
@@ -19,17 +19,20 @@ limitations under the License.
|
||||
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
|
||||
<title>base-url-behavior</title>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/bower_components/web-component-tester/browser.js"></script>
|
||||
<script src="../../test/test-pre-setup.js"></script>
|
||||
<link rel="import" href="../../test/common-test-setup.html"/>
|
||||
<script>
|
||||
/** @type {string} */
|
||||
window.CANONICAL_PATH = '/r';
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/components/wct-browser-legacy/browser.js"></script>
|
||||
<script type="module" src="../../test/test-pre-setup.js"></script>
|
||||
<script type="module" src="../../test/common-test-setup.js"></script>
|
||||
<script type="module">
|
||||
import '../../test/test-pre-setup.js';
|
||||
import '../../test/common-test-setup.js';
|
||||
import './base-url-behavior.js';
|
||||
/** @type {string} */
|
||||
window.CANONICAL_PATH = '/r';
|
||||
</script>
|
||||
<link rel="import" href="base-url-behavior.html">
|
||||
<script type="module" src="./base-url-behavior.js"></script>
|
||||
|
||||
<test-fixture id="basic">
|
||||
<template>
|
||||
@@ -45,30 +48,33 @@ limitations under the License.
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<script>
|
||||
suite('base-url-behavior tests', async () => {
|
||||
await readyToTest();
|
||||
let element;
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
let overlay;
|
||||
<script type="module">
|
||||
import '../../test/test-pre-setup.js';
|
||||
import '../../test/common-test-setup.js';
|
||||
import './base-url-behavior.js';
|
||||
import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
|
||||
suite('base-url-behavior tests', () => {
|
||||
let element;
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
let overlay;
|
||||
|
||||
suiteSetup(() => {
|
||||
// Define a Polymer element that uses this behavior.
|
||||
Polymer({
|
||||
is: 'test-element',
|
||||
behaviors: [
|
||||
Gerrit.BaseUrlBehavior,
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
element = fixture('basic');
|
||||
overlay = fixture('within-overlay');
|
||||
});
|
||||
|
||||
test('getBaseUrl', () => {
|
||||
assert.deepEqual(element.getBaseUrl(), '/r');
|
||||
suiteSetup(() => {
|
||||
// Define a Polymer element that uses this behavior.
|
||||
Polymer({
|
||||
is: 'test-element',
|
||||
behaviors: [
|
||||
Gerrit.BaseUrlBehavior,
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
element = fixture('basic');
|
||||
overlay = fixture('within-overlay');
|
||||
});
|
||||
|
||||
test('getBaseUrl', () => {
|
||||
assert.deepEqual(element.getBaseUrl(), '/r');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
<!--
|
||||
@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.
|
||||
*/
|
||||
import '../base-url-behavior/base-url-behavior.js';
|
||||
|
||||
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.
|
||||
-->
|
||||
<link rel="import" href="../base-url-behavior/base-url-behavior.html">
|
||||
<script>
|
||||
(function(window) {
|
||||
'use strict';
|
||||
|
||||
@@ -77,4 +77,3 @@ limitations under the License.
|
||||
};
|
||||
}
|
||||
})(window);
|
||||
</script>
|
||||
|
||||
@@ -15,17 +15,22 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<!-- Polymer included for the html import polyfill. -->
|
||||
<script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/bower_components/web-component-tester/browser.js"></script>
|
||||
<script src="../../test/test-pre-setup.js"></script>
|
||||
<link rel="import" href="../../test/common-test-setup.html"/>
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/components/wct-browser-legacy/browser.js"></script>
|
||||
<script type="module" src="../../test/test-pre-setup.js"></script>
|
||||
<script type="module" src="../../test/common-test-setup.js"></script>
|
||||
<title>docs-url-behavior</title>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
|
||||
<link rel="import" href="docs-url-behavior.html">
|
||||
<script type="module" src="./docs-url-behavior.js"></script>
|
||||
|
||||
<script>void(0);</script>
|
||||
<script type="module">
|
||||
import '../../test/test-pre-setup.js';
|
||||
import '../../test/common-test-setup.js';
|
||||
import './docs-url-behavior.js';
|
||||
void(0);
|
||||
</script>
|
||||
|
||||
<test-fixture id="basic">
|
||||
<template>
|
||||
@@ -33,71 +38,74 @@ limitations under the License.
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<script>
|
||||
suite('docs-url-behavior tests', async () => {
|
||||
await readyToTest();
|
||||
let element;
|
||||
<script type="module">
|
||||
import '../../test/test-pre-setup.js';
|
||||
import '../../test/common-test-setup.js';
|
||||
import './docs-url-behavior.js';
|
||||
import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
|
||||
suite('docs-url-behavior tests', () => {
|
||||
let element;
|
||||
|
||||
suiteSetup(() => {
|
||||
// Define a Polymer element that uses this behavior.
|
||||
Polymer({
|
||||
is: 'docs-url-behavior-element',
|
||||
behaviors: [Gerrit.DocsUrlBehavior],
|
||||
});
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
element = fixture('basic');
|
||||
element._clearDocsBaseUrlCache();
|
||||
});
|
||||
|
||||
test('null config', () => {
|
||||
const mockRestApi = {
|
||||
probePath: sinon.stub().returns(Promise.resolve(true)),
|
||||
};
|
||||
return element.getDocsBaseUrl(null, mockRestApi)
|
||||
.then(docsBaseUrl => {
|
||||
assert.isTrue(
|
||||
mockRestApi.probePath.calledWith('/Documentation/index.html'));
|
||||
assert.equal(docsBaseUrl, '/Documentation');
|
||||
});
|
||||
});
|
||||
|
||||
test('no doc config', () => {
|
||||
const mockRestApi = {
|
||||
probePath: sinon.stub().returns(Promise.resolve(true)),
|
||||
};
|
||||
const config = {gerrit: {}};
|
||||
return element.getDocsBaseUrl(config, mockRestApi)
|
||||
.then(docsBaseUrl => {
|
||||
assert.isTrue(
|
||||
mockRestApi.probePath.calledWith('/Documentation/index.html'));
|
||||
assert.equal(docsBaseUrl, '/Documentation');
|
||||
});
|
||||
});
|
||||
|
||||
test('has doc config', () => {
|
||||
const mockRestApi = {
|
||||
probePath: sinon.stub().returns(Promise.resolve(true)),
|
||||
};
|
||||
const config = {gerrit: {doc_url: 'foobar'}};
|
||||
return element.getDocsBaseUrl(config, mockRestApi)
|
||||
.then(docsBaseUrl => {
|
||||
assert.isFalse(mockRestApi.probePath.called);
|
||||
assert.equal(docsBaseUrl, 'foobar');
|
||||
});
|
||||
});
|
||||
|
||||
test('no probe', () => {
|
||||
const mockRestApi = {
|
||||
probePath: sinon.stub().returns(Promise.resolve(false)),
|
||||
};
|
||||
return element.getDocsBaseUrl(null, mockRestApi)
|
||||
.then(docsBaseUrl => {
|
||||
assert.isTrue(
|
||||
mockRestApi.probePath.calledWith('/Documentation/index.html'));
|
||||
assert.isNotOk(docsBaseUrl);
|
||||
});
|
||||
suiteSetup(() => {
|
||||
// Define a Polymer element that uses this behavior.
|
||||
Polymer({
|
||||
is: 'docs-url-behavior-element',
|
||||
behaviors: [Gerrit.DocsUrlBehavior],
|
||||
});
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
element = fixture('basic');
|
||||
element._clearDocsBaseUrlCache();
|
||||
});
|
||||
|
||||
test('null config', () => {
|
||||
const mockRestApi = {
|
||||
probePath: sinon.stub().returns(Promise.resolve(true)),
|
||||
};
|
||||
return element.getDocsBaseUrl(null, mockRestApi)
|
||||
.then(docsBaseUrl => {
|
||||
assert.isTrue(
|
||||
mockRestApi.probePath.calledWith('/Documentation/index.html'));
|
||||
assert.equal(docsBaseUrl, '/Documentation');
|
||||
});
|
||||
});
|
||||
|
||||
test('no doc config', () => {
|
||||
const mockRestApi = {
|
||||
probePath: sinon.stub().returns(Promise.resolve(true)),
|
||||
};
|
||||
const config = {gerrit: {}};
|
||||
return element.getDocsBaseUrl(config, mockRestApi)
|
||||
.then(docsBaseUrl => {
|
||||
assert.isTrue(
|
||||
mockRestApi.probePath.calledWith('/Documentation/index.html'));
|
||||
assert.equal(docsBaseUrl, '/Documentation');
|
||||
});
|
||||
});
|
||||
|
||||
test('has doc config', () => {
|
||||
const mockRestApi = {
|
||||
probePath: sinon.stub().returns(Promise.resolve(true)),
|
||||
};
|
||||
const config = {gerrit: {doc_url: 'foobar'}};
|
||||
return element.getDocsBaseUrl(config, mockRestApi)
|
||||
.then(docsBaseUrl => {
|
||||
assert.isFalse(mockRestApi.probePath.called);
|
||||
assert.equal(docsBaseUrl, 'foobar');
|
||||
});
|
||||
});
|
||||
|
||||
test('no probe', () => {
|
||||
const mockRestApi = {
|
||||
probePath: sinon.stub().returns(Promise.resolve(false)),
|
||||
};
|
||||
return element.getDocsBaseUrl(null, mockRestApi)
|
||||
.then(docsBaseUrl => {
|
||||
assert.isTrue(
|
||||
mockRestApi.probePath.calledWith('/Documentation/index.html'));
|
||||
assert.isNotOk(docsBaseUrl);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
<!--
|
||||
@license
|
||||
Copyright (C) 2018 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.
|
||||
-->
|
||||
<script>
|
||||
/**
|
||||
* @license
|
||||
* Copyright (C) 2018 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.
|
||||
*/
|
||||
(function(window) {
|
||||
'use strict';
|
||||
|
||||
@@ -61,4 +60,3 @@ limitations under the License.
|
||||
};
|
||||
}
|
||||
})(window);
|
||||
</script>
|
||||
|
||||
@@ -19,13 +19,13 @@ limitations under the License.
|
||||
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
|
||||
<title>dom-util-behavior</title>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/bower_components/web-component-tester/browser.js"></script>
|
||||
<script src="../../test/test-pre-setup.js"></script>
|
||||
<link rel="import" href="../../test/common-test-setup.html"/>
|
||||
<link rel="import" href="dom-util-behavior.html">
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/components/wct-browser-legacy/browser.js"></script>
|
||||
<script type="module" src="../../test/test-pre-setup.js"></script>
|
||||
<script type="module" src="../../test/common-test-setup.js"></script>
|
||||
<script type="module" src="./dom-util-behavior.js"></script>
|
||||
|
||||
<test-fixture id="nested-structure">
|
||||
<template>
|
||||
@@ -40,34 +40,37 @@ limitations under the License.
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<script>
|
||||
suite('dom-util-behavior tests', async () => {
|
||||
await readyToTest();
|
||||
let element;
|
||||
let divs;
|
||||
<script type="module">
|
||||
import '../../test/test-pre-setup.js';
|
||||
import '../../test/common-test-setup.js';
|
||||
import './dom-util-behavior.js';
|
||||
import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
|
||||
suite('dom-util-behavior tests', () => {
|
||||
let element;
|
||||
let divs;
|
||||
|
||||
suiteSetup(() => {
|
||||
// Define a Polymer element that uses this behavior.
|
||||
Polymer({
|
||||
is: 'test-element',
|
||||
behaviors: [Gerrit.DomUtilBehavior],
|
||||
});
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
const testDom = fixture('nested-structure');
|
||||
element = testDom[0];
|
||||
divs = testDom[1];
|
||||
});
|
||||
|
||||
test('descendedFromClass', () => {
|
||||
// .c is a child of .a and not vice versa.
|
||||
assert.isTrue(element.descendedFromClass(divs.querySelector('.c'), 'a'));
|
||||
assert.isFalse(element.descendedFromClass(divs.querySelector('.a'), 'c'));
|
||||
|
||||
// Stops at stop element.
|
||||
assert.isFalse(element.descendedFromClass(divs.querySelector('.c'), 'a',
|
||||
divs.querySelector('.b')));
|
||||
suiteSetup(() => {
|
||||
// Define a Polymer element that uses this behavior.
|
||||
Polymer({
|
||||
is: 'test-element',
|
||||
behaviors: [Gerrit.DomUtilBehavior],
|
||||
});
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
const testDom = fixture('nested-structure');
|
||||
element = testDom[0];
|
||||
divs = testDom[1];
|
||||
});
|
||||
|
||||
test('descendedFromClass', () => {
|
||||
// .c is a child of .a and not vice versa.
|
||||
assert.isTrue(element.descendedFromClass(divs.querySelector('.c'), 'a'));
|
||||
assert.isFalse(element.descendedFromClass(divs.querySelector('.a'), 'c'));
|
||||
|
||||
// Stops at stop element.
|
||||
assert.isFalse(element.descendedFromClass(divs.querySelector('.c'), 'a',
|
||||
divs.querySelector('.b')));
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
<!--
|
||||
@license
|
||||
Copyright (C) 2019 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.
|
||||
-->
|
||||
|
||||
<script>
|
||||
/**
|
||||
* @license
|
||||
* Copyright (C) 2019 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.
|
||||
*/
|
||||
(function(window) {
|
||||
'use strict';
|
||||
|
||||
@@ -69,4 +67,3 @@ limitations under the License.
|
||||
};
|
||||
}
|
||||
})(window);
|
||||
</script>
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
<!--
|
||||
@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.
|
||||
-->
|
||||
|
||||
<script>
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
(function(window) {
|
||||
'use strict';
|
||||
|
||||
@@ -177,4 +175,3 @@ limitations under the License.
|
||||
};
|
||||
}
|
||||
})(window);
|
||||
</script>
|
||||
|
||||
@@ -19,13 +19,13 @@ limitations under the License.
|
||||
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
|
||||
<title>keyboard-shortcut-behavior</title>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/bower_components/web-component-tester/browser.js"></script>
|
||||
<script src="../../test/test-pre-setup.js"></script>
|
||||
<link rel="import" href="../../test/common-test-setup.html"/>
|
||||
<link rel="import" href="gr-access-behavior.html">
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/components/wct-browser-legacy/browser.js"></script>
|
||||
<script type="module" src="../../test/test-pre-setup.js"></script>
|
||||
<script type="module" src="../../test/common-test-setup.js"></script>
|
||||
<script type="module" src="./gr-access-behavior.js"></script>
|
||||
|
||||
<test-fixture id="basic">
|
||||
<template>
|
||||
@@ -33,41 +33,44 @@ limitations under the License.
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<script>
|
||||
suite('gr-access-behavior tests', async () => {
|
||||
await readyToTest();
|
||||
let element;
|
||||
<script type="module">
|
||||
import '../../test/test-pre-setup.js';
|
||||
import '../../test/common-test-setup.js';
|
||||
import './gr-access-behavior.js';
|
||||
import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
|
||||
suite('gr-access-behavior tests', () => {
|
||||
let element;
|
||||
|
||||
suiteSetup(() => {
|
||||
// Define a Polymer element that uses this behavior.
|
||||
Polymer({
|
||||
is: 'test-element',
|
||||
behaviors: [Gerrit.AccessBehavior],
|
||||
});
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
element = fixture('basic');
|
||||
});
|
||||
|
||||
test('toSortedArray', () => {
|
||||
const rules = {
|
||||
'global:Project-Owners': {
|
||||
action: 'ALLOW', force: false,
|
||||
},
|
||||
'4c97682e6ce6b7247f3381b6f1789356666de7f': {
|
||||
action: 'ALLOW', force: false,
|
||||
},
|
||||
};
|
||||
const expectedResult = [
|
||||
{id: '4c97682e6ce6b7247f3381b6f1789356666de7f', value: {
|
||||
action: 'ALLOW', force: false,
|
||||
}},
|
||||
{id: 'global:Project-Owners', value: {
|
||||
action: 'ALLOW', force: false,
|
||||
}},
|
||||
];
|
||||
assert.deepEqual(element.toSortedArray(rules), expectedResult);
|
||||
suiteSetup(() => {
|
||||
// Define a Polymer element that uses this behavior.
|
||||
Polymer({
|
||||
is: 'test-element',
|
||||
behaviors: [Gerrit.AccessBehavior],
|
||||
});
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
element = fixture('basic');
|
||||
});
|
||||
|
||||
test('toSortedArray', () => {
|
||||
const rules = {
|
||||
'global:Project-Owners': {
|
||||
action: 'ALLOW', force: false,
|
||||
},
|
||||
'4c97682e6ce6b7247f3381b6f1789356666de7f': {
|
||||
action: 'ALLOW', force: false,
|
||||
},
|
||||
};
|
||||
const expectedResult = [
|
||||
{id: '4c97682e6ce6b7247f3381b6f1789356666de7f', value: {
|
||||
action: 'ALLOW', force: false,
|
||||
}},
|
||||
{id: 'global:Project-Owners', value: {
|
||||
action: 'ALLOW', force: false,
|
||||
}},
|
||||
];
|
||||
assert.deepEqual(element.toSortedArray(rules), expectedResult);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
<!--
|
||||
@license
|
||||
Copyright (C) 2018 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.
|
||||
-->
|
||||
<script>
|
||||
/**
|
||||
* @license
|
||||
* Copyright (C) 2018 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.
|
||||
*/
|
||||
(function(window) {
|
||||
'use strict';
|
||||
|
||||
@@ -220,4 +219,3 @@ limitations under the License.
|
||||
};
|
||||
}
|
||||
})(window);
|
||||
</script>
|
||||
|
||||
@@ -19,13 +19,13 @@ limitations under the License.
|
||||
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
|
||||
<title>keyboard-shortcut-behavior</title>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/bower_components/web-component-tester/browser.js"></script>
|
||||
<script src="../../test/test-pre-setup.js"></script>
|
||||
<link rel="import" href="../../test/common-test-setup.html"/>
|
||||
<link rel="import" href="gr-admin-nav-behavior.html">
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/components/wct-browser-legacy/browser.js"></script>
|
||||
<script type="module" src="../../test/test-pre-setup.js"></script>
|
||||
<script type="module" src="../../test/common-test-setup.js"></script>
|
||||
<script type="module" src="./gr-admin-nav-behavior.js"></script>
|
||||
|
||||
<test-fixture id="basic">
|
||||
<template>
|
||||
@@ -33,338 +33,341 @@ limitations under the License.
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<script>
|
||||
suite('gr-admin-nav-behavior tests', async () => {
|
||||
await readyToTest();
|
||||
let element;
|
||||
let sandbox;
|
||||
let capabilityStub;
|
||||
let menuLinkStub;
|
||||
<script type="module">
|
||||
import '../../test/test-pre-setup.js';
|
||||
import '../../test/common-test-setup.js';
|
||||
import './gr-admin-nav-behavior.js';
|
||||
import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
|
||||
suite('gr-admin-nav-behavior tests', () => {
|
||||
let element;
|
||||
let sandbox;
|
||||
let capabilityStub;
|
||||
let menuLinkStub;
|
||||
|
||||
suiteSetup(() => {
|
||||
// Define a Polymer element that uses this behavior.
|
||||
Polymer({
|
||||
is: 'test-element',
|
||||
behaviors: [
|
||||
Gerrit.AdminNavBehavior,
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
element = fixture('basic');
|
||||
sandbox = sinon.sandbox.create();
|
||||
capabilityStub = sinon.stub();
|
||||
menuLinkStub = sinon.stub().returns([]);
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
const testAdminLinks = (account, options, expected, done) => {
|
||||
element.getAdminLinks(account,
|
||||
capabilityStub,
|
||||
menuLinkStub,
|
||||
options)
|
||||
.then(res => {
|
||||
assert.equal(expected.totalLength, res.links.length);
|
||||
assert.equal(res.links[0].name, 'Repositories');
|
||||
// Repos
|
||||
if (expected.groupListShown) {
|
||||
assert.equal(res.links[1].name, 'Groups');
|
||||
}
|
||||
|
||||
if (expected.pluginListShown) {
|
||||
assert.equal(res.links[2].name, 'Plugins');
|
||||
assert.isNotOk(res.links[2].subsection);
|
||||
}
|
||||
|
||||
if (expected.projectPageShown) {
|
||||
assert.isOk(res.links[0].subsection);
|
||||
assert.equal(res.links[0].subsection.children.length, 5);
|
||||
} else {
|
||||
assert.isNotOk(res.links[0].subsection);
|
||||
}
|
||||
// Groups
|
||||
if (expected.groupPageShown) {
|
||||
assert.isOk(res.links[1].subsection);
|
||||
assert.equal(res.links[1].subsection.children.length,
|
||||
expected.groupSubpageLength);
|
||||
} else if ( expected.totalLength > 1) {
|
||||
assert.isNotOk(res.links[1].subsection);
|
||||
}
|
||||
|
||||
if (expected.pluginGeneratedLinks) {
|
||||
for (const link of expected.pluginGeneratedLinks) {
|
||||
const linkMatch = res.links
|
||||
.find(l => (l.url === link.url && l.name === link.text));
|
||||
assert.isTrue(!!linkMatch);
|
||||
|
||||
// External links should open in new tab.
|
||||
if (link.url[0] !== '/') {
|
||||
assert.equal(linkMatch.target, '_blank');
|
||||
} else {
|
||||
assert.isNotOk(linkMatch.target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Current section
|
||||
if (expected.projectPageShown || expected.groupPageShown) {
|
||||
assert.isOk(res.expandedSection);
|
||||
assert.isOk(res.expandedSection.children);
|
||||
} else {
|
||||
assert.isNotOk(res.expandedSection);
|
||||
}
|
||||
if (expected.projectPageShown) {
|
||||
assert.equal(res.expandedSection.name, 'my-repo');
|
||||
assert.equal(res.expandedSection.children.length, 5);
|
||||
} else if (expected.groupPageShown) {
|
||||
assert.equal(res.expandedSection.name, 'my-group');
|
||||
assert.equal(res.expandedSection.children.length,
|
||||
expected.groupSubpageLength);
|
||||
}
|
||||
done();
|
||||
});
|
||||
};
|
||||
|
||||
suite('logged out', () => {
|
||||
let account;
|
||||
let expected;
|
||||
|
||||
setup(() => {
|
||||
expected = {
|
||||
groupListShown: false,
|
||||
groupPageShown: false,
|
||||
pluginListShown: false,
|
||||
};
|
||||
});
|
||||
|
||||
test('without a specific repo or group', done => {
|
||||
let options;
|
||||
expected = Object.assign(expected, {
|
||||
totalLength: 1,
|
||||
projectPageShown: false,
|
||||
});
|
||||
testAdminLinks(account, options, expected, done);
|
||||
});
|
||||
|
||||
test('with a repo', done => {
|
||||
const options = {repoName: 'my-repo'};
|
||||
expected = Object.assign(expected, {
|
||||
totalLength: 1,
|
||||
projectPageShown: true,
|
||||
});
|
||||
testAdminLinks(account, options, expected, done);
|
||||
});
|
||||
|
||||
test('with plugin generated links', done => {
|
||||
let options;
|
||||
const generatedLinks = [
|
||||
{text: 'internal link text', url: '/internal/link/url'},
|
||||
{text: 'external link text', url: 'http://external/link/url'},
|
||||
];
|
||||
menuLinkStub.returns(generatedLinks);
|
||||
expected = Object.assign(expected, {
|
||||
totalLength: 3,
|
||||
projectPageShown: false,
|
||||
pluginGeneratedLinks: generatedLinks,
|
||||
});
|
||||
testAdminLinks(account, options, expected, done);
|
||||
});
|
||||
});
|
||||
|
||||
suite('no plugin capability logged in', () => {
|
||||
const account = {
|
||||
name: 'test-user',
|
||||
};
|
||||
let expected;
|
||||
|
||||
setup(() => {
|
||||
expected = {
|
||||
totalLength: 2,
|
||||
pluginListShown: false,
|
||||
};
|
||||
capabilityStub.returns(Promise.resolve({}));
|
||||
});
|
||||
|
||||
test('without a specific project or group', done => {
|
||||
let options;
|
||||
expected = Object.assign(expected, {
|
||||
projectPageShown: false,
|
||||
groupListShown: true,
|
||||
groupPageShown: false,
|
||||
});
|
||||
testAdminLinks(account, options, expected, done);
|
||||
});
|
||||
|
||||
test('with a repo', done => {
|
||||
const account = {
|
||||
name: 'test-user',
|
||||
};
|
||||
const options = {repoName: 'my-repo'};
|
||||
expected = Object.assign(expected, {
|
||||
projectPageShown: true,
|
||||
groupListShown: true,
|
||||
groupPageShown: false,
|
||||
});
|
||||
testAdminLinks(account, options, expected, done);
|
||||
});
|
||||
});
|
||||
|
||||
suite('view plugin capability logged in', () => {
|
||||
const account = {
|
||||
name: 'test-user',
|
||||
};
|
||||
let expected;
|
||||
|
||||
setup(() => {
|
||||
capabilityStub.returns(Promise.resolve({viewPlugins: true}));
|
||||
expected = {
|
||||
totalLength: 3,
|
||||
groupListShown: true,
|
||||
pluginListShown: true,
|
||||
};
|
||||
});
|
||||
|
||||
test('without a specific repo or group', done => {
|
||||
let options;
|
||||
expected = Object.assign(expected, {
|
||||
projectPageShown: false,
|
||||
groupPageShown: false,
|
||||
});
|
||||
testAdminLinks(account, options, expected, done);
|
||||
});
|
||||
|
||||
test('with a repo', done => {
|
||||
const options = {repoName: 'my-repo'};
|
||||
expected = Object.assign(expected, {
|
||||
projectPageShown: true,
|
||||
groupPageShown: false,
|
||||
});
|
||||
testAdminLinks(account, options, expected, done);
|
||||
});
|
||||
|
||||
test('admin with internal group', done => {
|
||||
const options = {
|
||||
groupId: 'a15262',
|
||||
groupName: 'my-group',
|
||||
groupIsInternal: true,
|
||||
isAdmin: true,
|
||||
groupOwner: false,
|
||||
};
|
||||
expected = Object.assign(expected, {
|
||||
projectPageShown: false,
|
||||
groupPageShown: true,
|
||||
groupSubpageLength: 2,
|
||||
});
|
||||
testAdminLinks(account, options, expected, done);
|
||||
});
|
||||
|
||||
test('group owner with internal group', done => {
|
||||
const options = {
|
||||
groupId: 'a15262',
|
||||
groupName: 'my-group',
|
||||
groupIsInternal: true,
|
||||
isAdmin: false,
|
||||
groupOwner: true,
|
||||
};
|
||||
expected = Object.assign(expected, {
|
||||
projectPageShown: false,
|
||||
groupPageShown: true,
|
||||
groupSubpageLength: 2,
|
||||
});
|
||||
testAdminLinks(account, options, expected, done);
|
||||
});
|
||||
|
||||
test('non owner or admin with internal group', done => {
|
||||
const options = {
|
||||
groupId: 'a15262',
|
||||
groupName: 'my-group',
|
||||
groupIsInternal: true,
|
||||
isAdmin: false,
|
||||
groupOwner: false,
|
||||
};
|
||||
expected = Object.assign(expected, {
|
||||
projectPageShown: false,
|
||||
groupPageShown: true,
|
||||
groupSubpageLength: 1,
|
||||
});
|
||||
testAdminLinks(account, options, expected, done);
|
||||
});
|
||||
|
||||
test('admin with external group', done => {
|
||||
const options = {
|
||||
groupId: 'a15262',
|
||||
groupName: 'my-group',
|
||||
groupIsInternal: false,
|
||||
isAdmin: true,
|
||||
groupOwner: true,
|
||||
};
|
||||
expected = Object.assign(expected, {
|
||||
projectPageShown: false,
|
||||
groupPageShown: true,
|
||||
groupSubpageLength: 0,
|
||||
});
|
||||
testAdminLinks(account, options, expected, done);
|
||||
});
|
||||
});
|
||||
|
||||
suite('view plugin screen with plugin capability', () => {
|
||||
const account = {
|
||||
name: 'test-user',
|
||||
};
|
||||
let expected;
|
||||
|
||||
setup(() => {
|
||||
capabilityStub.returns(Promise.resolve({pluginCapability: true}));
|
||||
expected = {};
|
||||
});
|
||||
|
||||
test('with plugin with capabilities', done => {
|
||||
let options;
|
||||
const generatedLinks = [
|
||||
{text: 'without capability', url: '/without'},
|
||||
{text: 'with capability',
|
||||
url: '/with',
|
||||
capability: 'pluginCapability'},
|
||||
];
|
||||
menuLinkStub.returns(generatedLinks);
|
||||
expected = Object.assign(expected, {
|
||||
totalLength: 4,
|
||||
pluginGeneratedLinks: generatedLinks,
|
||||
});
|
||||
testAdminLinks(account, options, expected, done);
|
||||
});
|
||||
});
|
||||
|
||||
suite('view plugin screen without plugin capability', () => {
|
||||
const account = {
|
||||
name: 'test-user',
|
||||
};
|
||||
let expected;
|
||||
|
||||
setup(() => {
|
||||
capabilityStub.returns(Promise.resolve({}));
|
||||
expected = {};
|
||||
});
|
||||
|
||||
test('with plugin with capabilities', done => {
|
||||
let options;
|
||||
const generatedLinks = [
|
||||
{text: 'without capability', url: '/without'},
|
||||
{text: 'with capability',
|
||||
url: '/with',
|
||||
capability: 'pluginCapability'},
|
||||
];
|
||||
menuLinkStub.returns(generatedLinks);
|
||||
expected = Object.assign(expected, {
|
||||
totalLength: 3,
|
||||
pluginGeneratedLinks: [generatedLinks[0]],
|
||||
});
|
||||
testAdminLinks(account, options, expected, done);
|
||||
});
|
||||
suiteSetup(() => {
|
||||
// Define a Polymer element that uses this behavior.
|
||||
Polymer({
|
||||
is: 'test-element',
|
||||
behaviors: [
|
||||
Gerrit.AdminNavBehavior,
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
element = fixture('basic');
|
||||
sandbox = sinon.sandbox.create();
|
||||
capabilityStub = sinon.stub();
|
||||
menuLinkStub = sinon.stub().returns([]);
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
const testAdminLinks = (account, options, expected, done) => {
|
||||
element.getAdminLinks(account,
|
||||
capabilityStub,
|
||||
menuLinkStub,
|
||||
options)
|
||||
.then(res => {
|
||||
assert.equal(expected.totalLength, res.links.length);
|
||||
assert.equal(res.links[0].name, 'Repositories');
|
||||
// Repos
|
||||
if (expected.groupListShown) {
|
||||
assert.equal(res.links[1].name, 'Groups');
|
||||
}
|
||||
|
||||
if (expected.pluginListShown) {
|
||||
assert.equal(res.links[2].name, 'Plugins');
|
||||
assert.isNotOk(res.links[2].subsection);
|
||||
}
|
||||
|
||||
if (expected.projectPageShown) {
|
||||
assert.isOk(res.links[0].subsection);
|
||||
assert.equal(res.links[0].subsection.children.length, 5);
|
||||
} else {
|
||||
assert.isNotOk(res.links[0].subsection);
|
||||
}
|
||||
// Groups
|
||||
if (expected.groupPageShown) {
|
||||
assert.isOk(res.links[1].subsection);
|
||||
assert.equal(res.links[1].subsection.children.length,
|
||||
expected.groupSubpageLength);
|
||||
} else if ( expected.totalLength > 1) {
|
||||
assert.isNotOk(res.links[1].subsection);
|
||||
}
|
||||
|
||||
if (expected.pluginGeneratedLinks) {
|
||||
for (const link of expected.pluginGeneratedLinks) {
|
||||
const linkMatch = res.links
|
||||
.find(l => (l.url === link.url && l.name === link.text));
|
||||
assert.isTrue(!!linkMatch);
|
||||
|
||||
// External links should open in new tab.
|
||||
if (link.url[0] !== '/') {
|
||||
assert.equal(linkMatch.target, '_blank');
|
||||
} else {
|
||||
assert.isNotOk(linkMatch.target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Current section
|
||||
if (expected.projectPageShown || expected.groupPageShown) {
|
||||
assert.isOk(res.expandedSection);
|
||||
assert.isOk(res.expandedSection.children);
|
||||
} else {
|
||||
assert.isNotOk(res.expandedSection);
|
||||
}
|
||||
if (expected.projectPageShown) {
|
||||
assert.equal(res.expandedSection.name, 'my-repo');
|
||||
assert.equal(res.expandedSection.children.length, 5);
|
||||
} else if (expected.groupPageShown) {
|
||||
assert.equal(res.expandedSection.name, 'my-group');
|
||||
assert.equal(res.expandedSection.children.length,
|
||||
expected.groupSubpageLength);
|
||||
}
|
||||
done();
|
||||
});
|
||||
};
|
||||
|
||||
suite('logged out', () => {
|
||||
let account;
|
||||
let expected;
|
||||
|
||||
setup(() => {
|
||||
expected = {
|
||||
groupListShown: false,
|
||||
groupPageShown: false,
|
||||
pluginListShown: false,
|
||||
};
|
||||
});
|
||||
|
||||
test('without a specific repo or group', done => {
|
||||
let options;
|
||||
expected = Object.assign(expected, {
|
||||
totalLength: 1,
|
||||
projectPageShown: false,
|
||||
});
|
||||
testAdminLinks(account, options, expected, done);
|
||||
});
|
||||
|
||||
test('with a repo', done => {
|
||||
const options = {repoName: 'my-repo'};
|
||||
expected = Object.assign(expected, {
|
||||
totalLength: 1,
|
||||
projectPageShown: true,
|
||||
});
|
||||
testAdminLinks(account, options, expected, done);
|
||||
});
|
||||
|
||||
test('with plugin generated links', done => {
|
||||
let options;
|
||||
const generatedLinks = [
|
||||
{text: 'internal link text', url: '/internal/link/url'},
|
||||
{text: 'external link text', url: 'http://external/link/url'},
|
||||
];
|
||||
menuLinkStub.returns(generatedLinks);
|
||||
expected = Object.assign(expected, {
|
||||
totalLength: 3,
|
||||
projectPageShown: false,
|
||||
pluginGeneratedLinks: generatedLinks,
|
||||
});
|
||||
testAdminLinks(account, options, expected, done);
|
||||
});
|
||||
});
|
||||
|
||||
suite('no plugin capability logged in', () => {
|
||||
const account = {
|
||||
name: 'test-user',
|
||||
};
|
||||
let expected;
|
||||
|
||||
setup(() => {
|
||||
expected = {
|
||||
totalLength: 2,
|
||||
pluginListShown: false,
|
||||
};
|
||||
capabilityStub.returns(Promise.resolve({}));
|
||||
});
|
||||
|
||||
test('without a specific project or group', done => {
|
||||
let options;
|
||||
expected = Object.assign(expected, {
|
||||
projectPageShown: false,
|
||||
groupListShown: true,
|
||||
groupPageShown: false,
|
||||
});
|
||||
testAdminLinks(account, options, expected, done);
|
||||
});
|
||||
|
||||
test('with a repo', done => {
|
||||
const account = {
|
||||
name: 'test-user',
|
||||
};
|
||||
const options = {repoName: 'my-repo'};
|
||||
expected = Object.assign(expected, {
|
||||
projectPageShown: true,
|
||||
groupListShown: true,
|
||||
groupPageShown: false,
|
||||
});
|
||||
testAdminLinks(account, options, expected, done);
|
||||
});
|
||||
});
|
||||
|
||||
suite('view plugin capability logged in', () => {
|
||||
const account = {
|
||||
name: 'test-user',
|
||||
};
|
||||
let expected;
|
||||
|
||||
setup(() => {
|
||||
capabilityStub.returns(Promise.resolve({viewPlugins: true}));
|
||||
expected = {
|
||||
totalLength: 3,
|
||||
groupListShown: true,
|
||||
pluginListShown: true,
|
||||
};
|
||||
});
|
||||
|
||||
test('without a specific repo or group', done => {
|
||||
let options;
|
||||
expected = Object.assign(expected, {
|
||||
projectPageShown: false,
|
||||
groupPageShown: false,
|
||||
});
|
||||
testAdminLinks(account, options, expected, done);
|
||||
});
|
||||
|
||||
test('with a repo', done => {
|
||||
const options = {repoName: 'my-repo'};
|
||||
expected = Object.assign(expected, {
|
||||
projectPageShown: true,
|
||||
groupPageShown: false,
|
||||
});
|
||||
testAdminLinks(account, options, expected, done);
|
||||
});
|
||||
|
||||
test('admin with internal group', done => {
|
||||
const options = {
|
||||
groupId: 'a15262',
|
||||
groupName: 'my-group',
|
||||
groupIsInternal: true,
|
||||
isAdmin: true,
|
||||
groupOwner: false,
|
||||
};
|
||||
expected = Object.assign(expected, {
|
||||
projectPageShown: false,
|
||||
groupPageShown: true,
|
||||
groupSubpageLength: 2,
|
||||
});
|
||||
testAdminLinks(account, options, expected, done);
|
||||
});
|
||||
|
||||
test('group owner with internal group', done => {
|
||||
const options = {
|
||||
groupId: 'a15262',
|
||||
groupName: 'my-group',
|
||||
groupIsInternal: true,
|
||||
isAdmin: false,
|
||||
groupOwner: true,
|
||||
};
|
||||
expected = Object.assign(expected, {
|
||||
projectPageShown: false,
|
||||
groupPageShown: true,
|
||||
groupSubpageLength: 2,
|
||||
});
|
||||
testAdminLinks(account, options, expected, done);
|
||||
});
|
||||
|
||||
test('non owner or admin with internal group', done => {
|
||||
const options = {
|
||||
groupId: 'a15262',
|
||||
groupName: 'my-group',
|
||||
groupIsInternal: true,
|
||||
isAdmin: false,
|
||||
groupOwner: false,
|
||||
};
|
||||
expected = Object.assign(expected, {
|
||||
projectPageShown: false,
|
||||
groupPageShown: true,
|
||||
groupSubpageLength: 1,
|
||||
});
|
||||
testAdminLinks(account, options, expected, done);
|
||||
});
|
||||
|
||||
test('admin with external group', done => {
|
||||
const options = {
|
||||
groupId: 'a15262',
|
||||
groupName: 'my-group',
|
||||
groupIsInternal: false,
|
||||
isAdmin: true,
|
||||
groupOwner: true,
|
||||
};
|
||||
expected = Object.assign(expected, {
|
||||
projectPageShown: false,
|
||||
groupPageShown: true,
|
||||
groupSubpageLength: 0,
|
||||
});
|
||||
testAdminLinks(account, options, expected, done);
|
||||
});
|
||||
});
|
||||
|
||||
suite('view plugin screen with plugin capability', () => {
|
||||
const account = {
|
||||
name: 'test-user',
|
||||
};
|
||||
let expected;
|
||||
|
||||
setup(() => {
|
||||
capabilityStub.returns(Promise.resolve({pluginCapability: true}));
|
||||
expected = {};
|
||||
});
|
||||
|
||||
test('with plugin with capabilities', done => {
|
||||
let options;
|
||||
const generatedLinks = [
|
||||
{text: 'without capability', url: '/without'},
|
||||
{text: 'with capability',
|
||||
url: '/with',
|
||||
capability: 'pluginCapability'},
|
||||
];
|
||||
menuLinkStub.returns(generatedLinks);
|
||||
expected = Object.assign(expected, {
|
||||
totalLength: 4,
|
||||
pluginGeneratedLinks: generatedLinks,
|
||||
});
|
||||
testAdminLinks(account, options, expected, done);
|
||||
});
|
||||
});
|
||||
|
||||
suite('view plugin screen without plugin capability', () => {
|
||||
const account = {
|
||||
name: 'test-user',
|
||||
};
|
||||
let expected;
|
||||
|
||||
setup(() => {
|
||||
capabilityStub.returns(Promise.resolve({}));
|
||||
expected = {};
|
||||
});
|
||||
|
||||
test('with plugin with capabilities', done => {
|
||||
let options;
|
||||
const generatedLinks = [
|
||||
{text: 'without capability', url: '/without'},
|
||||
{text: 'with capability',
|
||||
url: '/with',
|
||||
capability: 'pluginCapability'},
|
||||
];
|
||||
menuLinkStub.returns(generatedLinks);
|
||||
expected = Object.assign(expected, {
|
||||
totalLength: 3,
|
||||
pluginGeneratedLinks: [generatedLinks[0]],
|
||||
});
|
||||
testAdminLinks(account, options, expected, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
<!--
|
||||
@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.
|
||||
-->
|
||||
<script>
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
(function(window) {
|
||||
'use strict';
|
||||
|
||||
@@ -105,4 +104,3 @@ limitations under the License.
|
||||
};
|
||||
}
|
||||
})(window);
|
||||
</script>
|
||||
|
||||
@@ -19,13 +19,13 @@ limitations under the License.
|
||||
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
|
||||
<title>keyboard-shortcut-behavior</title>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/bower_components/web-component-tester/browser.js"></script>
|
||||
<script src="../../test/test-pre-setup.js"></script>
|
||||
<link rel="import" href="../../test/common-test-setup.html"/>
|
||||
<link rel="import" href="gr-change-table-behavior.html">
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/components/wct-browser-legacy/browser.js"></script>
|
||||
<script type="module" src="../../test/test-pre-setup.js"></script>
|
||||
<script type="module" src="../../test/common-test-setup.js"></script>
|
||||
<script type="module" src="./gr-change-table-behavior.js"></script>
|
||||
|
||||
<test-fixture id="basic">
|
||||
<template>
|
||||
@@ -41,87 +41,90 @@ limitations under the License.
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<script>
|
||||
suite('gr-change-table-behavior tests', async () => {
|
||||
await readyToTest();
|
||||
let element;
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
let overlay;
|
||||
<script type="module">
|
||||
import '../../test/test-pre-setup.js';
|
||||
import '../../test/common-test-setup.js';
|
||||
import './gr-change-table-behavior.js';
|
||||
import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
|
||||
suite('gr-change-table-behavior tests', () => {
|
||||
let element;
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
let overlay;
|
||||
|
||||
suiteSetup(() => {
|
||||
// Define a Polymer element that uses this behavior.
|
||||
Polymer({
|
||||
is: 'test-element',
|
||||
behaviors: [Gerrit.ChangeTableBehavior],
|
||||
});
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
element = fixture('basic');
|
||||
overlay = fixture('within-overlay');
|
||||
});
|
||||
|
||||
test('getComplementColumns', () => {
|
||||
let columns = [
|
||||
'Subject',
|
||||
'Status',
|
||||
'Owner',
|
||||
'Assignee',
|
||||
'Repo',
|
||||
'Branch',
|
||||
'Updated',
|
||||
'Size',
|
||||
];
|
||||
assert.deepEqual(element.getComplementColumns(columns), []);
|
||||
|
||||
columns = [
|
||||
'Subject',
|
||||
'Status',
|
||||
'Assignee',
|
||||
'Repo',
|
||||
'Branch',
|
||||
'Size',
|
||||
];
|
||||
assert.deepEqual(element.getComplementColumns(columns),
|
||||
['Owner', 'Updated']);
|
||||
});
|
||||
|
||||
test('isColumnHidden', () => {
|
||||
const columnToCheck = 'Repo';
|
||||
let columnsToDisplay = [
|
||||
'Subject',
|
||||
'Status',
|
||||
'Owner',
|
||||
'Assignee',
|
||||
'Repo',
|
||||
'Branch',
|
||||
'Updated',
|
||||
'Size',
|
||||
];
|
||||
assert.isFalse(element.isColumnHidden(columnToCheck, columnsToDisplay));
|
||||
|
||||
columnsToDisplay = [
|
||||
'Subject',
|
||||
'Status',
|
||||
'Owner',
|
||||
'Assignee',
|
||||
'Branch',
|
||||
'Updated',
|
||||
'Size',
|
||||
];
|
||||
assert.isTrue(element.isColumnHidden(columnToCheck, columnsToDisplay));
|
||||
});
|
||||
|
||||
test('getVisibleColumns maps Project to Repo', () => {
|
||||
const columns = [
|
||||
'Subject',
|
||||
'Status',
|
||||
'Owner',
|
||||
];
|
||||
assert.deepEqual(element.getVisibleColumns(columns), columns.slice(0));
|
||||
assert.deepEqual(
|
||||
element.getVisibleColumns(columns.concat(['Project'])),
|
||||
columns.slice(0).concat(['Repo']));
|
||||
suiteSetup(() => {
|
||||
// Define a Polymer element that uses this behavior.
|
||||
Polymer({
|
||||
is: 'test-element',
|
||||
behaviors: [Gerrit.ChangeTableBehavior],
|
||||
});
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
element = fixture('basic');
|
||||
overlay = fixture('within-overlay');
|
||||
});
|
||||
|
||||
test('getComplementColumns', () => {
|
||||
let columns = [
|
||||
'Subject',
|
||||
'Status',
|
||||
'Owner',
|
||||
'Assignee',
|
||||
'Repo',
|
||||
'Branch',
|
||||
'Updated',
|
||||
'Size',
|
||||
];
|
||||
assert.deepEqual(element.getComplementColumns(columns), []);
|
||||
|
||||
columns = [
|
||||
'Subject',
|
||||
'Status',
|
||||
'Assignee',
|
||||
'Repo',
|
||||
'Branch',
|
||||
'Size',
|
||||
];
|
||||
assert.deepEqual(element.getComplementColumns(columns),
|
||||
['Owner', 'Updated']);
|
||||
});
|
||||
|
||||
test('isColumnHidden', () => {
|
||||
const columnToCheck = 'Repo';
|
||||
let columnsToDisplay = [
|
||||
'Subject',
|
||||
'Status',
|
||||
'Owner',
|
||||
'Assignee',
|
||||
'Repo',
|
||||
'Branch',
|
||||
'Updated',
|
||||
'Size',
|
||||
];
|
||||
assert.isFalse(element.isColumnHidden(columnToCheck, columnsToDisplay));
|
||||
|
||||
columnsToDisplay = [
|
||||
'Subject',
|
||||
'Status',
|
||||
'Owner',
|
||||
'Assignee',
|
||||
'Branch',
|
||||
'Updated',
|
||||
'Size',
|
||||
];
|
||||
assert.isTrue(element.isColumnHidden(columnToCheck, columnsToDisplay));
|
||||
});
|
||||
|
||||
test('getVisibleColumns maps Project to Repo', () => {
|
||||
const columns = [
|
||||
'Subject',
|
||||
'Status',
|
||||
'Owner',
|
||||
];
|
||||
assert.deepEqual(element.getVisibleColumns(columns), columns.slice(0));
|
||||
assert.deepEqual(
|
||||
element.getVisibleColumns(columns.concat(['Project'])),
|
||||
columns.slice(0).concat(['Repo']));
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,23 +1,21 @@
|
||||
<!--
|
||||
@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.
|
||||
*/
|
||||
import '../../scripts/gr-display-name-utils/gr-display-name-utils.js';
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
<script src="../../scripts/gr-display-name-utils/gr-display-name-utils.js"></script>
|
||||
|
||||
<script>
|
||||
(function(window) {
|
||||
'use strict';
|
||||
|
||||
@@ -57,4 +55,3 @@ limitations under the License.
|
||||
};
|
||||
}
|
||||
})(window);
|
||||
</script>
|
||||
|
||||
@@ -19,13 +19,13 @@ limitations under the License.
|
||||
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
|
||||
<title>gr-display-name-behavior</title>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/bower_components/web-component-tester/browser.js"></script>
|
||||
<script src="../../test/test-pre-setup.js"></script>
|
||||
<link rel="import" href="../../test/common-test-setup.html"/>
|
||||
<link rel="import" href="gr-display-name-behavior.html">
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/components/wct-browser-legacy/browser.js"></script>
|
||||
<script type="module" src="../../test/test-pre-setup.js"></script>
|
||||
<script type="module" src="../../test/common-test-setup.js"></script>
|
||||
<script type="module" src="./gr-display-name-behavior.js"></script>
|
||||
|
||||
<test-fixture id="basic">
|
||||
<template>
|
||||
@@ -33,69 +33,72 @@ limitations under the License.
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<script>
|
||||
suite('gr-display-name-behavior tests', async () => {
|
||||
await readyToTest();
|
||||
let element;
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const config = {
|
||||
user: {
|
||||
anonymous_coward_name: 'Anonymous Coward',
|
||||
},
|
||||
};
|
||||
<script type="module">
|
||||
import '../../test/test-pre-setup.js';
|
||||
import '../../test/common-test-setup.js';
|
||||
import './gr-display-name-behavior.js';
|
||||
import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
|
||||
suite('gr-display-name-behavior tests', () => {
|
||||
let element;
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const config = {
|
||||
user: {
|
||||
anonymous_coward_name: 'Anonymous Coward',
|
||||
},
|
||||
};
|
||||
|
||||
suiteSetup(() => {
|
||||
// Define a Polymer element that uses this behavior.
|
||||
Polymer({
|
||||
is: 'test-element-anon',
|
||||
behaviors: [
|
||||
Gerrit.DisplayNameBehavior,
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
element = fixture('basic');
|
||||
});
|
||||
|
||||
test('getUserName name only', () => {
|
||||
const account = {
|
||||
name: 'test-name',
|
||||
};
|
||||
assert.deepEqual(element.getUserName(config, account, true), 'test-name');
|
||||
});
|
||||
|
||||
test('getUserName username only', () => {
|
||||
const account = {
|
||||
username: 'test-user',
|
||||
};
|
||||
assert.deepEqual(element.getUserName(config, account, true), 'test-user');
|
||||
});
|
||||
|
||||
test('getUserName email only', () => {
|
||||
const account = {
|
||||
email: 'test-user@test-url.com',
|
||||
};
|
||||
assert.deepEqual(element.getUserName(config, account, true),
|
||||
'test-user@test-url.com');
|
||||
});
|
||||
|
||||
test('getUserName returns not Anonymous Coward as the anon name', () => {
|
||||
assert.deepEqual(element.getUserName(config, null, true), 'Anonymous');
|
||||
});
|
||||
|
||||
test('getUserName for the config returning the anon name', () => {
|
||||
const config = {
|
||||
user: {
|
||||
anonymous_coward_name: 'Test Anon',
|
||||
},
|
||||
};
|
||||
assert.deepEqual(element.getUserName(config, null, true), 'Test Anon');
|
||||
});
|
||||
|
||||
test('getGroupDisplayName', () => {
|
||||
assert.equal(element.getGroupDisplayName({name: 'Some user name'}),
|
||||
'Some user name (group)');
|
||||
suiteSetup(() => {
|
||||
// Define a Polymer element that uses this behavior.
|
||||
Polymer({
|
||||
is: 'test-element-anon',
|
||||
behaviors: [
|
||||
Gerrit.DisplayNameBehavior,
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
element = fixture('basic');
|
||||
});
|
||||
|
||||
test('getUserName name only', () => {
|
||||
const account = {
|
||||
name: 'test-name',
|
||||
};
|
||||
assert.deepEqual(element.getUserName(config, account, true), 'test-name');
|
||||
});
|
||||
|
||||
test('getUserName username only', () => {
|
||||
const account = {
|
||||
username: 'test-user',
|
||||
};
|
||||
assert.deepEqual(element.getUserName(config, account, true), 'test-user');
|
||||
});
|
||||
|
||||
test('getUserName email only', () => {
|
||||
const account = {
|
||||
email: 'test-user@test-url.com',
|
||||
};
|
||||
assert.deepEqual(element.getUserName(config, account, true),
|
||||
'test-user@test-url.com');
|
||||
});
|
||||
|
||||
test('getUserName returns not Anonymous Coward as the anon name', () => {
|
||||
assert.deepEqual(element.getUserName(config, null, true), 'Anonymous');
|
||||
});
|
||||
|
||||
test('getUserName for the config returning the anon name', () => {
|
||||
const config = {
|
||||
user: {
|
||||
anonymous_coward_name: 'Test Anon',
|
||||
},
|
||||
};
|
||||
assert.deepEqual(element.getUserName(config, null, true), 'Test Anon');
|
||||
});
|
||||
|
||||
test('getGroupDisplayName', () => {
|
||||
assert.equal(element.getGroupDisplayName({name: 'Some user name'}),
|
||||
'Some user name (group)');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
<!--
|
||||
@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.
|
||||
*/
|
||||
import '../base-url-behavior/base-url-behavior.js';
|
||||
|
||||
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.
|
||||
-->
|
||||
<link rel="import" href="../base-url-behavior/base-url-behavior.html">
|
||||
<link rel="import" href="../gr-url-encoding-behavior/gr-url-encoding-behavior.html">
|
||||
<script>
|
||||
import '../gr-url-encoding-behavior/gr-url-encoding-behavior.js';
|
||||
(function(window) {
|
||||
'use strict';
|
||||
|
||||
@@ -80,5 +80,3 @@ limitations under the License.
|
||||
};
|
||||
}
|
||||
})(window);
|
||||
|
||||
</script>
|
||||
|
||||
@@ -19,13 +19,13 @@ limitations under the License.
|
||||
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
|
||||
<title>keyboard-shortcut-behavior</title>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/bower_components/web-component-tester/browser.js"></script>
|
||||
<script src="../../test/test-pre-setup.js"></script>
|
||||
<link rel="import" href="../../test/common-test-setup.html"/>
|
||||
<link rel="import" href="gr-list-view-behavior.html">
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/components/wct-browser-legacy/browser.js"></script>
|
||||
<script type="module" src="../../test/test-pre-setup.js"></script>
|
||||
<script type="module" src="../../test/common-test-setup.js"></script>
|
||||
<script type="module" src="./gr-list-view-behavior.js"></script>
|
||||
|
||||
<test-fixture id="basic">
|
||||
<template>
|
||||
@@ -33,62 +33,65 @@ limitations under the License.
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<script>
|
||||
suite('gr-list-view-behavior tests', async () => {
|
||||
await readyToTest();
|
||||
let element;
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
let overlay;
|
||||
<script type="module">
|
||||
import '../../test/test-pre-setup.js';
|
||||
import '../../test/common-test-setup.js';
|
||||
import './gr-list-view-behavior.js';
|
||||
import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
|
||||
suite('gr-list-view-behavior tests', () => {
|
||||
let element;
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
let overlay;
|
||||
|
||||
suiteSetup(() => {
|
||||
// Define a Polymer element that uses this behavior.
|
||||
Polymer({
|
||||
is: 'test-element',
|
||||
behaviors: [Gerrit.ListViewBehavior],
|
||||
});
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
element = fixture('basic');
|
||||
});
|
||||
|
||||
test('computeLoadingClass', () => {
|
||||
assert.equal(element.computeLoadingClass(true), 'loading');
|
||||
assert.equal(element.computeLoadingClass(false), '');
|
||||
});
|
||||
|
||||
test('computeShownItems', () => {
|
||||
const myArr = new Array(26);
|
||||
assert.equal(element.computeShownItems(myArr).length, 25);
|
||||
});
|
||||
|
||||
test('getUrl', () => {
|
||||
assert.equal(element.getUrl('/path/to/something/', 'item'),
|
||||
'/path/to/something/item');
|
||||
assert.equal(element.getUrl('/path/to/something/', 'item%test'),
|
||||
'/path/to/something/item%2525test');
|
||||
});
|
||||
|
||||
test('getFilterValue', () => {
|
||||
let params;
|
||||
assert.equal(element.getFilterValue(params), '');
|
||||
|
||||
params = {filter: null};
|
||||
assert.equal(element.getFilterValue(params), '');
|
||||
|
||||
params = {filter: 'test'};
|
||||
assert.equal(element.getFilterValue(params), 'test');
|
||||
});
|
||||
|
||||
test('getOffsetValue', () => {
|
||||
let params;
|
||||
assert.equal(element.getOffsetValue(params), 0);
|
||||
|
||||
params = {offset: null};
|
||||
assert.equal(element.getOffsetValue(params), 0);
|
||||
|
||||
params = {offset: 1};
|
||||
assert.equal(element.getOffsetValue(params), 1);
|
||||
suiteSetup(() => {
|
||||
// Define a Polymer element that uses this behavior.
|
||||
Polymer({
|
||||
is: 'test-element',
|
||||
behaviors: [Gerrit.ListViewBehavior],
|
||||
});
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
element = fixture('basic');
|
||||
});
|
||||
|
||||
test('computeLoadingClass', () => {
|
||||
assert.equal(element.computeLoadingClass(true), 'loading');
|
||||
assert.equal(element.computeLoadingClass(false), '');
|
||||
});
|
||||
|
||||
test('computeShownItems', () => {
|
||||
const myArr = new Array(26);
|
||||
assert.equal(element.computeShownItems(myArr).length, 25);
|
||||
});
|
||||
|
||||
test('getUrl', () => {
|
||||
assert.equal(element.getUrl('/path/to/something/', 'item'),
|
||||
'/path/to/something/item');
|
||||
assert.equal(element.getUrl('/path/to/something/', 'item%test'),
|
||||
'/path/to/something/item%2525test');
|
||||
});
|
||||
|
||||
test('getFilterValue', () => {
|
||||
let params;
|
||||
assert.equal(element.getFilterValue(params), '');
|
||||
|
||||
params = {filter: null};
|
||||
assert.equal(element.getFilterValue(params), '');
|
||||
|
||||
params = {filter: 'test'};
|
||||
assert.equal(element.getFilterValue(params), 'test');
|
||||
});
|
||||
|
||||
test('getOffsetValue', () => {
|
||||
let params;
|
||||
assert.equal(element.getOffsetValue(params), 0);
|
||||
|
||||
params = {offset: null};
|
||||
assert.equal(element.getOffsetValue(params), 0);
|
||||
|
||||
params = {offset: 1};
|
||||
assert.equal(element.getOffsetValue(params), 1);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
<!--
|
||||
@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.
|
||||
-->
|
||||
<script>
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
(function(window) {
|
||||
'use strict';
|
||||
|
||||
@@ -298,4 +297,3 @@ limitations under the License.
|
||||
};
|
||||
}
|
||||
})(window);
|
||||
</script>
|
||||
|
||||
@@ -15,313 +15,315 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<!-- Polymer included for the html import polyfill. -->
|
||||
<script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/bower_components/web-component-tester/browser.js"></script>
|
||||
<script src="../../test/test-pre-setup.js"></script>
|
||||
<link rel="import" href="../../test/common-test-setup.html"/>
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/components/wct-browser-legacy/browser.js"></script>
|
||||
<script type="module" src="../../test/test-pre-setup.js"></script>
|
||||
<script type="module" src="../../test/common-test-setup.js"></script>
|
||||
<title>gr-patch-set-behavior</title>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
|
||||
<link rel="import" href="gr-patch-set-behavior.html">
|
||||
<script type="module" src="./gr-patch-set-behavior.js"></script>
|
||||
|
||||
<script>
|
||||
suite('gr-patch-set-behavior tests', async () => {
|
||||
await readyToTest();
|
||||
test('getRevisionByPatchNum', () => {
|
||||
const get = Gerrit.PatchSetBehavior.getRevisionByPatchNum;
|
||||
const revisions = [
|
||||
{_number: 0},
|
||||
{_number: 1},
|
||||
{_number: 2},
|
||||
];
|
||||
assert.deepEqual(get(revisions, '1'), revisions[1]);
|
||||
assert.deepEqual(get(revisions, 2), revisions[2]);
|
||||
assert.equal(get(revisions, '3'), undefined);
|
||||
});
|
||||
|
||||
test('fetchChangeUpdates on latest', done => {
|
||||
const knownChange = {
|
||||
revisions: {
|
||||
sha1: {description: 'patch 1', _number: 1},
|
||||
sha2: {description: 'patch 2', _number: 2},
|
||||
},
|
||||
status: 'NEW',
|
||||
messages: [],
|
||||
};
|
||||
const mockRestApi = {
|
||||
getChangeDetail() {
|
||||
return Promise.resolve(knownChange);
|
||||
},
|
||||
};
|
||||
Gerrit.PatchSetBehavior.fetchChangeUpdates(knownChange, mockRestApi)
|
||||
.then(result => {
|
||||
assert.isTrue(result.isLatest);
|
||||
assert.isNotOk(result.newStatus);
|
||||
assert.isFalse(result.newMessages);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('fetchChangeUpdates not on latest', done => {
|
||||
const knownChange = {
|
||||
revisions: {
|
||||
sha1: {description: 'patch 1', _number: 1},
|
||||
sha2: {description: 'patch 2', _number: 2},
|
||||
},
|
||||
status: 'NEW',
|
||||
messages: [],
|
||||
};
|
||||
const actualChange = {
|
||||
revisions: {
|
||||
sha1: {description: 'patch 1', _number: 1},
|
||||
sha2: {description: 'patch 2', _number: 2},
|
||||
sha3: {description: 'patch 3', _number: 3},
|
||||
},
|
||||
status: 'NEW',
|
||||
messages: [],
|
||||
};
|
||||
const mockRestApi = {
|
||||
getChangeDetail() {
|
||||
return Promise.resolve(actualChange);
|
||||
},
|
||||
};
|
||||
Gerrit.PatchSetBehavior.fetchChangeUpdates(knownChange, mockRestApi)
|
||||
.then(result => {
|
||||
assert.isFalse(result.isLatest);
|
||||
assert.isNotOk(result.newStatus);
|
||||
assert.isFalse(result.newMessages);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('fetchChangeUpdates new status', done => {
|
||||
const knownChange = {
|
||||
revisions: {
|
||||
sha1: {description: 'patch 1', _number: 1},
|
||||
sha2: {description: 'patch 2', _number: 2},
|
||||
},
|
||||
status: 'NEW',
|
||||
messages: [],
|
||||
};
|
||||
const actualChange = {
|
||||
revisions: {
|
||||
sha1: {description: 'patch 1', _number: 1},
|
||||
sha2: {description: 'patch 2', _number: 2},
|
||||
},
|
||||
status: 'MERGED',
|
||||
messages: [],
|
||||
};
|
||||
const mockRestApi = {
|
||||
getChangeDetail() {
|
||||
return Promise.resolve(actualChange);
|
||||
},
|
||||
};
|
||||
Gerrit.PatchSetBehavior.fetchChangeUpdates(knownChange, mockRestApi)
|
||||
.then(result => {
|
||||
assert.isTrue(result.isLatest);
|
||||
assert.equal(result.newStatus, 'MERGED');
|
||||
assert.isFalse(result.newMessages);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('fetchChangeUpdates new messages', done => {
|
||||
const knownChange = {
|
||||
revisions: {
|
||||
sha1: {description: 'patch 1', _number: 1},
|
||||
sha2: {description: 'patch 2', _number: 2},
|
||||
},
|
||||
status: 'NEW',
|
||||
messages: [],
|
||||
};
|
||||
const actualChange = {
|
||||
revisions: {
|
||||
sha1: {description: 'patch 1', _number: 1},
|
||||
sha2: {description: 'patch 2', _number: 2},
|
||||
},
|
||||
status: 'NEW',
|
||||
messages: [{message: 'blah blah'}],
|
||||
};
|
||||
const mockRestApi = {
|
||||
getChangeDetail() {
|
||||
return Promise.resolve(actualChange);
|
||||
},
|
||||
};
|
||||
Gerrit.PatchSetBehavior.fetchChangeUpdates(knownChange, mockRestApi)
|
||||
.then(result => {
|
||||
assert.isTrue(result.isLatest);
|
||||
assert.isNotOk(result.newStatus);
|
||||
assert.isTrue(result.newMessages);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('_computeWipForPatchSets', () => {
|
||||
// Compute patch sets for a given timeline on a change. The initial WIP
|
||||
// property of the change can be true or false. The map of tags by
|
||||
// revision is keyed by patch set number. Each value is a list of change
|
||||
// message tags in the order that they occurred in the timeline. These
|
||||
// indicate actions that modify the WIP property of the change and/or
|
||||
// create new patch sets.
|
||||
//
|
||||
// Returns the actual results with an assertWip method that can be used
|
||||
// to compare against an expected value for a particular patch set.
|
||||
const compute = (initialWip, tagsByRevision) => {
|
||||
const change = {
|
||||
messages: [],
|
||||
work_in_progress: initialWip,
|
||||
};
|
||||
const revs = Object.keys(tagsByRevision).sort((a, b) => a - b);
|
||||
for (const rev of revs) {
|
||||
for (const tag of tagsByRevision[rev]) {
|
||||
change.messages.push({
|
||||
tag,
|
||||
_revision_number: rev,
|
||||
});
|
||||
}
|
||||
}
|
||||
let patchNums = revs.map(rev => { return {num: rev}; });
|
||||
patchNums = Gerrit.PatchSetBehavior._computeWipForPatchSets(
|
||||
change, patchNums);
|
||||
const actualWipsByRevision = {};
|
||||
for (const patchNum of patchNums) {
|
||||
actualWipsByRevision[patchNum.num] = patchNum.wip;
|
||||
}
|
||||
const verifier = {
|
||||
assertWip(revision, expectedWip) {
|
||||
const patchNum = patchNums.find(patchNum => patchNum.num == revision);
|
||||
if (!patchNum) {
|
||||
assert.fail('revision ' + revision + ' not found');
|
||||
}
|
||||
assert.equal(patchNum.wip, expectedWip,
|
||||
'wip state for ' + revision + ' is ' +
|
||||
patchNum.wip + '; expected ' + expectedWip);
|
||||
return verifier;
|
||||
},
|
||||
};
|
||||
return verifier;
|
||||
};
|
||||
|
||||
compute(false, {1: ['upload']}).assertWip(1, false);
|
||||
compute(true, {1: ['upload']}).assertWip(1, true);
|
||||
|
||||
const setWip = 'autogenerated:gerrit:setWorkInProgress';
|
||||
const uploadInWip = 'autogenerated:gerrit:newWipPatchSet';
|
||||
const clearWip = 'autogenerated:gerrit:setReadyForReview';
|
||||
|
||||
compute(false, {
|
||||
1: ['upload', setWip],
|
||||
2: ['upload'],
|
||||
3: ['upload', clearWip],
|
||||
4: ['upload', setWip],
|
||||
}).assertWip(1, false) // Change was created with PS1 ready for review
|
||||
.assertWip(2, true) // PS2 was uploaded during WIP
|
||||
.assertWip(3, false) // PS3 was marked ready for review after upload
|
||||
.assertWip(4, false); // PS4 was uploaded ready for review
|
||||
|
||||
compute(false, {
|
||||
1: [uploadInWip, null, 'addReviewer'],
|
||||
2: ['upload'],
|
||||
3: ['upload', clearWip, setWip],
|
||||
4: ['upload'],
|
||||
5: ['upload', clearWip],
|
||||
6: [uploadInWip],
|
||||
}).assertWip(1, true) // Change was created in WIP
|
||||
.assertWip(2, true) // PS2 was uploaded during WIP
|
||||
.assertWip(3, false) // PS3 was marked ready for review
|
||||
.assertWip(4, true) // PS4 was uploaded during WIP
|
||||
.assertWip(5, false) // PS5 was marked ready for review
|
||||
.assertWip(6, true); // PS6 was uploaded with WIP option
|
||||
});
|
||||
|
||||
test('patchNumEquals', () => {
|
||||
const equals = Gerrit.PatchSetBehavior.patchNumEquals;
|
||||
assert.isFalse(equals('edit', 'PARENT'));
|
||||
assert.isFalse(equals('edit', NaN));
|
||||
assert.isFalse(equals(1, '2'));
|
||||
|
||||
assert.isTrue(equals(1, '1'));
|
||||
assert.isTrue(equals(1, 1));
|
||||
assert.isTrue(equals('edit', 'edit'));
|
||||
assert.isTrue(equals('PARENT', 'PARENT'));
|
||||
});
|
||||
|
||||
test('isMergeParent', () => {
|
||||
const isParent = Gerrit.PatchSetBehavior.isMergeParent;
|
||||
assert.isFalse(isParent(1));
|
||||
assert.isFalse(isParent(4321));
|
||||
assert.isFalse(isParent('52'));
|
||||
assert.isFalse(isParent('edit'));
|
||||
assert.isFalse(isParent('PARENT'));
|
||||
assert.isFalse(isParent(0));
|
||||
|
||||
assert.isTrue(isParent(-23));
|
||||
assert.isTrue(isParent(-1));
|
||||
assert.isTrue(isParent('-42'));
|
||||
});
|
||||
|
||||
test('findEditParentRevision', () => {
|
||||
const findParent = Gerrit.PatchSetBehavior.findEditParentRevision;
|
||||
let revisions = [
|
||||
{_number: 0},
|
||||
{_number: 1},
|
||||
{_number: 2},
|
||||
];
|
||||
assert.strictEqual(findParent(revisions), null);
|
||||
|
||||
revisions = [...revisions, {_number: 'edit', basePatchNum: 3}];
|
||||
assert.strictEqual(findParent(revisions), null);
|
||||
|
||||
revisions = [...revisions, {_number: 3}];
|
||||
assert.deepEqual(findParent(revisions), {_number: 3});
|
||||
});
|
||||
|
||||
test('findEditParentPatchNum', () => {
|
||||
const findNum = Gerrit.PatchSetBehavior.findEditParentPatchNum;
|
||||
let revisions = [
|
||||
{_number: 0},
|
||||
{_number: 1},
|
||||
{_number: 2},
|
||||
];
|
||||
assert.equal(findNum(revisions), -1);
|
||||
|
||||
revisions =
|
||||
[...revisions, {_number: 'edit', basePatchNum: 3}, {_number: 3}];
|
||||
assert.deepEqual(findNum(revisions), 3);
|
||||
});
|
||||
|
||||
test('sortRevisions', () => {
|
||||
const sort = Gerrit.PatchSetBehavior.sortRevisions;
|
||||
const revisions = [
|
||||
{_number: 0},
|
||||
{_number: 2},
|
||||
{_number: 1},
|
||||
];
|
||||
const sorted = [
|
||||
{_number: 2},
|
||||
{_number: 1},
|
||||
{_number: 0},
|
||||
];
|
||||
|
||||
assert.deepEqual(sort(revisions), sorted);
|
||||
|
||||
// Edit patchset should follow directly after its basePatchNum.
|
||||
revisions.push({_number: 'edit', basePatchNum: 2});
|
||||
sorted.unshift({_number: 'edit', basePatchNum: 2});
|
||||
assert.deepEqual(sort(revisions), sorted);
|
||||
|
||||
revisions[0].basePatchNum = 0;
|
||||
const edit = sorted.shift();
|
||||
edit.basePatchNum = 0;
|
||||
// Edit patchset should be at index 2.
|
||||
sorted.splice(2, 0, edit);
|
||||
assert.deepEqual(sort(revisions), sorted);
|
||||
});
|
||||
|
||||
test('getParentIndex', () => {
|
||||
assert.equal(Gerrit.PatchSetBehavior.getParentIndex('-13'), 13);
|
||||
assert.equal(Gerrit.PatchSetBehavior.getParentIndex(-4), 4);
|
||||
});
|
||||
<script type="module">
|
||||
import '../../test/test-pre-setup.js';
|
||||
import '../../test/common-test-setup.js';
|
||||
import './gr-patch-set-behavior.js';
|
||||
suite('gr-patch-set-behavior tests', () => {
|
||||
test('getRevisionByPatchNum', () => {
|
||||
const get = Gerrit.PatchSetBehavior.getRevisionByPatchNum;
|
||||
const revisions = [
|
||||
{_number: 0},
|
||||
{_number: 1},
|
||||
{_number: 2},
|
||||
];
|
||||
assert.deepEqual(get(revisions, '1'), revisions[1]);
|
||||
assert.deepEqual(get(revisions, 2), revisions[2]);
|
||||
assert.equal(get(revisions, '3'), undefined);
|
||||
});
|
||||
|
||||
test('fetchChangeUpdates on latest', done => {
|
||||
const knownChange = {
|
||||
revisions: {
|
||||
sha1: {description: 'patch 1', _number: 1},
|
||||
sha2: {description: 'patch 2', _number: 2},
|
||||
},
|
||||
status: 'NEW',
|
||||
messages: [],
|
||||
};
|
||||
const mockRestApi = {
|
||||
getChangeDetail() {
|
||||
return Promise.resolve(knownChange);
|
||||
},
|
||||
};
|
||||
Gerrit.PatchSetBehavior.fetchChangeUpdates(knownChange, mockRestApi)
|
||||
.then(result => {
|
||||
assert.isTrue(result.isLatest);
|
||||
assert.isNotOk(result.newStatus);
|
||||
assert.isFalse(result.newMessages);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('fetchChangeUpdates not on latest', done => {
|
||||
const knownChange = {
|
||||
revisions: {
|
||||
sha1: {description: 'patch 1', _number: 1},
|
||||
sha2: {description: 'patch 2', _number: 2},
|
||||
},
|
||||
status: 'NEW',
|
||||
messages: [],
|
||||
};
|
||||
const actualChange = {
|
||||
revisions: {
|
||||
sha1: {description: 'patch 1', _number: 1},
|
||||
sha2: {description: 'patch 2', _number: 2},
|
||||
sha3: {description: 'patch 3', _number: 3},
|
||||
},
|
||||
status: 'NEW',
|
||||
messages: [],
|
||||
};
|
||||
const mockRestApi = {
|
||||
getChangeDetail() {
|
||||
return Promise.resolve(actualChange);
|
||||
},
|
||||
};
|
||||
Gerrit.PatchSetBehavior.fetchChangeUpdates(knownChange, mockRestApi)
|
||||
.then(result => {
|
||||
assert.isFalse(result.isLatest);
|
||||
assert.isNotOk(result.newStatus);
|
||||
assert.isFalse(result.newMessages);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('fetchChangeUpdates new status', done => {
|
||||
const knownChange = {
|
||||
revisions: {
|
||||
sha1: {description: 'patch 1', _number: 1},
|
||||
sha2: {description: 'patch 2', _number: 2},
|
||||
},
|
||||
status: 'NEW',
|
||||
messages: [],
|
||||
};
|
||||
const actualChange = {
|
||||
revisions: {
|
||||
sha1: {description: 'patch 1', _number: 1},
|
||||
sha2: {description: 'patch 2', _number: 2},
|
||||
},
|
||||
status: 'MERGED',
|
||||
messages: [],
|
||||
};
|
||||
const mockRestApi = {
|
||||
getChangeDetail() {
|
||||
return Promise.resolve(actualChange);
|
||||
},
|
||||
};
|
||||
Gerrit.PatchSetBehavior.fetchChangeUpdates(knownChange, mockRestApi)
|
||||
.then(result => {
|
||||
assert.isTrue(result.isLatest);
|
||||
assert.equal(result.newStatus, 'MERGED');
|
||||
assert.isFalse(result.newMessages);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('fetchChangeUpdates new messages', done => {
|
||||
const knownChange = {
|
||||
revisions: {
|
||||
sha1: {description: 'patch 1', _number: 1},
|
||||
sha2: {description: 'patch 2', _number: 2},
|
||||
},
|
||||
status: 'NEW',
|
||||
messages: [],
|
||||
};
|
||||
const actualChange = {
|
||||
revisions: {
|
||||
sha1: {description: 'patch 1', _number: 1},
|
||||
sha2: {description: 'patch 2', _number: 2},
|
||||
},
|
||||
status: 'NEW',
|
||||
messages: [{message: 'blah blah'}],
|
||||
};
|
||||
const mockRestApi = {
|
||||
getChangeDetail() {
|
||||
return Promise.resolve(actualChange);
|
||||
},
|
||||
};
|
||||
Gerrit.PatchSetBehavior.fetchChangeUpdates(knownChange, mockRestApi)
|
||||
.then(result => {
|
||||
assert.isTrue(result.isLatest);
|
||||
assert.isNotOk(result.newStatus);
|
||||
assert.isTrue(result.newMessages);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('_computeWipForPatchSets', () => {
|
||||
// Compute patch sets for a given timeline on a change. The initial WIP
|
||||
// property of the change can be true or false. The map of tags by
|
||||
// revision is keyed by patch set number. Each value is a list of change
|
||||
// message tags in the order that they occurred in the timeline. These
|
||||
// indicate actions that modify the WIP property of the change and/or
|
||||
// create new patch sets.
|
||||
//
|
||||
// Returns the actual results with an assertWip method that can be used
|
||||
// to compare against an expected value for a particular patch set.
|
||||
const compute = (initialWip, tagsByRevision) => {
|
||||
const change = {
|
||||
messages: [],
|
||||
work_in_progress: initialWip,
|
||||
};
|
||||
const revs = Object.keys(tagsByRevision).sort((a, b) => a - b);
|
||||
for (const rev of revs) {
|
||||
for (const tag of tagsByRevision[rev]) {
|
||||
change.messages.push({
|
||||
tag,
|
||||
_revision_number: rev,
|
||||
});
|
||||
}
|
||||
}
|
||||
let patchNums = revs.map(rev => { return {num: rev}; });
|
||||
patchNums = Gerrit.PatchSetBehavior._computeWipForPatchSets(
|
||||
change, patchNums);
|
||||
const actualWipsByRevision = {};
|
||||
for (const patchNum of patchNums) {
|
||||
actualWipsByRevision[patchNum.num] = patchNum.wip;
|
||||
}
|
||||
const verifier = {
|
||||
assertWip(revision, expectedWip) {
|
||||
const patchNum = patchNums.find(patchNum => patchNum.num == revision);
|
||||
if (!patchNum) {
|
||||
assert.fail('revision ' + revision + ' not found');
|
||||
}
|
||||
assert.equal(patchNum.wip, expectedWip,
|
||||
'wip state for ' + revision + ' is ' +
|
||||
patchNum.wip + '; expected ' + expectedWip);
|
||||
return verifier;
|
||||
},
|
||||
};
|
||||
return verifier;
|
||||
};
|
||||
|
||||
compute(false, {1: ['upload']}).assertWip(1, false);
|
||||
compute(true, {1: ['upload']}).assertWip(1, true);
|
||||
|
||||
const setWip = 'autogenerated:gerrit:setWorkInProgress';
|
||||
const uploadInWip = 'autogenerated:gerrit:newWipPatchSet';
|
||||
const clearWip = 'autogenerated:gerrit:setReadyForReview';
|
||||
|
||||
compute(false, {
|
||||
1: ['upload', setWip],
|
||||
2: ['upload'],
|
||||
3: ['upload', clearWip],
|
||||
4: ['upload', setWip],
|
||||
}).assertWip(1, false) // Change was created with PS1 ready for review
|
||||
.assertWip(2, true) // PS2 was uploaded during WIP
|
||||
.assertWip(3, false) // PS3 was marked ready for review after upload
|
||||
.assertWip(4, false); // PS4 was uploaded ready for review
|
||||
|
||||
compute(false, {
|
||||
1: [uploadInWip, null, 'addReviewer'],
|
||||
2: ['upload'],
|
||||
3: ['upload', clearWip, setWip],
|
||||
4: ['upload'],
|
||||
5: ['upload', clearWip],
|
||||
6: [uploadInWip],
|
||||
}).assertWip(1, true) // Change was created in WIP
|
||||
.assertWip(2, true) // PS2 was uploaded during WIP
|
||||
.assertWip(3, false) // PS3 was marked ready for review
|
||||
.assertWip(4, true) // PS4 was uploaded during WIP
|
||||
.assertWip(5, false) // PS5 was marked ready for review
|
||||
.assertWip(6, true); // PS6 was uploaded with WIP option
|
||||
});
|
||||
|
||||
test('patchNumEquals', () => {
|
||||
const equals = Gerrit.PatchSetBehavior.patchNumEquals;
|
||||
assert.isFalse(equals('edit', 'PARENT'));
|
||||
assert.isFalse(equals('edit', NaN));
|
||||
assert.isFalse(equals(1, '2'));
|
||||
|
||||
assert.isTrue(equals(1, '1'));
|
||||
assert.isTrue(equals(1, 1));
|
||||
assert.isTrue(equals('edit', 'edit'));
|
||||
assert.isTrue(equals('PARENT', 'PARENT'));
|
||||
});
|
||||
|
||||
test('isMergeParent', () => {
|
||||
const isParent = Gerrit.PatchSetBehavior.isMergeParent;
|
||||
assert.isFalse(isParent(1));
|
||||
assert.isFalse(isParent(4321));
|
||||
assert.isFalse(isParent('52'));
|
||||
assert.isFalse(isParent('edit'));
|
||||
assert.isFalse(isParent('PARENT'));
|
||||
assert.isFalse(isParent(0));
|
||||
|
||||
assert.isTrue(isParent(-23));
|
||||
assert.isTrue(isParent(-1));
|
||||
assert.isTrue(isParent('-42'));
|
||||
});
|
||||
|
||||
test('findEditParentRevision', () => {
|
||||
const findParent = Gerrit.PatchSetBehavior.findEditParentRevision;
|
||||
let revisions = [
|
||||
{_number: 0},
|
||||
{_number: 1},
|
||||
{_number: 2},
|
||||
];
|
||||
assert.strictEqual(findParent(revisions), null);
|
||||
|
||||
revisions = [...revisions, {_number: 'edit', basePatchNum: 3}];
|
||||
assert.strictEqual(findParent(revisions), null);
|
||||
|
||||
revisions = [...revisions, {_number: 3}];
|
||||
assert.deepEqual(findParent(revisions), {_number: 3});
|
||||
});
|
||||
|
||||
test('findEditParentPatchNum', () => {
|
||||
const findNum = Gerrit.PatchSetBehavior.findEditParentPatchNum;
|
||||
let revisions = [
|
||||
{_number: 0},
|
||||
{_number: 1},
|
||||
{_number: 2},
|
||||
];
|
||||
assert.equal(findNum(revisions), -1);
|
||||
|
||||
revisions =
|
||||
[...revisions, {_number: 'edit', basePatchNum: 3}, {_number: 3}];
|
||||
assert.deepEqual(findNum(revisions), 3);
|
||||
});
|
||||
|
||||
test('sortRevisions', () => {
|
||||
const sort = Gerrit.PatchSetBehavior.sortRevisions;
|
||||
const revisions = [
|
||||
{_number: 0},
|
||||
{_number: 2},
|
||||
{_number: 1},
|
||||
];
|
||||
const sorted = [
|
||||
{_number: 2},
|
||||
{_number: 1},
|
||||
{_number: 0},
|
||||
];
|
||||
|
||||
assert.deepEqual(sort(revisions), sorted);
|
||||
|
||||
// Edit patchset should follow directly after its basePatchNum.
|
||||
revisions.push({_number: 'edit', basePatchNum: 2});
|
||||
sorted.unshift({_number: 'edit', basePatchNum: 2});
|
||||
assert.deepEqual(sort(revisions), sorted);
|
||||
|
||||
revisions[0].basePatchNum = 0;
|
||||
const edit = sorted.shift();
|
||||
edit.basePatchNum = 0;
|
||||
// Edit patchset should be at index 2.
|
||||
sorted.splice(2, 0, edit);
|
||||
assert.deepEqual(sort(revisions), sorted);
|
||||
});
|
||||
|
||||
test('getParentIndex', () => {
|
||||
assert.equal(Gerrit.PatchSetBehavior.getParentIndex('-13'), 13);
|
||||
assert.equal(Gerrit.PatchSetBehavior.getParentIndex(-4), 4);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
<!--
|
||||
@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.
|
||||
*/
|
||||
import '../../scripts/util.js';
|
||||
|
||||
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.
|
||||
-->
|
||||
<script src="../../scripts/util.js"></script>
|
||||
<script>
|
||||
(function(window) {
|
||||
'use strict';
|
||||
|
||||
@@ -137,4 +137,3 @@ limitations under the License.
|
||||
};
|
||||
}
|
||||
})(window);
|
||||
</script>
|
||||
|
||||
@@ -15,89 +15,91 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<!-- Polymer included for the html import polyfill. -->
|
||||
<script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/bower_components/web-component-tester/browser.js"></script>
|
||||
<script src="../../test/test-pre-setup.js"></script>
|
||||
<link rel="import" href="../../test/common-test-setup.html"/>
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/components/wct-browser-legacy/browser.js"></script>
|
||||
<script type="module" src="../../test/test-pre-setup.js"></script>
|
||||
<script type="module" src="../../test/common-test-setup.js"></script>
|
||||
<title>gr-path-list-behavior</title>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
|
||||
<link rel="import" href="gr-path-list-behavior.html">
|
||||
<script type="module" src="./gr-path-list-behavior.js"></script>
|
||||
|
||||
<script>
|
||||
suite('gr-path-list-behavior tests', async () => {
|
||||
await readyToTest();
|
||||
test('special sort', () => {
|
||||
const sort = Gerrit.PathListBehavior.specialFilePathCompare;
|
||||
const testFiles = [
|
||||
'/a.h',
|
||||
'/MERGE_LIST',
|
||||
'/a.cpp',
|
||||
'/COMMIT_MSG',
|
||||
'/asdasd',
|
||||
'/mrPeanutbutter.py',
|
||||
];
|
||||
assert.deepEqual(
|
||||
testFiles.sort(sort),
|
||||
[
|
||||
'/COMMIT_MSG',
|
||||
'/MERGE_LIST',
|
||||
'/a.h',
|
||||
'/a.cpp',
|
||||
'/asdasd',
|
||||
'/mrPeanutbutter.py',
|
||||
]);
|
||||
});
|
||||
|
||||
test('file display name', () => {
|
||||
const name = Gerrit.PathListBehavior.computeDisplayPath;
|
||||
assert.equal(name('/foo/bar/baz'), '/foo/bar/baz');
|
||||
assert.equal(name('/foobarbaz'), '/foobarbaz');
|
||||
assert.equal(name('/COMMIT_MSG'), 'Commit message');
|
||||
assert.equal(name('/MERGE_LIST'), 'Merge list');
|
||||
});
|
||||
|
||||
test('isMagicPath', () => {
|
||||
const isMagic = Gerrit.PathListBehavior.isMagicPath;
|
||||
assert.isFalse(isMagic(undefined));
|
||||
assert.isFalse(isMagic('/foo.cc'));
|
||||
assert.isTrue(isMagic('/COMMIT_MSG'));
|
||||
assert.isTrue(isMagic('/MERGE_LIST'));
|
||||
});
|
||||
|
||||
test('truncatePath with long path should add ellipsis', () => {
|
||||
const truncatePath = Gerrit.PathListBehavior.truncatePath;
|
||||
let path = 'level1/level2/level3/level4/file.js';
|
||||
let shortenedPath = truncatePath(path);
|
||||
// The expected path is truncated with an ellipsis.
|
||||
const expectedPath = '\u2026/file.js';
|
||||
assert.equal(shortenedPath, expectedPath);
|
||||
|
||||
path = 'level2/file.js';
|
||||
shortenedPath = truncatePath(path);
|
||||
assert.equal(shortenedPath, expectedPath);
|
||||
});
|
||||
|
||||
test('truncatePath with opt_threshold', () => {
|
||||
const truncatePath = Gerrit.PathListBehavior.truncatePath;
|
||||
let path = 'level1/level2/level3/level4/file.js';
|
||||
let shortenedPath = truncatePath(path, 2);
|
||||
// The expected path is truncated with an ellipsis.
|
||||
const expectedPath = '\u2026/level4/file.js';
|
||||
assert.equal(shortenedPath, expectedPath);
|
||||
|
||||
path = 'level2/file.js';
|
||||
shortenedPath = truncatePath(path, 2);
|
||||
assert.equal(shortenedPath, path);
|
||||
});
|
||||
|
||||
test('truncatePath with short path should not add ellipsis', () => {
|
||||
const truncatePath = Gerrit.PathListBehavior.truncatePath;
|
||||
const path = 'file.js';
|
||||
const expectedPath = 'file.js';
|
||||
const shortenedPath = truncatePath(path);
|
||||
assert.equal(shortenedPath, expectedPath);
|
||||
});
|
||||
<script type="module">
|
||||
import '../../test/test-pre-setup.js';
|
||||
import '../../test/common-test-setup.js';
|
||||
import './gr-path-list-behavior.js';
|
||||
suite('gr-path-list-behavior tests', () => {
|
||||
test('special sort', () => {
|
||||
const sort = Gerrit.PathListBehavior.specialFilePathCompare;
|
||||
const testFiles = [
|
||||
'/a.h',
|
||||
'/MERGE_LIST',
|
||||
'/a.cpp',
|
||||
'/COMMIT_MSG',
|
||||
'/asdasd',
|
||||
'/mrPeanutbutter.py',
|
||||
];
|
||||
assert.deepEqual(
|
||||
testFiles.sort(sort),
|
||||
[
|
||||
'/COMMIT_MSG',
|
||||
'/MERGE_LIST',
|
||||
'/a.h',
|
||||
'/a.cpp',
|
||||
'/asdasd',
|
||||
'/mrPeanutbutter.py',
|
||||
]);
|
||||
});
|
||||
|
||||
test('file display name', () => {
|
||||
const name = Gerrit.PathListBehavior.computeDisplayPath;
|
||||
assert.equal(name('/foo/bar/baz'), '/foo/bar/baz');
|
||||
assert.equal(name('/foobarbaz'), '/foobarbaz');
|
||||
assert.equal(name('/COMMIT_MSG'), 'Commit message');
|
||||
assert.equal(name('/MERGE_LIST'), 'Merge list');
|
||||
});
|
||||
|
||||
test('isMagicPath', () => {
|
||||
const isMagic = Gerrit.PathListBehavior.isMagicPath;
|
||||
assert.isFalse(isMagic(undefined));
|
||||
assert.isFalse(isMagic('/foo.cc'));
|
||||
assert.isTrue(isMagic('/COMMIT_MSG'));
|
||||
assert.isTrue(isMagic('/MERGE_LIST'));
|
||||
});
|
||||
|
||||
test('truncatePath with long path should add ellipsis', () => {
|
||||
const truncatePath = Gerrit.PathListBehavior.truncatePath;
|
||||
let path = 'level1/level2/level3/level4/file.js';
|
||||
let shortenedPath = truncatePath(path);
|
||||
// The expected path is truncated with an ellipsis.
|
||||
const expectedPath = '\u2026/file.js';
|
||||
assert.equal(shortenedPath, expectedPath);
|
||||
|
||||
path = 'level2/file.js';
|
||||
shortenedPath = truncatePath(path);
|
||||
assert.equal(shortenedPath, expectedPath);
|
||||
});
|
||||
|
||||
test('truncatePath with opt_threshold', () => {
|
||||
const truncatePath = Gerrit.PathListBehavior.truncatePath;
|
||||
let path = 'level1/level2/level3/level4/file.js';
|
||||
let shortenedPath = truncatePath(path, 2);
|
||||
// The expected path is truncated with an ellipsis.
|
||||
const expectedPath = '\u2026/level4/file.js';
|
||||
assert.equal(shortenedPath, expectedPath);
|
||||
|
||||
path = 'level2/file.js';
|
||||
shortenedPath = truncatePath(path, 2);
|
||||
assert.equal(shortenedPath, path);
|
||||
});
|
||||
|
||||
test('truncatePath with short path should not add ellipsis', () => {
|
||||
const truncatePath = Gerrit.PathListBehavior.truncatePath;
|
||||
const path = 'file.js';
|
||||
const expectedPath = 'file.js';
|
||||
const shortenedPath = truncatePath(path);
|
||||
assert.equal(shortenedPath, expectedPath);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
<!--
|
||||
@license
|
||||
Copyright (C) 2019 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.
|
||||
-->
|
||||
<script>
|
||||
/**
|
||||
* @license
|
||||
* Copyright (C) 2019 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.
|
||||
*/
|
||||
(function(window) {
|
||||
'use strict';
|
||||
|
||||
@@ -52,4 +51,3 @@ limitations under the License.
|
||||
};
|
||||
}
|
||||
})(window);
|
||||
</script>
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
<!--
|
||||
@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.
|
||||
-->
|
||||
<link rel="import" href="/bower_components/polymer/polymer.html">
|
||||
<link rel="import" href="../../elements/shared/gr-tooltip/gr-tooltip.html">
|
||||
<script src="../../scripts/rootElement.js"></script>
|
||||
|
||||
<script src="gr-tooltip-behavior.js"></script>
|
||||
@@ -14,6 +14,12 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import '../../scripts/bundled-polymer.js';
|
||||
|
||||
import '../../elements/shared/gr-tooltip/gr-tooltip.js';
|
||||
import '../../scripts/rootElement.js';
|
||||
import {flush} from '@polymer/polymer/lib/legacy/polymer.dom.js';
|
||||
|
||||
(function(window) {
|
||||
'use strict';
|
||||
|
||||
@@ -135,7 +141,7 @@
|
||||
_positionTooltip(tooltip) {
|
||||
// This flush is needed for tooltips to be positioned correctly in Firefox
|
||||
// and Safari.
|
||||
Polymer.dom.flush();
|
||||
flush();
|
||||
const rect = this.getBoundingClientRect();
|
||||
const boxRect = tooltip.getBoundingClientRect();
|
||||
const parentRect = tooltip.parentElement.getBoundingClientRect();
|
||||
|
||||
@@ -18,15 +18,20 @@ limitations under the License.
|
||||
|
||||
<title>tooltip-behavior</title>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/bower_components/web-component-tester/browser.js"></script>
|
||||
<script src="../../test/test-pre-setup.js"></script>
|
||||
<link rel="import" href="../../test/common-test-setup.html"/>
|
||||
<link rel="import" href="gr-tooltip-behavior.html">
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/components/wct-browser-legacy/browser.js"></script>
|
||||
<script type="module" src="../../test/test-pre-setup.js"></script>
|
||||
<script type="module" src="../../test/common-test-setup.js"></script>
|
||||
<script type="module" src="./gr-tooltip-behavior.js"></script>
|
||||
|
||||
<script>void(0);</script>
|
||||
<script type="module">
|
||||
import '../../test/test-pre-setup.js';
|
||||
import '../../test/common-test-setup.js';
|
||||
import './gr-tooltip-behavior.js';
|
||||
void(0);
|
||||
</script>
|
||||
|
||||
<test-fixture id="basic">
|
||||
<template>
|
||||
@@ -34,124 +39,127 @@ limitations under the License.
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<script>
|
||||
suite('gr-tooltip-behavior tests', async () => {
|
||||
await readyToTest();
|
||||
let element;
|
||||
let sandbox;
|
||||
<script type="module">
|
||||
import '../../test/test-pre-setup.js';
|
||||
import '../../test/common-test-setup.js';
|
||||
import './gr-tooltip-behavior.js';
|
||||
import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
|
||||
suite('gr-tooltip-behavior tests', () => {
|
||||
let element;
|
||||
let sandbox;
|
||||
|
||||
function makeTooltip(tooltipRect, parentRect) {
|
||||
return {
|
||||
getBoundingClientRect() { return tooltipRect; },
|
||||
updateStyles: sinon.stub(),
|
||||
style: {left: 0, top: 0},
|
||||
parentElement: {
|
||||
getBoundingClientRect() { return parentRect; },
|
||||
},
|
||||
};
|
||||
}
|
||||
function makeTooltip(tooltipRect, parentRect) {
|
||||
return {
|
||||
getBoundingClientRect() { return tooltipRect; },
|
||||
updateStyles: sinon.stub(),
|
||||
style: {left: 0, top: 0},
|
||||
parentElement: {
|
||||
getBoundingClientRect() { return parentRect; },
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
suiteSetup(() => {
|
||||
// Define a Polymer element that uses this behavior.
|
||||
Polymer({
|
||||
is: 'tooltip-behavior-element',
|
||||
behaviors: [Gerrit.TooltipBehavior],
|
||||
});
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
sandbox = sinon.sandbox.create();
|
||||
element = fixture('basic');
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
test('normal position', () => {
|
||||
sandbox.stub(element, 'getBoundingClientRect', () => {
|
||||
return {top: 100, left: 100, width: 200};
|
||||
});
|
||||
const tooltip = makeTooltip(
|
||||
{height: 30, width: 50},
|
||||
{top: 0, left: 0, width: 1000});
|
||||
|
||||
element._positionTooltip(tooltip);
|
||||
assert.isFalse(tooltip.updateStyles.called);
|
||||
assert.equal(tooltip.style.left, '175px');
|
||||
assert.equal(tooltip.style.top, '100px');
|
||||
});
|
||||
|
||||
test('left side position', () => {
|
||||
sandbox.stub(element, 'getBoundingClientRect', () => {
|
||||
return {top: 100, left: 10, width: 50};
|
||||
});
|
||||
const tooltip = makeTooltip(
|
||||
{height: 30, width: 120},
|
||||
{top: 0, left: 0, width: 1000});
|
||||
|
||||
element._positionTooltip(tooltip);
|
||||
assert.isTrue(tooltip.updateStyles.called);
|
||||
const offset = tooltip.updateStyles
|
||||
.lastCall.args[0]['--gr-tooltip-arrow-center-offset'];
|
||||
assert.isBelow(parseFloat(offset.replace(/px$/, '')), 0);
|
||||
assert.equal(tooltip.style.left, '0px');
|
||||
assert.equal(tooltip.style.top, '100px');
|
||||
});
|
||||
|
||||
test('right side position', () => {
|
||||
sandbox.stub(element, 'getBoundingClientRect', () => {
|
||||
return {top: 100, left: 950, width: 50};
|
||||
});
|
||||
const tooltip = makeTooltip(
|
||||
{height: 30, width: 120},
|
||||
{top: 0, left: 0, width: 1000});
|
||||
|
||||
element._positionTooltip(tooltip);
|
||||
assert.isTrue(tooltip.updateStyles.called);
|
||||
const offset = tooltip.updateStyles
|
||||
.lastCall.args[0]['--gr-tooltip-arrow-center-offset'];
|
||||
assert.isAbove(parseFloat(offset.replace(/px$/, '')), 0);
|
||||
assert.equal(tooltip.style.left, '915px');
|
||||
assert.equal(tooltip.style.top, '100px');
|
||||
});
|
||||
|
||||
test('position to bottom', () => {
|
||||
sandbox.stub(element, 'getBoundingClientRect', () => {
|
||||
return {top: 100, left: 950, width: 50, height: 50};
|
||||
});
|
||||
const tooltip = makeTooltip(
|
||||
{height: 30, width: 120},
|
||||
{top: 0, left: 0, width: 1000});
|
||||
|
||||
element.positionBelow = true;
|
||||
element._positionTooltip(tooltip);
|
||||
assert.isTrue(tooltip.updateStyles.called);
|
||||
const offset = tooltip.updateStyles
|
||||
.lastCall.args[0]['--gr-tooltip-arrow-center-offset'];
|
||||
assert.isAbove(parseFloat(offset.replace(/px$/, '')), 0);
|
||||
assert.equal(tooltip.style.left, '915px');
|
||||
assert.equal(tooltip.style.top, '157.2px');
|
||||
});
|
||||
|
||||
test('hides tooltip when detached', () => {
|
||||
sandbox.stub(element, '_handleHideTooltip');
|
||||
element.remove();
|
||||
flushAsynchronousOperations();
|
||||
assert.isTrue(element._handleHideTooltip.called);
|
||||
});
|
||||
|
||||
test('sets up listeners when has-tooltip is changed', () => {
|
||||
const addListenerStub = sandbox.stub(element, 'addEventListener');
|
||||
element.hasTooltip = true;
|
||||
assert.isTrue(addListenerStub.called);
|
||||
});
|
||||
|
||||
test('clean up listeners when has-tooltip changed to false', () => {
|
||||
const removeListenerStub = sandbox.stub(element, 'removeEventListener');
|
||||
element.hasTooltip = true;
|
||||
element.hasTooltip = false;
|
||||
assert.isTrue(removeListenerStub.called);
|
||||
suiteSetup(() => {
|
||||
// Define a Polymer element that uses this behavior.
|
||||
Polymer({
|
||||
is: 'tooltip-behavior-element',
|
||||
behaviors: [Gerrit.TooltipBehavior],
|
||||
});
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
sandbox = sinon.sandbox.create();
|
||||
element = fixture('basic');
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
test('normal position', () => {
|
||||
sandbox.stub(element, 'getBoundingClientRect', () => {
|
||||
return {top: 100, left: 100, width: 200};
|
||||
});
|
||||
const tooltip = makeTooltip(
|
||||
{height: 30, width: 50},
|
||||
{top: 0, left: 0, width: 1000});
|
||||
|
||||
element._positionTooltip(tooltip);
|
||||
assert.isFalse(tooltip.updateStyles.called);
|
||||
assert.equal(tooltip.style.left, '175px');
|
||||
assert.equal(tooltip.style.top, '100px');
|
||||
});
|
||||
|
||||
test('left side position', () => {
|
||||
sandbox.stub(element, 'getBoundingClientRect', () => {
|
||||
return {top: 100, left: 10, width: 50};
|
||||
});
|
||||
const tooltip = makeTooltip(
|
||||
{height: 30, width: 120},
|
||||
{top: 0, left: 0, width: 1000});
|
||||
|
||||
element._positionTooltip(tooltip);
|
||||
assert.isTrue(tooltip.updateStyles.called);
|
||||
const offset = tooltip.updateStyles
|
||||
.lastCall.args[0]['--gr-tooltip-arrow-center-offset'];
|
||||
assert.isBelow(parseFloat(offset.replace(/px$/, '')), 0);
|
||||
assert.equal(tooltip.style.left, '0px');
|
||||
assert.equal(tooltip.style.top, '100px');
|
||||
});
|
||||
|
||||
test('right side position', () => {
|
||||
sandbox.stub(element, 'getBoundingClientRect', () => {
|
||||
return {top: 100, left: 950, width: 50};
|
||||
});
|
||||
const tooltip = makeTooltip(
|
||||
{height: 30, width: 120},
|
||||
{top: 0, left: 0, width: 1000});
|
||||
|
||||
element._positionTooltip(tooltip);
|
||||
assert.isTrue(tooltip.updateStyles.called);
|
||||
const offset = tooltip.updateStyles
|
||||
.lastCall.args[0]['--gr-tooltip-arrow-center-offset'];
|
||||
assert.isAbove(parseFloat(offset.replace(/px$/, '')), 0);
|
||||
assert.equal(tooltip.style.left, '915px');
|
||||
assert.equal(tooltip.style.top, '100px');
|
||||
});
|
||||
|
||||
test('position to bottom', () => {
|
||||
sandbox.stub(element, 'getBoundingClientRect', () => {
|
||||
return {top: 100, left: 950, width: 50, height: 50};
|
||||
});
|
||||
const tooltip = makeTooltip(
|
||||
{height: 30, width: 120},
|
||||
{top: 0, left: 0, width: 1000});
|
||||
|
||||
element.positionBelow = true;
|
||||
element._positionTooltip(tooltip);
|
||||
assert.isTrue(tooltip.updateStyles.called);
|
||||
const offset = tooltip.updateStyles
|
||||
.lastCall.args[0]['--gr-tooltip-arrow-center-offset'];
|
||||
assert.isAbove(parseFloat(offset.replace(/px$/, '')), 0);
|
||||
assert.equal(tooltip.style.left, '915px');
|
||||
assert.equal(tooltip.style.top, '157.2px');
|
||||
});
|
||||
|
||||
test('hides tooltip when detached', () => {
|
||||
sandbox.stub(element, '_handleHideTooltip');
|
||||
element.remove();
|
||||
flushAsynchronousOperations();
|
||||
assert.isTrue(element._handleHideTooltip.called);
|
||||
});
|
||||
|
||||
test('sets up listeners when has-tooltip is changed', () => {
|
||||
const addListenerStub = sandbox.stub(element, 'addEventListener');
|
||||
element.hasTooltip = true;
|
||||
assert.isTrue(addListenerStub.called);
|
||||
});
|
||||
|
||||
test('clean up listeners when has-tooltip changed to false', () => {
|
||||
const removeListenerStub = sandbox.stub(element, 'removeEventListener');
|
||||
element.hasTooltip = true;
|
||||
element.hasTooltip = false;
|
||||
assert.isTrue(removeListenerStub.called);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
<!--
|
||||
@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.
|
||||
-->
|
||||
<script>
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
(function(window) {
|
||||
'use strict';
|
||||
|
||||
@@ -73,4 +72,3 @@ limitations under the License.
|
||||
};
|
||||
}
|
||||
})(window);
|
||||
</script>
|
||||
|
||||
@@ -18,15 +18,20 @@ limitations under the License.
|
||||
|
||||
<title>gr-url-encoding-behavior</title>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/bower_components/web-component-tester/browser.js"></script>
|
||||
<script src="../../test/test-pre-setup.js"></script>
|
||||
<link rel="import" href="../../test/common-test-setup.html"/>
|
||||
<link rel="import" href="gr-url-encoding-behavior.html">
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/components/wct-browser-legacy/browser.js"></script>
|
||||
<script type="module" src="../../test/test-pre-setup.js"></script>
|
||||
<script type="module" src="../../test/common-test-setup.js"></script>
|
||||
<script type="module" src="./gr-url-encoding-behavior.js"></script>
|
||||
|
||||
<script>void(0);</script>
|
||||
<script type="module">
|
||||
import '../../test/test-pre-setup.js';
|
||||
import '../../test/common-test-setup.js';
|
||||
import './gr-url-encoding-behavior.js';
|
||||
void(0);
|
||||
</script>
|
||||
|
||||
<test-fixture id="basic">
|
||||
<template>
|
||||
@@ -34,62 +39,65 @@ limitations under the License.
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<script>
|
||||
suite('gr-url-encoding-behavior tests', async () => {
|
||||
await readyToTest();
|
||||
let element;
|
||||
let sandbox;
|
||||
<script type="module">
|
||||
import '../../test/test-pre-setup.js';
|
||||
import '../../test/common-test-setup.js';
|
||||
import './gr-url-encoding-behavior.js';
|
||||
import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
|
||||
suite('gr-url-encoding-behavior tests', () => {
|
||||
let element;
|
||||
let sandbox;
|
||||
|
||||
suiteSetup(() => {
|
||||
// Define a Polymer element that uses this behavior.
|
||||
Polymer({
|
||||
is: 'test-element',
|
||||
behaviors: [Gerrit.URLEncodingBehavior],
|
||||
});
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
sandbox = sinon.sandbox.create();
|
||||
element = fixture('basic');
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
suite('encodeURL', () => {
|
||||
test('double encodes', () => {
|
||||
assert.equal(element.encodeURL('abc?123'), 'abc%253F123');
|
||||
assert.equal(element.encodeURL('def/ghi'), 'def%252Fghi');
|
||||
assert.equal(element.encodeURL('jkl'), 'jkl');
|
||||
assert.equal(element.encodeURL(''), '');
|
||||
});
|
||||
|
||||
test('does not convert colons', () => {
|
||||
assert.equal(element.encodeURL('mno:pqr'), 'mno:pqr');
|
||||
});
|
||||
|
||||
test('converts spaces to +', () => {
|
||||
assert.equal(element.encodeURL('words with spaces'), 'words+with+spaces');
|
||||
});
|
||||
|
||||
test('does not convert slashes when configured', () => {
|
||||
assert.equal(element.encodeURL('stu/vwx', true), 'stu/vwx');
|
||||
});
|
||||
|
||||
test('does not convert slashes when configured', () => {
|
||||
assert.equal(element.encodeURL('stu/vwx', true), 'stu/vwx');
|
||||
});
|
||||
});
|
||||
|
||||
suite('singleDecodeUrl', () => {
|
||||
test('single decodes', () => {
|
||||
assert.equal(element.singleDecodeURL('abc%3Fdef'), 'abc?def');
|
||||
});
|
||||
|
||||
test('converts + to space', () => {
|
||||
assert.equal(element.singleDecodeURL('ghi+jkl'), 'ghi jkl');
|
||||
});
|
||||
suiteSetup(() => {
|
||||
// Define a Polymer element that uses this behavior.
|
||||
Polymer({
|
||||
is: 'test-element',
|
||||
behaviors: [Gerrit.URLEncodingBehavior],
|
||||
});
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
sandbox = sinon.sandbox.create();
|
||||
element = fixture('basic');
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
suite('encodeURL', () => {
|
||||
test('double encodes', () => {
|
||||
assert.equal(element.encodeURL('abc?123'), 'abc%253F123');
|
||||
assert.equal(element.encodeURL('def/ghi'), 'def%252Fghi');
|
||||
assert.equal(element.encodeURL('jkl'), 'jkl');
|
||||
assert.equal(element.encodeURL(''), '');
|
||||
});
|
||||
|
||||
test('does not convert colons', () => {
|
||||
assert.equal(element.encodeURL('mno:pqr'), 'mno:pqr');
|
||||
});
|
||||
|
||||
test('converts spaces to +', () => {
|
||||
assert.equal(element.encodeURL('words with spaces'), 'words+with+spaces');
|
||||
});
|
||||
|
||||
test('does not convert slashes when configured', () => {
|
||||
assert.equal(element.encodeURL('stu/vwx', true), 'stu/vwx');
|
||||
});
|
||||
|
||||
test('does not convert slashes when configured', () => {
|
||||
assert.equal(element.encodeURL('stu/vwx', true), 'stu/vwx');
|
||||
});
|
||||
});
|
||||
|
||||
suite('singleDecodeUrl', () => {
|
||||
test('single decodes', () => {
|
||||
assert.equal(element.singleDecodeURL('abc%3Fdef'), 'abc?def');
|
||||
});
|
||||
|
||||
test('converts + to space', () => {
|
||||
assert.equal(element.singleDecodeURL('ghi+jkl'), 'ghi jkl');
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
<!--
|
||||
@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.
|
||||
-->
|
||||
|
||||
<!--
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
/*
|
||||
|
||||
How to Add a Keyboard Shortcut
|
||||
==============================
|
||||
@@ -95,12 +94,17 @@ by gr-app, and actually implemented by gr-comment-thread.
|
||||
|
||||
NOTE: doc-only shortcuts will not be customizable in the same way that other
|
||||
shortcuts are.
|
||||
-->
|
||||
<link rel="import" href="/bower_components/polymer/polymer.html">
|
||||
<link rel="import" href="/bower_components/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
|
||||
<script src="../../types/polymer-behaviors.js"></script>
|
||||
*/
|
||||
/*
|
||||
FIXME(polymer-modulizer): the above comments were extracted
|
||||
from HTML and may be out of place here. Review them and
|
||||
then delete this comment!
|
||||
*/
|
||||
import '../../scripts/bundled-polymer.js';
|
||||
|
||||
<script>
|
||||
import {IronA11yKeysBehavior} from '@polymer/iron-a11y-keys-behavior/iron-a11y-keys-behavior.js';
|
||||
import '../../types/polymer-behaviors.js';
|
||||
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
|
||||
(function(window) {
|
||||
'use strict';
|
||||
|
||||
@@ -307,7 +311,7 @@ shortcuts are.
|
||||
|
||||
/** @return {!(Event|PolymerDomApi|PolymerEventApi)} */
|
||||
const getKeyboardEvent = function(e) {
|
||||
e = Polymer.dom(e.detail ? e.detail.keyboardEvent : e);
|
||||
e = dom(e.detail ? e.detail.keyboardEvent : e);
|
||||
// When e is a keyboardEvent, e.event is not null.
|
||||
if (e.event) { e = e.event; }
|
||||
return e;
|
||||
@@ -482,7 +486,7 @@ shortcuts are.
|
||||
|
||||
/** @polymerBehavior Gerrit.KeyboardShortcutBehavior*/
|
||||
Gerrit.KeyboardShortcutBehavior = [
|
||||
Polymer.IronA11yKeysBehavior,
|
||||
IronA11yKeysBehavior,
|
||||
{
|
||||
// Exports for convenience. Note: Closure compiler crashes when
|
||||
// object-shorthand syntax is used here.
|
||||
@@ -518,7 +522,7 @@ shortcuts are.
|
||||
|
||||
shouldSuppressKeyboardShortcut(e) {
|
||||
e = getKeyboardEvent(e);
|
||||
const tagName = Polymer.dom(e).rootTarget.tagName;
|
||||
const tagName = dom(e).rootTarget.tagName;
|
||||
if (tagName === 'INPUT' || tagName === 'TEXTAREA' ||
|
||||
(e.keyCode === 13 && tagName === 'A')) {
|
||||
// Suppress shortcuts if the key is 'enter' and target is an anchor.
|
||||
@@ -542,7 +546,7 @@ shortcuts are.
|
||||
},
|
||||
|
||||
getRootTarget(e) {
|
||||
return Polymer.dom(getKeyboardEvent(e)).rootTarget;
|
||||
return dom(getKeyboardEvent(e)).rootTarget;
|
||||
},
|
||||
|
||||
bindShortcut(shortcut, ...bindings) {
|
||||
@@ -671,4 +675,3 @@ shortcuts are.
|
||||
};
|
||||
}
|
||||
})(window);
|
||||
</script>
|
||||
|
||||
@@ -19,13 +19,13 @@ limitations under the License.
|
||||
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
|
||||
<title>keyboard-shortcut-behavior</title>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/bower_components/web-component-tester/browser.js"></script>
|
||||
<script src="../../test/test-pre-setup.js"></script>
|
||||
<link rel="import" href="../../test/common-test-setup.html"/>
|
||||
<link rel="import" href="keyboard-shortcut-behavior.html">
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/components/wct-browser-legacy/browser.js"></script>
|
||||
<script type="module" src="../../test/test-pre-setup.js"></script>
|
||||
<script type="module" src="../../test/common-test-setup.js"></script>
|
||||
<script type="module" src="./keyboard-shortcut-behavior.js"></script>
|
||||
|
||||
<test-fixture id="basic">
|
||||
<template>
|
||||
@@ -41,403 +41,406 @@ limitations under the License.
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<script>
|
||||
suite('keyboard-shortcut-behavior tests', async () => {
|
||||
await readyToTest();
|
||||
const kb = window.Gerrit.KeyboardShortcutBinder;
|
||||
<script type="module">
|
||||
import '../../test/test-pre-setup.js';
|
||||
import '../../test/common-test-setup.js';
|
||||
import './keyboard-shortcut-behavior.js';
|
||||
import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
|
||||
suite('keyboard-shortcut-behavior tests', () => {
|
||||
const kb = window.Gerrit.KeyboardShortcutBinder;
|
||||
|
||||
let element;
|
||||
let overlay;
|
||||
let sandbox;
|
||||
let element;
|
||||
let overlay;
|
||||
let sandbox;
|
||||
|
||||
suiteSetup(() => {
|
||||
// Define a Polymer element that uses this behavior.
|
||||
Polymer({
|
||||
is: 'test-element',
|
||||
behaviors: [Gerrit.KeyboardShortcutBehavior],
|
||||
keyBindings: {
|
||||
k: '_handleKey',
|
||||
enter: '_handleKey',
|
||||
},
|
||||
_handleKey() {},
|
||||
});
|
||||
suiteSetup(() => {
|
||||
// Define a Polymer element that uses this behavior.
|
||||
Polymer({
|
||||
is: 'test-element',
|
||||
behaviors: [Gerrit.KeyboardShortcutBehavior],
|
||||
keyBindings: {
|
||||
k: '_handleKey',
|
||||
enter: '_handleKey',
|
||||
},
|
||||
_handleKey() {},
|
||||
});
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
element = fixture('basic');
|
||||
overlay = fixture('within-overlay');
|
||||
sandbox = sinon.sandbox.create();
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
suite('ShortcutManager', () => {
|
||||
test('bindings management', () => {
|
||||
const mgr = new kb.ShortcutManager();
|
||||
const {NEXT_FILE} = kb.Shortcut;
|
||||
|
||||
assert.isUndefined(mgr.getBindingsForShortcut(NEXT_FILE));
|
||||
mgr.bindShortcut(NEXT_FILE, ']', '}', 'right');
|
||||
assert.deepEqual(
|
||||
mgr.getBindingsForShortcut(NEXT_FILE),
|
||||
[']', '}', 'right']);
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
element = fixture('basic');
|
||||
overlay = fixture('within-overlay');
|
||||
sandbox = sinon.sandbox.create();
|
||||
});
|
||||
suite('binding descriptions', () => {
|
||||
function mapToObject(m) {
|
||||
const o = {};
|
||||
m.forEach((v, k) => o[k] = v);
|
||||
return o;
|
||||
}
|
||||
|
||||
teardown(() => {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
suite('ShortcutManager', () => {
|
||||
test('bindings management', () => {
|
||||
test('single combo description', () => {
|
||||
const mgr = new kb.ShortcutManager();
|
||||
const {NEXT_FILE} = kb.Shortcut;
|
||||
|
||||
assert.isUndefined(mgr.getBindingsForShortcut(NEXT_FILE));
|
||||
mgr.bindShortcut(NEXT_FILE, ']', '}', 'right');
|
||||
assert.deepEqual(mgr.describeBinding('a'), ['a']);
|
||||
assert.deepEqual(mgr.describeBinding('a:keyup'), ['a']);
|
||||
assert.deepEqual(mgr.describeBinding('ctrl+a'), ['Ctrl', 'a']);
|
||||
assert.deepEqual(
|
||||
mgr.getBindingsForShortcut(NEXT_FILE),
|
||||
[']', '}', 'right']);
|
||||
mgr.describeBinding('ctrl+shift+up:keyup'),
|
||||
['Ctrl', 'Shift', '↑']);
|
||||
});
|
||||
|
||||
suite('binding descriptions', () => {
|
||||
function mapToObject(m) {
|
||||
const o = {};
|
||||
m.forEach((v, k) => o[k] = v);
|
||||
return o;
|
||||
}
|
||||
test('combo set description', () => {
|
||||
const {GO_KEY, DOC_ONLY, ShortcutManager} = kb;
|
||||
const {GO_TO_OPENED_CHANGES, NEXT_FILE, PREV_FILE} = kb.Shortcut;
|
||||
|
||||
test('single combo description', () => {
|
||||
const mgr = new kb.ShortcutManager();
|
||||
assert.deepEqual(mgr.describeBinding('a'), ['a']);
|
||||
assert.deepEqual(mgr.describeBinding('a:keyup'), ['a']);
|
||||
assert.deepEqual(mgr.describeBinding('ctrl+a'), ['Ctrl', 'a']);
|
||||
assert.deepEqual(
|
||||
mgr.describeBinding('ctrl+shift+up:keyup'),
|
||||
['Ctrl', 'Shift', '↑']);
|
||||
const mgr = new ShortcutManager();
|
||||
assert.isNull(mgr.describeBindings(NEXT_FILE));
|
||||
|
||||
mgr.bindShortcut(GO_TO_OPENED_CHANGES, GO_KEY, 'o');
|
||||
assert.deepEqual(
|
||||
mgr.describeBindings(GO_TO_OPENED_CHANGES),
|
||||
[['g', 'o']]);
|
||||
|
||||
mgr.bindShortcut(NEXT_FILE, DOC_ONLY, ']', 'ctrl+shift+right:keyup');
|
||||
assert.deepEqual(
|
||||
mgr.describeBindings(NEXT_FILE),
|
||||
[[']'], ['Ctrl', 'Shift', '→']]);
|
||||
|
||||
mgr.bindShortcut(PREV_FILE, '[');
|
||||
assert.deepEqual(mgr.describeBindings(PREV_FILE), [['[']]);
|
||||
});
|
||||
|
||||
test('combo set description width', () => {
|
||||
const mgr = new kb.ShortcutManager();
|
||||
assert.strictEqual(mgr.comboSetDisplayWidth([['u']]), 1);
|
||||
assert.strictEqual(mgr.comboSetDisplayWidth([['g', 'o']]), 2);
|
||||
assert.strictEqual(mgr.comboSetDisplayWidth([['Shift', 'r']]), 6);
|
||||
assert.strictEqual(mgr.comboSetDisplayWidth([['x'], ['y']]), 4);
|
||||
assert.strictEqual(
|
||||
mgr.comboSetDisplayWidth([['x'], ['y'], ['Shift', 'z']]),
|
||||
12);
|
||||
});
|
||||
|
||||
test('distribute shortcut help', () => {
|
||||
const mgr = new kb.ShortcutManager();
|
||||
assert.deepEqual(mgr.distributeBindingDesc([['o']]), [[['o']]]);
|
||||
assert.deepEqual(
|
||||
mgr.distributeBindingDesc([['g', 'o']]),
|
||||
[[['g', 'o']]]);
|
||||
assert.deepEqual(
|
||||
mgr.distributeBindingDesc([['ctrl', 'shift', 'meta', 'enter']]),
|
||||
[[['ctrl', 'shift', 'meta', 'enter']]]);
|
||||
assert.deepEqual(
|
||||
mgr.distributeBindingDesc([
|
||||
['ctrl', 'shift', 'meta', 'enter'],
|
||||
['o'],
|
||||
]),
|
||||
[
|
||||
[['ctrl', 'shift', 'meta', 'enter']],
|
||||
[['o']],
|
||||
]);
|
||||
assert.deepEqual(
|
||||
mgr.distributeBindingDesc([
|
||||
['ctrl', 'enter'],
|
||||
['meta', 'enter'],
|
||||
['ctrl', 's'],
|
||||
['meta', 's'],
|
||||
]),
|
||||
[
|
||||
[['ctrl', 'enter'], ['meta', 'enter']],
|
||||
[['ctrl', 's'], ['meta', 's']],
|
||||
]);
|
||||
});
|
||||
|
||||
test('active shortcuts by section', () => {
|
||||
const {NEXT_FILE, NEXT_LINE, GO_TO_OPENED_CHANGES, SEARCH} =
|
||||
kb.Shortcut;
|
||||
const {DIFFS, EVERYWHERE, NAVIGATION} = kb.ShortcutSection;
|
||||
|
||||
const mgr = new kb.ShortcutManager();
|
||||
mgr.bindShortcut(NEXT_FILE, ']');
|
||||
mgr.bindShortcut(NEXT_LINE, 'j');
|
||||
mgr.bindShortcut(GO_TO_OPENED_CHANGES, 'g+o');
|
||||
mgr.bindShortcut(SEARCH, '/');
|
||||
|
||||
assert.deepEqual(
|
||||
mapToObject(mgr.activeShortcutsBySection()),
|
||||
{});
|
||||
|
||||
mgr.attachHost({
|
||||
keyboardShortcuts() {
|
||||
return {
|
||||
[NEXT_FILE]: null,
|
||||
};
|
||||
},
|
||||
});
|
||||
assert.deepEqual(
|
||||
mapToObject(mgr.activeShortcutsBySection()),
|
||||
{
|
||||
[NAVIGATION]: [
|
||||
{shortcut: NEXT_FILE, text: 'Go to next file'},
|
||||
],
|
||||
});
|
||||
|
||||
test('combo set description', () => {
|
||||
const {GO_KEY, DOC_ONLY, ShortcutManager} = kb;
|
||||
const {GO_TO_OPENED_CHANGES, NEXT_FILE, PREV_FILE} = kb.Shortcut;
|
||||
|
||||
const mgr = new ShortcutManager();
|
||||
assert.isNull(mgr.describeBindings(NEXT_FILE));
|
||||
|
||||
mgr.bindShortcut(GO_TO_OPENED_CHANGES, GO_KEY, 'o');
|
||||
assert.deepEqual(
|
||||
mgr.describeBindings(GO_TO_OPENED_CHANGES),
|
||||
[['g', 'o']]);
|
||||
|
||||
mgr.bindShortcut(NEXT_FILE, DOC_ONLY, ']', 'ctrl+shift+right:keyup');
|
||||
assert.deepEqual(
|
||||
mgr.describeBindings(NEXT_FILE),
|
||||
[[']'], ['Ctrl', 'Shift', '→']]);
|
||||
|
||||
mgr.bindShortcut(PREV_FILE, '[');
|
||||
assert.deepEqual(mgr.describeBindings(PREV_FILE), [['[']]);
|
||||
mgr.attachHost({
|
||||
keyboardShortcuts() {
|
||||
return {
|
||||
[NEXT_LINE]: null,
|
||||
};
|
||||
},
|
||||
});
|
||||
assert.deepEqual(
|
||||
mapToObject(mgr.activeShortcutsBySection()),
|
||||
{
|
||||
[DIFFS]: [
|
||||
{shortcut: NEXT_LINE, text: 'Go to next line'},
|
||||
],
|
||||
[NAVIGATION]: [
|
||||
{shortcut: NEXT_FILE, text: 'Go to next file'},
|
||||
],
|
||||
});
|
||||
|
||||
test('combo set description width', () => {
|
||||
const mgr = new kb.ShortcutManager();
|
||||
assert.strictEqual(mgr.comboSetDisplayWidth([['u']]), 1);
|
||||
assert.strictEqual(mgr.comboSetDisplayWidth([['g', 'o']]), 2);
|
||||
assert.strictEqual(mgr.comboSetDisplayWidth([['Shift', 'r']]), 6);
|
||||
assert.strictEqual(mgr.comboSetDisplayWidth([['x'], ['y']]), 4);
|
||||
assert.strictEqual(
|
||||
mgr.comboSetDisplayWidth([['x'], ['y'], ['Shift', 'z']]),
|
||||
12);
|
||||
mgr.attachHost({
|
||||
keyboardShortcuts() {
|
||||
return {
|
||||
[SEARCH]: null,
|
||||
[GO_TO_OPENED_CHANGES]: null,
|
||||
};
|
||||
},
|
||||
});
|
||||
assert.deepEqual(
|
||||
mapToObject(mgr.activeShortcutsBySection()),
|
||||
{
|
||||
[DIFFS]: [
|
||||
{shortcut: NEXT_LINE, text: 'Go to next line'},
|
||||
],
|
||||
[EVERYWHERE]: [
|
||||
{shortcut: SEARCH, text: 'Search'},
|
||||
{
|
||||
shortcut: GO_TO_OPENED_CHANGES,
|
||||
text: 'Go to Opened Changes',
|
||||
},
|
||||
],
|
||||
[NAVIGATION]: [
|
||||
{shortcut: NEXT_FILE, text: 'Go to next file'},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
test('distribute shortcut help', () => {
|
||||
const mgr = new kb.ShortcutManager();
|
||||
assert.deepEqual(mgr.distributeBindingDesc([['o']]), [[['o']]]);
|
||||
assert.deepEqual(
|
||||
mgr.distributeBindingDesc([['g', 'o']]),
|
||||
[[['g', 'o']]]);
|
||||
assert.deepEqual(
|
||||
mgr.distributeBindingDesc([['ctrl', 'shift', 'meta', 'enter']]),
|
||||
[[['ctrl', 'shift', 'meta', 'enter']]]);
|
||||
assert.deepEqual(
|
||||
mgr.distributeBindingDesc([
|
||||
['ctrl', 'shift', 'meta', 'enter'],
|
||||
['o'],
|
||||
]),
|
||||
[
|
||||
[['ctrl', 'shift', 'meta', 'enter']],
|
||||
[['o']],
|
||||
]);
|
||||
assert.deepEqual(
|
||||
mgr.distributeBindingDesc([
|
||||
['ctrl', 'enter'],
|
||||
['meta', 'enter'],
|
||||
['ctrl', 's'],
|
||||
['meta', 's'],
|
||||
]),
|
||||
[
|
||||
[['ctrl', 'enter'], ['meta', 'enter']],
|
||||
[['ctrl', 's'], ['meta', 's']],
|
||||
]);
|
||||
test('directory view', () => {
|
||||
const {
|
||||
NEXT_FILE, NEXT_LINE, GO_TO_OPENED_CHANGES, SEARCH,
|
||||
SAVE_COMMENT,
|
||||
} = kb.Shortcut;
|
||||
const {DIFFS, EVERYWHERE, NAVIGATION} = kb.ShortcutSection;
|
||||
const {GO_KEY, ShortcutManager} = kb;
|
||||
|
||||
const mgr = new ShortcutManager();
|
||||
mgr.bindShortcut(NEXT_FILE, ']');
|
||||
mgr.bindShortcut(NEXT_LINE, 'j');
|
||||
mgr.bindShortcut(GO_TO_OPENED_CHANGES, GO_KEY, 'o');
|
||||
mgr.bindShortcut(SEARCH, '/');
|
||||
mgr.bindShortcut(
|
||||
SAVE_COMMENT, 'ctrl+enter', 'meta+enter', 'ctrl+s', 'meta+s');
|
||||
|
||||
assert.deepEqual(mapToObject(mgr.directoryView()), {});
|
||||
|
||||
mgr.attachHost({
|
||||
keyboardShortcuts() {
|
||||
return {
|
||||
[GO_TO_OPENED_CHANGES]: null,
|
||||
[NEXT_FILE]: null,
|
||||
[NEXT_LINE]: null,
|
||||
[SAVE_COMMENT]: null,
|
||||
[SEARCH]: null,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
test('active shortcuts by section', () => {
|
||||
const {NEXT_FILE, NEXT_LINE, GO_TO_OPENED_CHANGES, SEARCH} =
|
||||
kb.Shortcut;
|
||||
const {DIFFS, EVERYWHERE, NAVIGATION} = kb.ShortcutSection;
|
||||
|
||||
const mgr = new kb.ShortcutManager();
|
||||
mgr.bindShortcut(NEXT_FILE, ']');
|
||||
mgr.bindShortcut(NEXT_LINE, 'j');
|
||||
mgr.bindShortcut(GO_TO_OPENED_CHANGES, 'g+o');
|
||||
mgr.bindShortcut(SEARCH, '/');
|
||||
|
||||
assert.deepEqual(
|
||||
mapToObject(mgr.activeShortcutsBySection()),
|
||||
{});
|
||||
|
||||
mgr.attachHost({
|
||||
keyboardShortcuts() {
|
||||
return {
|
||||
[NEXT_FILE]: null,
|
||||
};
|
||||
},
|
||||
});
|
||||
assert.deepEqual(
|
||||
mapToObject(mgr.activeShortcutsBySection()),
|
||||
{
|
||||
[NAVIGATION]: [
|
||||
{shortcut: NEXT_FILE, text: 'Go to next file'},
|
||||
],
|
||||
});
|
||||
|
||||
mgr.attachHost({
|
||||
keyboardShortcuts() {
|
||||
return {
|
||||
[NEXT_LINE]: null,
|
||||
};
|
||||
},
|
||||
});
|
||||
assert.deepEqual(
|
||||
mapToObject(mgr.activeShortcutsBySection()),
|
||||
{
|
||||
[DIFFS]: [
|
||||
{shortcut: NEXT_LINE, text: 'Go to next line'},
|
||||
],
|
||||
[NAVIGATION]: [
|
||||
{shortcut: NEXT_FILE, text: 'Go to next file'},
|
||||
],
|
||||
});
|
||||
|
||||
mgr.attachHost({
|
||||
keyboardShortcuts() {
|
||||
return {
|
||||
[SEARCH]: null,
|
||||
[GO_TO_OPENED_CHANGES]: null,
|
||||
};
|
||||
},
|
||||
});
|
||||
assert.deepEqual(
|
||||
mapToObject(mgr.activeShortcutsBySection()),
|
||||
{
|
||||
[DIFFS]: [
|
||||
{shortcut: NEXT_LINE, text: 'Go to next line'},
|
||||
],
|
||||
[EVERYWHERE]: [
|
||||
{shortcut: SEARCH, text: 'Search'},
|
||||
{
|
||||
shortcut: GO_TO_OPENED_CHANGES,
|
||||
text: 'Go to Opened Changes',
|
||||
},
|
||||
],
|
||||
[NAVIGATION]: [
|
||||
{shortcut: NEXT_FILE, text: 'Go to next file'},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
test('directory view', () => {
|
||||
const {
|
||||
NEXT_FILE, NEXT_LINE, GO_TO_OPENED_CHANGES, SEARCH,
|
||||
SAVE_COMMENT,
|
||||
} = kb.Shortcut;
|
||||
const {DIFFS, EVERYWHERE, NAVIGATION} = kb.ShortcutSection;
|
||||
const {GO_KEY, ShortcutManager} = kb;
|
||||
|
||||
const mgr = new ShortcutManager();
|
||||
mgr.bindShortcut(NEXT_FILE, ']');
|
||||
mgr.bindShortcut(NEXT_LINE, 'j');
|
||||
mgr.bindShortcut(GO_TO_OPENED_CHANGES, GO_KEY, 'o');
|
||||
mgr.bindShortcut(SEARCH, '/');
|
||||
mgr.bindShortcut(
|
||||
SAVE_COMMENT, 'ctrl+enter', 'meta+enter', 'ctrl+s', 'meta+s');
|
||||
|
||||
assert.deepEqual(mapToObject(mgr.directoryView()), {});
|
||||
|
||||
mgr.attachHost({
|
||||
keyboardShortcuts() {
|
||||
return {
|
||||
[GO_TO_OPENED_CHANGES]: null,
|
||||
[NEXT_FILE]: null,
|
||||
[NEXT_LINE]: null,
|
||||
[SAVE_COMMENT]: null,
|
||||
[SEARCH]: null,
|
||||
};
|
||||
},
|
||||
});
|
||||
assert.deepEqual(
|
||||
mapToObject(mgr.directoryView()),
|
||||
{
|
||||
[DIFFS]: [
|
||||
{binding: [['j']], text: 'Go to next line'},
|
||||
{
|
||||
binding: [['Ctrl', 'Enter'], ['Meta', 'Enter']],
|
||||
text: 'Save comment',
|
||||
},
|
||||
{
|
||||
binding: [['Ctrl', 's'], ['Meta', 's']],
|
||||
text: 'Save comment',
|
||||
},
|
||||
],
|
||||
[EVERYWHERE]: [
|
||||
{binding: [['/']], text: 'Search'},
|
||||
{binding: [['g', 'o']], text: 'Go to Opened Changes'},
|
||||
],
|
||||
[NAVIGATION]: [
|
||||
{binding: [[']']], text: 'Go to next file'},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('doesn’t block kb shortcuts for non-whitelisted els', done => {
|
||||
const divEl = document.createElement('div');
|
||||
element.appendChild(divEl);
|
||||
element._handleKey = e => {
|
||||
assert.isFalse(element.shouldSuppressKeyboardShortcut(e));
|
||||
done();
|
||||
};
|
||||
MockInteractions.keyDownOn(divEl, 75, null, 'k');
|
||||
});
|
||||
|
||||
test('blocks kb shortcuts for input els', done => {
|
||||
const inputEl = document.createElement('input');
|
||||
element.appendChild(inputEl);
|
||||
element._handleKey = e => {
|
||||
assert.isTrue(element.shouldSuppressKeyboardShortcut(e));
|
||||
done();
|
||||
};
|
||||
MockInteractions.keyDownOn(inputEl, 75, null, 'k');
|
||||
});
|
||||
|
||||
test('blocks kb shortcuts for textarea els', done => {
|
||||
const textareaEl = document.createElement('textarea');
|
||||
element.appendChild(textareaEl);
|
||||
element._handleKey = e => {
|
||||
assert.isTrue(element.shouldSuppressKeyboardShortcut(e));
|
||||
done();
|
||||
};
|
||||
MockInteractions.keyDownOn(textareaEl, 75, null, 'k');
|
||||
});
|
||||
|
||||
test('blocks kb shortcuts for anything in a gr-overlay', done => {
|
||||
const divEl = document.createElement('div');
|
||||
const element = overlay.querySelector('test-element');
|
||||
element.appendChild(divEl);
|
||||
element._handleKey = e => {
|
||||
assert.isTrue(element.shouldSuppressKeyboardShortcut(e));
|
||||
done();
|
||||
};
|
||||
MockInteractions.keyDownOn(divEl, 75, null, 'k');
|
||||
});
|
||||
|
||||
test('blocks enter shortcut on an anchor', done => {
|
||||
const anchorEl = document.createElement('a');
|
||||
const element = overlay.querySelector('test-element');
|
||||
element.appendChild(anchorEl);
|
||||
element._handleKey = e => {
|
||||
assert.isTrue(element.shouldSuppressKeyboardShortcut(e));
|
||||
done();
|
||||
};
|
||||
MockInteractions.keyDownOn(anchorEl, 13, null, 'enter');
|
||||
});
|
||||
|
||||
test('modifierPressed returns accurate values', () => {
|
||||
const spy = sandbox.spy(element, 'modifierPressed');
|
||||
element._handleKey = e => {
|
||||
element.modifierPressed(e);
|
||||
};
|
||||
MockInteractions.keyDownOn(element, 75, 'shift', 'k');
|
||||
assert.isTrue(spy.lastCall.returnValue);
|
||||
MockInteractions.keyDownOn(element, 75, null, 'k');
|
||||
assert.isFalse(spy.lastCall.returnValue);
|
||||
MockInteractions.keyDownOn(element, 75, 'ctrl', 'k');
|
||||
assert.isTrue(spy.lastCall.returnValue);
|
||||
MockInteractions.keyDownOn(element, 75, null, 'k');
|
||||
assert.isFalse(spy.lastCall.returnValue);
|
||||
MockInteractions.keyDownOn(element, 75, 'meta', 'k');
|
||||
assert.isTrue(spy.lastCall.returnValue);
|
||||
MockInteractions.keyDownOn(element, 75, null, 'k');
|
||||
assert.isFalse(spy.lastCall.returnValue);
|
||||
MockInteractions.keyDownOn(element, 75, 'alt', 'k');
|
||||
assert.isTrue(spy.lastCall.returnValue);
|
||||
});
|
||||
|
||||
test('isModifierPressed returns accurate value', () => {
|
||||
const spy = sandbox.spy(element, 'isModifierPressed');
|
||||
element._handleKey = e => {
|
||||
element.isModifierPressed(e, 'shiftKey');
|
||||
};
|
||||
MockInteractions.keyDownOn(element, 75, 'shift', 'k');
|
||||
assert.isTrue(spy.lastCall.returnValue);
|
||||
MockInteractions.keyDownOn(element, 75, null, 'k');
|
||||
assert.isFalse(spy.lastCall.returnValue);
|
||||
MockInteractions.keyDownOn(element, 75, 'ctrl', 'k');
|
||||
assert.isFalse(spy.lastCall.returnValue);
|
||||
MockInteractions.keyDownOn(element, 75, null, 'k');
|
||||
assert.isFalse(spy.lastCall.returnValue);
|
||||
MockInteractions.keyDownOn(element, 75, 'meta', 'k');
|
||||
assert.isFalse(spy.lastCall.returnValue);
|
||||
MockInteractions.keyDownOn(element, 75, null, 'k');
|
||||
assert.isFalse(spy.lastCall.returnValue);
|
||||
MockInteractions.keyDownOn(element, 75, 'alt', 'k');
|
||||
assert.isFalse(spy.lastCall.returnValue);
|
||||
});
|
||||
|
||||
suite('GO_KEY timing', () => {
|
||||
let handlerStub;
|
||||
|
||||
setup(() => {
|
||||
element._shortcut_go_table.set('a', '_handleA');
|
||||
handlerStub = element._handleA = sinon.stub();
|
||||
sandbox.stub(Date, 'now').returns(10000);
|
||||
});
|
||||
|
||||
test('success', () => {
|
||||
const e = {detail: {key: 'a'}, preventDefault: () => {}};
|
||||
sandbox.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
|
||||
element._shortcut_go_key_last_pressed = 9000;
|
||||
element._handleGoAction(e);
|
||||
assert.isTrue(handlerStub.calledOnce);
|
||||
assert.strictEqual(handlerStub.lastCall.args[0], e);
|
||||
});
|
||||
|
||||
test('go key not pressed', () => {
|
||||
const e = {detail: {key: 'a'}, preventDefault: () => {}};
|
||||
sandbox.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
|
||||
element._shortcut_go_key_last_pressed = null;
|
||||
element._handleGoAction(e);
|
||||
assert.isFalse(handlerStub.called);
|
||||
});
|
||||
|
||||
test('go key pressed too long ago', () => {
|
||||
const e = {detail: {key: 'a'}, preventDefault: () => {}};
|
||||
sandbox.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
|
||||
element._shortcut_go_key_last_pressed = 3000;
|
||||
element._handleGoAction(e);
|
||||
assert.isFalse(handlerStub.called);
|
||||
});
|
||||
|
||||
test('should suppress', () => {
|
||||
const e = {detail: {key: 'a'}, preventDefault: () => {}};
|
||||
sandbox.stub(element, 'shouldSuppressKeyboardShortcut').returns(true);
|
||||
element._shortcut_go_key_last_pressed = 9000;
|
||||
element._handleGoAction(e);
|
||||
assert.isFalse(handlerStub.called);
|
||||
});
|
||||
|
||||
test('unrecognized key', () => {
|
||||
const e = {detail: {key: 'f'}, preventDefault: () => {}};
|
||||
sandbox.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
|
||||
element._shortcut_go_key_last_pressed = 9000;
|
||||
element._handleGoAction(e);
|
||||
assert.isFalse(handlerStub.called);
|
||||
assert.deepEqual(
|
||||
mapToObject(mgr.directoryView()),
|
||||
{
|
||||
[DIFFS]: [
|
||||
{binding: [['j']], text: 'Go to next line'},
|
||||
{
|
||||
binding: [['Ctrl', 'Enter'], ['Meta', 'Enter']],
|
||||
text: 'Save comment',
|
||||
},
|
||||
{
|
||||
binding: [['Ctrl', 's'], ['Meta', 's']],
|
||||
text: 'Save comment',
|
||||
},
|
||||
],
|
||||
[EVERYWHERE]: [
|
||||
{binding: [['/']], text: 'Search'},
|
||||
{binding: [['g', 'o']], text: 'Go to Opened Changes'},
|
||||
],
|
||||
[NAVIGATION]: [
|
||||
{binding: [[']']], text: 'Go to next file'},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('doesn’t block kb shortcuts for non-whitelisted els', done => {
|
||||
const divEl = document.createElement('div');
|
||||
element.appendChild(divEl);
|
||||
element._handleKey = e => {
|
||||
assert.isFalse(element.shouldSuppressKeyboardShortcut(e));
|
||||
done();
|
||||
};
|
||||
MockInteractions.keyDownOn(divEl, 75, null, 'k');
|
||||
});
|
||||
|
||||
test('blocks kb shortcuts for input els', done => {
|
||||
const inputEl = document.createElement('input');
|
||||
element.appendChild(inputEl);
|
||||
element._handleKey = e => {
|
||||
assert.isTrue(element.shouldSuppressKeyboardShortcut(e));
|
||||
done();
|
||||
};
|
||||
MockInteractions.keyDownOn(inputEl, 75, null, 'k');
|
||||
});
|
||||
|
||||
test('blocks kb shortcuts for textarea els', done => {
|
||||
const textareaEl = document.createElement('textarea');
|
||||
element.appendChild(textareaEl);
|
||||
element._handleKey = e => {
|
||||
assert.isTrue(element.shouldSuppressKeyboardShortcut(e));
|
||||
done();
|
||||
};
|
||||
MockInteractions.keyDownOn(textareaEl, 75, null, 'k');
|
||||
});
|
||||
|
||||
test('blocks kb shortcuts for anything in a gr-overlay', done => {
|
||||
const divEl = document.createElement('div');
|
||||
const element = overlay.querySelector('test-element');
|
||||
element.appendChild(divEl);
|
||||
element._handleKey = e => {
|
||||
assert.isTrue(element.shouldSuppressKeyboardShortcut(e));
|
||||
done();
|
||||
};
|
||||
MockInteractions.keyDownOn(divEl, 75, null, 'k');
|
||||
});
|
||||
|
||||
test('blocks enter shortcut on an anchor', done => {
|
||||
const anchorEl = document.createElement('a');
|
||||
const element = overlay.querySelector('test-element');
|
||||
element.appendChild(anchorEl);
|
||||
element._handleKey = e => {
|
||||
assert.isTrue(element.shouldSuppressKeyboardShortcut(e));
|
||||
done();
|
||||
};
|
||||
MockInteractions.keyDownOn(anchorEl, 13, null, 'enter');
|
||||
});
|
||||
|
||||
test('modifierPressed returns accurate values', () => {
|
||||
const spy = sandbox.spy(element, 'modifierPressed');
|
||||
element._handleKey = e => {
|
||||
element.modifierPressed(e);
|
||||
};
|
||||
MockInteractions.keyDownOn(element, 75, 'shift', 'k');
|
||||
assert.isTrue(spy.lastCall.returnValue);
|
||||
MockInteractions.keyDownOn(element, 75, null, 'k');
|
||||
assert.isFalse(spy.lastCall.returnValue);
|
||||
MockInteractions.keyDownOn(element, 75, 'ctrl', 'k');
|
||||
assert.isTrue(spy.lastCall.returnValue);
|
||||
MockInteractions.keyDownOn(element, 75, null, 'k');
|
||||
assert.isFalse(spy.lastCall.returnValue);
|
||||
MockInteractions.keyDownOn(element, 75, 'meta', 'k');
|
||||
assert.isTrue(spy.lastCall.returnValue);
|
||||
MockInteractions.keyDownOn(element, 75, null, 'k');
|
||||
assert.isFalse(spy.lastCall.returnValue);
|
||||
MockInteractions.keyDownOn(element, 75, 'alt', 'k');
|
||||
assert.isTrue(spy.lastCall.returnValue);
|
||||
});
|
||||
|
||||
test('isModifierPressed returns accurate value', () => {
|
||||
const spy = sandbox.spy(element, 'isModifierPressed');
|
||||
element._handleKey = e => {
|
||||
element.isModifierPressed(e, 'shiftKey');
|
||||
};
|
||||
MockInteractions.keyDownOn(element, 75, 'shift', 'k');
|
||||
assert.isTrue(spy.lastCall.returnValue);
|
||||
MockInteractions.keyDownOn(element, 75, null, 'k');
|
||||
assert.isFalse(spy.lastCall.returnValue);
|
||||
MockInteractions.keyDownOn(element, 75, 'ctrl', 'k');
|
||||
assert.isFalse(spy.lastCall.returnValue);
|
||||
MockInteractions.keyDownOn(element, 75, null, 'k');
|
||||
assert.isFalse(spy.lastCall.returnValue);
|
||||
MockInteractions.keyDownOn(element, 75, 'meta', 'k');
|
||||
assert.isFalse(spy.lastCall.returnValue);
|
||||
MockInteractions.keyDownOn(element, 75, null, 'k');
|
||||
assert.isFalse(spy.lastCall.returnValue);
|
||||
MockInteractions.keyDownOn(element, 75, 'alt', 'k');
|
||||
assert.isFalse(spy.lastCall.returnValue);
|
||||
});
|
||||
|
||||
suite('GO_KEY timing', () => {
|
||||
let handlerStub;
|
||||
|
||||
setup(() => {
|
||||
element._shortcut_go_table.set('a', '_handleA');
|
||||
handlerStub = element._handleA = sinon.stub();
|
||||
sandbox.stub(Date, 'now').returns(10000);
|
||||
});
|
||||
|
||||
test('success', () => {
|
||||
const e = {detail: {key: 'a'}, preventDefault: () => {}};
|
||||
sandbox.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
|
||||
element._shortcut_go_key_last_pressed = 9000;
|
||||
element._handleGoAction(e);
|
||||
assert.isTrue(handlerStub.calledOnce);
|
||||
assert.strictEqual(handlerStub.lastCall.args[0], e);
|
||||
});
|
||||
|
||||
test('go key not pressed', () => {
|
||||
const e = {detail: {key: 'a'}, preventDefault: () => {}};
|
||||
sandbox.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
|
||||
element._shortcut_go_key_last_pressed = null;
|
||||
element._handleGoAction(e);
|
||||
assert.isFalse(handlerStub.called);
|
||||
});
|
||||
|
||||
test('go key pressed too long ago', () => {
|
||||
const e = {detail: {key: 'a'}, preventDefault: () => {}};
|
||||
sandbox.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
|
||||
element._shortcut_go_key_last_pressed = 3000;
|
||||
element._handleGoAction(e);
|
||||
assert.isFalse(handlerStub.called);
|
||||
});
|
||||
|
||||
test('should suppress', () => {
|
||||
const e = {detail: {key: 'a'}, preventDefault: () => {}};
|
||||
sandbox.stub(element, 'shouldSuppressKeyboardShortcut').returns(true);
|
||||
element._shortcut_go_key_last_pressed = 9000;
|
||||
element._handleGoAction(e);
|
||||
assert.isFalse(handlerStub.called);
|
||||
});
|
||||
|
||||
test('unrecognized key', () => {
|
||||
const e = {detail: {key: 'f'}, preventDefault: () => {}};
|
||||
sandbox.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
|
||||
element._shortcut_go_key_last_pressed = 9000;
|
||||
element._handleGoAction(e);
|
||||
assert.isFalse(handlerStub.called);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
<!--
|
||||
@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.
|
||||
*/
|
||||
import '../../scripts/bundled-polymer.js';
|
||||
|
||||
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.
|
||||
-->
|
||||
<link rel="import" href="/bower_components/polymer/polymer.html">
|
||||
<link rel="import" href="../base-url-behavior/base-url-behavior.html">
|
||||
<script>
|
||||
import '../base-url-behavior/base-url-behavior.js';
|
||||
(function(window) {
|
||||
'use strict';
|
||||
|
||||
@@ -198,4 +198,3 @@ limitations under the License.
|
||||
};
|
||||
}
|
||||
})(window);
|
||||
</script>
|
||||
|
||||
@@ -19,19 +19,23 @@ limitations under the License.
|
||||
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
|
||||
<title>keyboard-shortcut-behavior</title>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/bower_components/web-component-tester/browser.js"></script>
|
||||
<script src="../../test/test-pre-setup.js"></script>
|
||||
<link rel="import" href="../../test/common-test-setup.html"/>
|
||||
<script>
|
||||
/** @type {string} */
|
||||
window.CANONICAL_PATH = '/r';
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/components/wct-browser-legacy/browser.js"></script>
|
||||
<script type="module" src="../../test/test-pre-setup.js"></script>
|
||||
<script type="module" src="../../test/common-test-setup.js"></script>
|
||||
<script type="module">
|
||||
import '../../test/test-pre-setup.js';
|
||||
import '../../test/common-test-setup.js';
|
||||
import '../base-url-behavior/base-url-behavior.js';
|
||||
import './rest-client-behavior.js';
|
||||
/** @type {string} */
|
||||
window.CANONICAL_PATH = '/r';
|
||||
</script>
|
||||
|
||||
<link rel="import" href="../base-url-behavior/base-url-behavior.html">
|
||||
<link rel="import" href="rest-client-behavior.html">
|
||||
<script type="module" src="../base-url-behavior/base-url-behavior.js"></script>
|
||||
<script type="module" src="./rest-client-behavior.js"></script>
|
||||
|
||||
<test-fixture id="basic">
|
||||
<template>
|
||||
@@ -47,191 +51,195 @@ limitations under the License.
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<script>
|
||||
suite('rest-client-behavior tests', async () => {
|
||||
await readyToTest();
|
||||
let element;
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
let overlay;
|
||||
<script type="module">
|
||||
import '../../test/test-pre-setup.js';
|
||||
import '../../test/common-test-setup.js';
|
||||
import '../base-url-behavior/base-url-behavior.js';
|
||||
import './rest-client-behavior.js';
|
||||
import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
|
||||
suite('rest-client-behavior tests', () => {
|
||||
let element;
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
let overlay;
|
||||
|
||||
suiteSetup(() => {
|
||||
// Define a Polymer element that uses this behavior.
|
||||
Polymer({
|
||||
is: 'test-element',
|
||||
behaviors: [
|
||||
Gerrit.BaseUrlBehavior,
|
||||
Gerrit.RESTClientBehavior,
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
element = fixture('basic');
|
||||
overlay = fixture('within-overlay');
|
||||
});
|
||||
|
||||
test('changeBaseURL', () => {
|
||||
assert.deepEqual(
|
||||
element.changeBaseURL('test/project', '1', '2'),
|
||||
'/r/changes/test%2Fproject~1/revisions/2'
|
||||
);
|
||||
});
|
||||
|
||||
test('changePath', () => {
|
||||
assert.deepEqual(element.changePath('1'), '/r/c/1');
|
||||
});
|
||||
|
||||
test('Open status', () => {
|
||||
const change = {
|
||||
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
||||
revisions: {
|
||||
rev1: {_number: 1},
|
||||
},
|
||||
current_revision: 'rev1',
|
||||
status: 'NEW',
|
||||
labels: {},
|
||||
mergeable: true,
|
||||
};
|
||||
let statuses = element.changeStatuses(change);
|
||||
const statusString = element.changeStatusString(change);
|
||||
assert.deepEqual(statuses, []);
|
||||
assert.equal(statusString, '');
|
||||
|
||||
change.submittable = false;
|
||||
statuses = element.changeStatuses(change,
|
||||
{includeDerived: true});
|
||||
assert.deepEqual(statuses, ['Active']);
|
||||
|
||||
// With no missing labels but no submitEnabled option.
|
||||
change.submittable = true;
|
||||
statuses = element.changeStatuses(change,
|
||||
{includeDerived: true});
|
||||
assert.deepEqual(statuses, ['Active']);
|
||||
|
||||
// Without missing labels and enabled submit
|
||||
statuses = element.changeStatuses(change,
|
||||
{includeDerived: true, submitEnabled: true});
|
||||
assert.deepEqual(statuses, ['Ready to submit']);
|
||||
|
||||
change.mergeable = false;
|
||||
change.submittable = true;
|
||||
statuses = element.changeStatuses(change,
|
||||
{includeDerived: true});
|
||||
assert.deepEqual(statuses, ['Merge Conflict']);
|
||||
|
||||
delete change.mergeable;
|
||||
change.submittable = true;
|
||||
statuses = element.changeStatuses(change,
|
||||
{includeDerived: true, mergeable: true, submitEnabled: true});
|
||||
assert.deepEqual(statuses, ['Ready to submit']);
|
||||
|
||||
change.submittable = true;
|
||||
statuses = element.changeStatuses(change,
|
||||
{includeDerived: true, mergeable: false});
|
||||
assert.deepEqual(statuses, ['Merge Conflict']);
|
||||
});
|
||||
|
||||
test('Merge conflict', () => {
|
||||
const change = {
|
||||
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
||||
revisions: {
|
||||
rev1: {_number: 1},
|
||||
},
|
||||
current_revision: 'rev1',
|
||||
status: 'NEW',
|
||||
labels: {},
|
||||
mergeable: false,
|
||||
};
|
||||
const statuses = element.changeStatuses(change);
|
||||
const statusString = element.changeStatusString(change);
|
||||
assert.deepEqual(statuses, ['Merge Conflict']);
|
||||
assert.equal(statusString, 'Merge Conflict');
|
||||
});
|
||||
|
||||
test('mergeable prop undefined', () => {
|
||||
const change = {
|
||||
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
||||
revisions: {
|
||||
rev1: {_number: 1},
|
||||
},
|
||||
current_revision: 'rev1',
|
||||
status: 'NEW',
|
||||
labels: {},
|
||||
};
|
||||
const statuses = element.changeStatuses(change);
|
||||
const statusString = element.changeStatusString(change);
|
||||
assert.deepEqual(statuses, []);
|
||||
assert.equal(statusString, '');
|
||||
});
|
||||
|
||||
test('Merged status', () => {
|
||||
const change = {
|
||||
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
||||
revisions: {
|
||||
rev1: {_number: 1},
|
||||
},
|
||||
current_revision: 'rev1',
|
||||
status: 'MERGED',
|
||||
labels: {},
|
||||
};
|
||||
const statuses = element.changeStatuses(change);
|
||||
const statusString = element.changeStatusString(change);
|
||||
assert.deepEqual(statuses, ['Merged']);
|
||||
assert.equal(statusString, 'Merged');
|
||||
});
|
||||
|
||||
test('Abandoned status', () => {
|
||||
const change = {
|
||||
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
||||
revisions: {
|
||||
rev1: {_number: 1},
|
||||
},
|
||||
current_revision: 'rev1',
|
||||
status: 'ABANDONED',
|
||||
labels: {},
|
||||
};
|
||||
const statuses = element.changeStatuses(change);
|
||||
const statusString = element.changeStatusString(change);
|
||||
assert.deepEqual(statuses, ['Abandoned']);
|
||||
assert.equal(statusString, 'Abandoned');
|
||||
});
|
||||
|
||||
test('Open status with private and wip', () => {
|
||||
const change = {
|
||||
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
||||
revisions: {
|
||||
rev1: {_number: 1},
|
||||
},
|
||||
current_revision: 'rev1',
|
||||
status: 'NEW',
|
||||
is_private: true,
|
||||
work_in_progress: true,
|
||||
labels: {},
|
||||
mergeable: true,
|
||||
};
|
||||
const statuses = element.changeStatuses(change);
|
||||
const statusString = element.changeStatusString(change);
|
||||
assert.deepEqual(statuses, ['WIP', 'Private']);
|
||||
assert.equal(statusString, 'WIP, Private');
|
||||
});
|
||||
|
||||
test('Merge conflict with private and wip', () => {
|
||||
const change = {
|
||||
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
||||
revisions: {
|
||||
rev1: {_number: 1},
|
||||
},
|
||||
current_revision: 'rev1',
|
||||
status: 'NEW',
|
||||
is_private: true,
|
||||
work_in_progress: true,
|
||||
labels: {},
|
||||
mergeable: false,
|
||||
};
|
||||
const statuses = element.changeStatuses(change);
|
||||
const statusString = element.changeStatusString(change);
|
||||
assert.deepEqual(statuses, ['Merge Conflict', 'WIP', 'Private']);
|
||||
assert.equal(statusString, 'Merge Conflict, WIP, Private');
|
||||
suiteSetup(() => {
|
||||
// Define a Polymer element that uses this behavior.
|
||||
Polymer({
|
||||
is: 'test-element',
|
||||
behaviors: [
|
||||
Gerrit.BaseUrlBehavior,
|
||||
Gerrit.RESTClientBehavior,
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
element = fixture('basic');
|
||||
overlay = fixture('within-overlay');
|
||||
});
|
||||
|
||||
test('changeBaseURL', () => {
|
||||
assert.deepEqual(
|
||||
element.changeBaseURL('test/project', '1', '2'),
|
||||
'/r/changes/test%2Fproject~1/revisions/2'
|
||||
);
|
||||
});
|
||||
|
||||
test('changePath', () => {
|
||||
assert.deepEqual(element.changePath('1'), '/r/c/1');
|
||||
});
|
||||
|
||||
test('Open status', () => {
|
||||
const change = {
|
||||
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
||||
revisions: {
|
||||
rev1: {_number: 1},
|
||||
},
|
||||
current_revision: 'rev1',
|
||||
status: 'NEW',
|
||||
labels: {},
|
||||
mergeable: true,
|
||||
};
|
||||
let statuses = element.changeStatuses(change);
|
||||
const statusString = element.changeStatusString(change);
|
||||
assert.deepEqual(statuses, []);
|
||||
assert.equal(statusString, '');
|
||||
|
||||
change.submittable = false;
|
||||
statuses = element.changeStatuses(change,
|
||||
{includeDerived: true});
|
||||
assert.deepEqual(statuses, ['Active']);
|
||||
|
||||
// With no missing labels but no submitEnabled option.
|
||||
change.submittable = true;
|
||||
statuses = element.changeStatuses(change,
|
||||
{includeDerived: true});
|
||||
assert.deepEqual(statuses, ['Active']);
|
||||
|
||||
// Without missing labels and enabled submit
|
||||
statuses = element.changeStatuses(change,
|
||||
{includeDerived: true, submitEnabled: true});
|
||||
assert.deepEqual(statuses, ['Ready to submit']);
|
||||
|
||||
change.mergeable = false;
|
||||
change.submittable = true;
|
||||
statuses = element.changeStatuses(change,
|
||||
{includeDerived: true});
|
||||
assert.deepEqual(statuses, ['Merge Conflict']);
|
||||
|
||||
delete change.mergeable;
|
||||
change.submittable = true;
|
||||
statuses = element.changeStatuses(change,
|
||||
{includeDerived: true, mergeable: true, submitEnabled: true});
|
||||
assert.deepEqual(statuses, ['Ready to submit']);
|
||||
|
||||
change.submittable = true;
|
||||
statuses = element.changeStatuses(change,
|
||||
{includeDerived: true, mergeable: false});
|
||||
assert.deepEqual(statuses, ['Merge Conflict']);
|
||||
});
|
||||
|
||||
test('Merge conflict', () => {
|
||||
const change = {
|
||||
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
||||
revisions: {
|
||||
rev1: {_number: 1},
|
||||
},
|
||||
current_revision: 'rev1',
|
||||
status: 'NEW',
|
||||
labels: {},
|
||||
mergeable: false,
|
||||
};
|
||||
const statuses = element.changeStatuses(change);
|
||||
const statusString = element.changeStatusString(change);
|
||||
assert.deepEqual(statuses, ['Merge Conflict']);
|
||||
assert.equal(statusString, 'Merge Conflict');
|
||||
});
|
||||
|
||||
test('mergeable prop undefined', () => {
|
||||
const change = {
|
||||
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
||||
revisions: {
|
||||
rev1: {_number: 1},
|
||||
},
|
||||
current_revision: 'rev1',
|
||||
status: 'NEW',
|
||||
labels: {},
|
||||
};
|
||||
const statuses = element.changeStatuses(change);
|
||||
const statusString = element.changeStatusString(change);
|
||||
assert.deepEqual(statuses, []);
|
||||
assert.equal(statusString, '');
|
||||
});
|
||||
|
||||
test('Merged status', () => {
|
||||
const change = {
|
||||
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
||||
revisions: {
|
||||
rev1: {_number: 1},
|
||||
},
|
||||
current_revision: 'rev1',
|
||||
status: 'MERGED',
|
||||
labels: {},
|
||||
};
|
||||
const statuses = element.changeStatuses(change);
|
||||
const statusString = element.changeStatusString(change);
|
||||
assert.deepEqual(statuses, ['Merged']);
|
||||
assert.equal(statusString, 'Merged');
|
||||
});
|
||||
|
||||
test('Abandoned status', () => {
|
||||
const change = {
|
||||
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
||||
revisions: {
|
||||
rev1: {_number: 1},
|
||||
},
|
||||
current_revision: 'rev1',
|
||||
status: 'ABANDONED',
|
||||
labels: {},
|
||||
};
|
||||
const statuses = element.changeStatuses(change);
|
||||
const statusString = element.changeStatusString(change);
|
||||
assert.deepEqual(statuses, ['Abandoned']);
|
||||
assert.equal(statusString, 'Abandoned');
|
||||
});
|
||||
|
||||
test('Open status with private and wip', () => {
|
||||
const change = {
|
||||
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
||||
revisions: {
|
||||
rev1: {_number: 1},
|
||||
},
|
||||
current_revision: 'rev1',
|
||||
status: 'NEW',
|
||||
is_private: true,
|
||||
work_in_progress: true,
|
||||
labels: {},
|
||||
mergeable: true,
|
||||
};
|
||||
const statuses = element.changeStatuses(change);
|
||||
const statusString = element.changeStatusString(change);
|
||||
assert.deepEqual(statuses, ['WIP', 'Private']);
|
||||
assert.equal(statusString, 'WIP, Private');
|
||||
});
|
||||
|
||||
test('Merge conflict with private and wip', () => {
|
||||
const change = {
|
||||
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
||||
revisions: {
|
||||
rev1: {_number: 1},
|
||||
},
|
||||
current_revision: 'rev1',
|
||||
status: 'NEW',
|
||||
is_private: true,
|
||||
work_in_progress: true,
|
||||
labels: {},
|
||||
mergeable: false,
|
||||
};
|
||||
const statuses = element.changeStatuses(change);
|
||||
const statusString = element.changeStatusString(change);
|
||||
assert.deepEqual(statuses, ['Merge Conflict', 'WIP', 'Private']);
|
||||
assert.equal(statusString, 'Merge Conflict, WIP, Private');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
<!--
|
||||
@license
|
||||
Copyright (C) 2018 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.
|
||||
-->
|
||||
<script>
|
||||
/**
|
||||
* @license
|
||||
* Copyright (C) 2018 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.
|
||||
*/
|
||||
(function(window) {
|
||||
'use strict';
|
||||
|
||||
@@ -74,4 +73,3 @@ limitations under the License.
|
||||
throw new Error(`Refused to bind value as ${type}: ${value}`);
|
||||
};
|
||||
})(window);
|
||||
</script>
|
||||
|
||||
@@ -18,15 +18,20 @@ limitations under the License.
|
||||
|
||||
<title>safe-types-behavior</title>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/bower_components/web-component-tester/browser.js"></script>
|
||||
<script src="../../test/test-pre-setup.js"></script>
|
||||
<link rel="import" href="../../test/common-test-setup.html"/>
|
||||
<link rel="import" href="safe-types-behavior.html">
|
||||
<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/components/wct-browser-legacy/browser.js"></script>
|
||||
<script type="module" src="../../test/test-pre-setup.js"></script>
|
||||
<script type="module" src="../../test/common-test-setup.js"></script>
|
||||
<script type="module" src="./safe-types-behavior.js"></script>
|
||||
|
||||
<script>void(0);</script>
|
||||
<script type="module">
|
||||
import '../../test/test-pre-setup.js';
|
||||
import '../../test/common-test-setup.js';
|
||||
import './safe-types-behavior.js';
|
||||
void(0);
|
||||
</script>
|
||||
|
||||
<test-fixture id="basic">
|
||||
<template>
|
||||
@@ -34,92 +39,95 @@ limitations under the License.
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<script>
|
||||
suite('gr-tooltip-behavior tests', async () => {
|
||||
await readyToTest();
|
||||
let element;
|
||||
let sandbox;
|
||||
<script type="module">
|
||||
import '../../test/test-pre-setup.js';
|
||||
import '../../test/common-test-setup.js';
|
||||
import './safe-types-behavior.js';
|
||||
import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
|
||||
suite('gr-tooltip-behavior tests', () => {
|
||||
let element;
|
||||
let sandbox;
|
||||
|
||||
suiteSetup(() => {
|
||||
Polymer({
|
||||
is: 'safe-types-element',
|
||||
behaviors: [Gerrit.SafeTypes],
|
||||
});
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
sandbox = sinon.sandbox.create();
|
||||
element = fixture('basic');
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
test('SafeUrl accepts valid urls', () => {
|
||||
function accepts(url) {
|
||||
const safeUrl = new element.SafeUrl(url);
|
||||
assert.isOk(safeUrl);
|
||||
assert.equal(url, safeUrl.asString());
|
||||
}
|
||||
accepts('http://www.google.com/');
|
||||
accepts('https://www.google.com/');
|
||||
accepts('HtTpS://www.google.com/');
|
||||
accepts('//www.google.com/');
|
||||
accepts('/c/1234/file/path.html@45');
|
||||
accepts('#hash-url');
|
||||
accepts('mailto:name@example.com');
|
||||
});
|
||||
|
||||
test('SafeUrl rejects invalid urls', () => {
|
||||
function rejects(url) {
|
||||
assert.throws(() => { new element.SafeUrl(url); });
|
||||
}
|
||||
rejects('javascript://alert("evil");');
|
||||
rejects('ftp:example.com');
|
||||
rejects('data:text/html,scary business');
|
||||
});
|
||||
|
||||
suite('safeTypesBridge', () => {
|
||||
function acceptsString(value, type) {
|
||||
assert.equal(Gerrit.SafeTypes.safeTypesBridge(value, type),
|
||||
value);
|
||||
}
|
||||
|
||||
function rejects(value, type) {
|
||||
assert.throws(() => { Gerrit.SafeTypes.safeTypesBridge(value, type); });
|
||||
}
|
||||
|
||||
test('accepts valid URL strings', () => {
|
||||
acceptsString('/foo/bar', 'URL');
|
||||
acceptsString('#baz', 'URL');
|
||||
});
|
||||
|
||||
test('rejects invalid URL strings', () => {
|
||||
rejects('javascript://void();', 'URL');
|
||||
});
|
||||
|
||||
test('accepts SafeUrl values', () => {
|
||||
const url = '/abc/123';
|
||||
const safeUrl = new element.SafeUrl(url);
|
||||
assert.equal(Gerrit.SafeTypes.safeTypesBridge(safeUrl, 'URL'), url);
|
||||
});
|
||||
|
||||
test('rejects non-string or non-SafeUrl types', () => {
|
||||
rejects(3.1415926, 'URL');
|
||||
});
|
||||
|
||||
test('accepts any binding to STRING or CONSTANT', () => {
|
||||
acceptsString('foo/bar/baz', 'STRING');
|
||||
acceptsString('lorem ipsum dolor', 'CONSTANT');
|
||||
});
|
||||
|
||||
test('rejects all other types', () => {
|
||||
rejects('foo', 'JAVASCRIPT');
|
||||
rejects('foo', 'HTML');
|
||||
rejects('foo', 'RESOURCE_URL');
|
||||
rejects('foo', 'STYLE');
|
||||
});
|
||||
suiteSetup(() => {
|
||||
Polymer({
|
||||
is: 'safe-types-element',
|
||||
behaviors: [Gerrit.SafeTypes],
|
||||
});
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
sandbox = sinon.sandbox.create();
|
||||
element = fixture('basic');
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
test('SafeUrl accepts valid urls', () => {
|
||||
function accepts(url) {
|
||||
const safeUrl = new element.SafeUrl(url);
|
||||
assert.isOk(safeUrl);
|
||||
assert.equal(url, safeUrl.asString());
|
||||
}
|
||||
accepts('http://www.google.com/');
|
||||
accepts('https://www.google.com/');
|
||||
accepts('HtTpS://www.google.com/');
|
||||
accepts('//www.google.com/');
|
||||
accepts('/c/1234/file/path.html@45');
|
||||
accepts('#hash-url');
|
||||
accepts('mailto:name@example.com');
|
||||
});
|
||||
|
||||
test('SafeUrl rejects invalid urls', () => {
|
||||
function rejects(url) {
|
||||
assert.throws(() => { new element.SafeUrl(url); });
|
||||
}
|
||||
rejects('javascript://alert("evil");');
|
||||
rejects('ftp:example.com');
|
||||
rejects('data:text/html,scary business');
|
||||
});
|
||||
|
||||
suite('safeTypesBridge', () => {
|
||||
function acceptsString(value, type) {
|
||||
assert.equal(Gerrit.SafeTypes.safeTypesBridge(value, type),
|
||||
value);
|
||||
}
|
||||
|
||||
function rejects(value, type) {
|
||||
assert.throws(() => { Gerrit.SafeTypes.safeTypesBridge(value, type); });
|
||||
}
|
||||
|
||||
test('accepts valid URL strings', () => {
|
||||
acceptsString('/foo/bar', 'URL');
|
||||
acceptsString('#baz', 'URL');
|
||||
});
|
||||
|
||||
test('rejects invalid URL strings', () => {
|
||||
rejects('javascript://void();', 'URL');
|
||||
});
|
||||
|
||||
test('accepts SafeUrl values', () => {
|
||||
const url = '/abc/123';
|
||||
const safeUrl = new element.SafeUrl(url);
|
||||
assert.equal(Gerrit.SafeTypes.safeTypesBridge(safeUrl, 'URL'), url);
|
||||
});
|
||||
|
||||
test('rejects non-string or non-SafeUrl types', () => {
|
||||
rejects(3.1415926, 'URL');
|
||||
});
|
||||
|
||||
test('accepts any binding to STRING or CONSTANT', () => {
|
||||
acceptsString('foo/bar/baz', 'STRING');
|
||||
acceptsString('lorem ipsum dolor', 'CONSTANT');
|
||||
});
|
||||
|
||||
test('rejects all other types', () => {
|
||||
rejects('foo', 'JAVASCRIPT');
|
||||
rejects('foo', 'HTML');
|
||||
rejects('foo', 'RESOURCE_URL');
|
||||
rejects('foo', 'STYLE');
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user