Merge changes from topic "project-cache-groups"
* changes:
Make ConfiguredMimeTypes an AutoValue
Make SubscribeSection an AutoValue
Make CommentLinkInfoImpl an AutoValue and remove inheritance
Add a test for checking mergability of a change on other branches
Allow mutating BranchOrder in project.config and add a test
Make BranchOrderSection an AutoValue
Make ValidationError an AutoValue
Mark Project.NameKey as immutable and thread-safe
ProjectConfig: Make GroupReference an AutoValue and remove byName map
* submodules:
* Update plugins/singleusergroup from branch 'master'
to 9eb63345a129533aa88235af3ba9308c53cee1d2
- Adust to changes in Gerrit core
Change-Id: Ic114e8b4c12a3d9c2474019d16b848ae2243f62f
diff --git a/.gitignore b/.gitignore
index 3a5d28b..bcafbb4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,6 +31,8 @@
/node_modules/
/package-lock.json
/plugins/*
+!/plugins/package.json
+!/plugins/yarn.lock
!/plugins/BUILD
!/plugins/codemirror-editor
!/plugins/commit-message-length-validator
diff --git a/Documentation/access-control.txt b/Documentation/access-control.txt
index 8509b1f..c9e2ed5 100644
--- a/Documentation/access-control.txt
+++ b/Documentation/access-control.txt
@@ -186,6 +186,10 @@
project "`All-Projects`". This inheritance can be configured
through link:cmd-set-project-parent.html[gerrit set-project-parent].
+When projects are set as parent projects, the child projects inherit
+all of the parent's access rights. "`All-Projects`" is treated as a
+parent of all projects.
+
Per-project access control lists are also supported.
Users are permitted to use the maximum range granted to any of their
diff --git a/Documentation/dev-crafting-changes.txt b/Documentation/dev-crafting-changes.txt
index 5a54c5f..9bc7f0b 100644
--- a/Documentation/dev-crafting-changes.txt
+++ b/Documentation/dev-crafting-changes.txt
@@ -116,7 +116,7 @@
link:https://github.com/google/google-java-format[`google-java-format`,role=external,window=_blank]
tool (version 1.7), and to format Bazel BUILD, WORKSPACE and .bzl files the
link:https://github.com/bazelbuild/buildtools/tree/master/buildifier[`buildifier`,role=external,window=_blank]
-tool (version 3.0.0). Unused dependencies are found and removed using the
+tool (version 3.2.1). Unused dependencies are found and removed using the
link:https://github.com/bazelbuild/buildtools/tree/master/unused_deps[`unused_deps`,role=external,window=_blank]
build tool, a sibling of `buildifier`.
diff --git a/Documentation/dev-roles.txt b/Documentation/dev-roles.txt
index 2ca7f22..cecaedc 100644
--- a/Documentation/dev-roles.txt
+++ b/Documentation/dev-roles.txt
@@ -213,10 +213,10 @@
[[maintainer-election]]
Maintainers can nominate new maintainers by posting a nomination on the
non-public maintainers mailing list. Nominations should stay open for
-at least 14 calendar days so that all maintainers have a chance to
+at least 10 calendar days so that all maintainers have a chance to
vote. To be approved as maintainer a minimum of 5 positive votes and no
negative votes is required. This means if 5 positive votes without
-negative votes have been reached and 14 calendar days have passed, any
+negative votes have been reached and 10 calendar days have passed, any
maintainer can close the vote and welcome the new maintainer. Extending
the voting period during holiday season or if there are not enough
votes is possible, but the voting period should not exceed 1 month. If
diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt
index 066f6d8..b483db8 100644
--- a/Documentation/rest-api-changes.txt
+++ b/Documentation/rest-api-changes.txt
@@ -100,6 +100,15 @@
"id": "demo~master~Idaf5e098d70898b7119f6f4af5a6c13343d64b57",
"project": "demo",
"branch": "master",
+ "attention_set": [
+ {
+ "account": {
+ "name": "John Doe"
+ },
+ "last_update": "2012-07-17 07:19:27.766000000",
+ "reason": "reviewer or cc replied"
+ }
+ ]
"change_id": "Idaf5e098d70898b7119f6f4af5a6c13343d64b57",
"subject": "One change",
"status": "NEW",
@@ -519,6 +528,15 @@
"id": "myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940",
"project": "myProject",
"branch": "master",
+ "attention_set": [
+ {
+ "account": {
+ "name": "John Doe"
+ },
+ "last_update": "2013-02-21 11:16:36.775000000",
+ "reason": "reviewer or cc replied"
+ }
+ ]
"change_id": "I8473b95934b5732ac55d26311a706c9c2bde9940",
"subject": "Implementing Feature X",
"status": "NEW",
@@ -571,6 +589,18 @@
"id": "myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940",
"project": "myProject",
"branch": "master",
+ "attention_set": [
+ {
+ "account": {
+ "_account_id": 1000096,
+ "name": "John Doe",
+ "email": "john.doe@example.com",
+ "username": "jdoe"
+ },
+ "last_update": "2013-02-21 11:16:36.775000000",
+ "reason": "reviewer or cc replied"
+ }
+ ]
"change_id": "I8473b95934b5732ac55d26311a706c9c2bde9940",
"subject": "Implementing Feature X",
"status": "NEW",
@@ -1128,6 +1158,8 @@
The request body does not need to include a link:#abandon-input[
AbandonInput] entity if no review comment is added.
+Abandoning a change also removes all users from the link:#attention-set[attention set].
+
.Request
----
POST /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/abandon HTTP/1.0
@@ -1616,6 +1648,8 @@
The request body only needs to include a link:#submit-input[
SubmitInput] entity if submitting on behalf of another user.
+Submitting a change also removes all users from the link:#attention-set[attention set].
+
.Request
----
POST /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/submit HTTP/1.0
@@ -2274,6 +2308,9 @@
is added. Actions that create a new patch set in a WIP change default to
notifying *OWNER* instead of *ALL*.
+Marking a change work in progress also removes all users from the
+link:#attention-set[attention set].
+
.Request
----
POST /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/wip HTTP/1.0
@@ -2302,6 +2339,9 @@
to include a link:#work-in-progress-input[WorkInProgressInput] entity
if no review comment is added.
+Marking a change ready for review also adds all of the reviewers of the change
+to the link:#attention-set[attention set].
+
.Request
----
POST /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/ready HTTP/1.0
@@ -3220,6 +3260,10 @@
a CC on the change is added as reviewer, the reviewer state of that
user is updated to reviewer.
+Adding a new reviewer also adds that reviewer to the attention set, unless
+the change is work in progress.
+Also, moving a reviewer to CC removes that user from the attention set.
+
.Request
----
POST /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/reviewers HTTP/1.0
@@ -3361,6 +3405,7 @@
--
Deletes a reviewer from a change.
+Deleting a reviewer also removes that user from the attention set.
.Request
----
@@ -3919,6 +3964,33 @@
added as a reviewer, otherwise (if they only commented) they are added to
the CC list.
+Some updates to the attention set occur here. If more than one update should
+occur, only the first update in the order of the below documentation occurs:
+
+If a user is part of remove_from_attention_set, the user will be explicitly
+removed from the attention set.
+
+If a user is part of add_to_attention_set, the user will be explicitly
+added to the attention set.
+
+If the boolean ignore_default_attention_set_rules is set to true, all
+other rules below will be ignored:
+
+The user who created the review is removed from the attention set.
+
+If the change is ready for review, the following also apply:
+
+When the uploader replies, the owner is added to the attention set.
+
+When the owner or uploader replies, all the reviewers are added to
+the attention set.
+
+When neither the owner nor the uploader replies, add the owner and the
+uploader to the attention set.
+
+Then, new reviewers are added to the attention set, and removed reviewers
+(by becoming CC) are removed from the attention set.
+
A review cannot be set on a change edit. Trying to post a review for a
change edit fails with `409 Conflict`.
@@ -5676,6 +5748,172 @@
HTTP/1.1 204 No Content
----
+[[attention-set-endpoints]]
+== Attention Set Endpoints
+
+[[get-attention-set]]
+=== Get Attention Set
+--
+'GET /changes/link:#change-id[\{change-id\}]/attention'
+--
+
+Returns all users that are currently in the attention set.
+As response a list of link:#attention-set-info[AttentionSetInfo]
+entity is returned.
+
+.Request
+----
+ GET /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/attention HTTP/1.0
+----
+
+.Response
+----
+ HTTP/1.1 200 OK
+ Content-Disposition: attachment
+ Content-Type: application/json; charset=UTF-8
+
+ )]}'
+ [
+ {
+ "account": {
+ "_account_id": 1000096,
+ "name": "John Doe",
+ "email": "john.doe@example.com",
+ "username": "jdoe"
+ },
+ "last_update": "2013-02-01 09:59:32.126000000",
+ "reason": "reviewer or cc replied"
+ },
+ {
+ "account": {
+ "_account_id": 1000097,
+ "name": "Jane Doe",
+ "email": "jane.doe@example.com",
+ "username": "janedoe"
+ },
+ "last_update": "2013-02-01 09:59:32.126000000",
+ "reason": "Reviewer was added"
+ }
+ ]
+----
+
+[[add-to-attention-set]]
+=== Add To Attention Set
+--
+'POST /changes/link:#change-id[\{change-id\}]/attention'
+--
+
+Adds a single user to the attention set of a change.
+
+A user can only be added if they are not in the attention set.
+If a user is added while already in the attention set, the
+request is silently ignored.
+
+.Request
+----
+ POST /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/attention HTTP/1.0
+----
+
+Details should be provided in the request body as an
+link:#attention-set-input[AttentionSetInput] entity.
+
+.Request
+----
+ POST /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/attention HTTP/1.0
+ Content-Type: application/json; charset=UTF-8
+
+ {
+ "user": "John Doe",
+ "reason": "reason"
+ }
+----
+
+.Response
+----
+ HTTP/1.1 200 OK
+ Content-Disposition: attachment
+ Content-Type: application/json; charset=UTF-8
+
+ )]}'
+ {
+ "_account_id": 1000096,
+ "name": "John Doe",
+ "email": "john.doe@example.com",
+ "username": "jdoe"
+ }
+----
+
+[[remove-from-attention-set]]
+=== Remove from Attention Set
+--
+'DELETE /changes/link:#change-id[\{change-id\}]/attention/link:rest-api-accounts.html#account-id[\{account-id\}]' +
+'POST /changes/link:#change-id[\{change-id\}]/attention/link:rest-api-accounts.html#account-id[\{account-id\}]/delete'
+--
+
+Deletes a single user from the attention set of a change.
+
+A user can only be removed from the attention set if they
+are currently in the attention set. Otherwise, the request
+is silently ignored.
+
+.Request
+----
+ DELETE /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/attention/John%20Doe HTTP/1.0
+ POST /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/attention/John%20Doe/delete HTTP/1.0
+----
+
+Reason can be provided in the request body as an
+link:#attention-set-input[AttentionSetInput] entity.
+
+User must be left empty, or the user must be exactly
+the same user as in the request header.
+
+.Request
+----
+ POST /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/attention/John%20Doe/delete HTTP/1.0
+ Content-Type: application/json; charset=UTF-8
+
+ {
+ "reason": "reason"
+ }
+----
+
+.Response
+----
+ HTTP/1.1 204 No Content
+----
+
+[[attention-set]]
+== Attention Set
+Attention Set is the set of users that should perform some action on the
+change. E.g, reviewers should review the change, owner/uploader should
+add a new patchset or respond to comments.
+
+Users are added to the attention set if one the following apply:
+
+* They are manually added in link:#review-input[ReviewInput] in
+ add_to_attention_set.
+* They are added as reviewers.
+* The change is marked ready for review.
+* As an owner/uploader, when someone replies on your change.
+* As a reviewer, when the owner/uploader replies.
+
+Users are removed from the attention set if one the following apply:
+
+* They are manually removed in link:#review-input[ReviewInput] in
+ remove_from_attention_set.
+* They are removed from reviewers.
+* The change is marked work in progress, abandoned, or submitted.
+* When the user replies on a change.
+
+If the ignore_default_attention_set_rules in link:#review-input[ReviewInput]
+is set to true, no other changes to the attention set will occur during the
+link:#set-review[set-review].
+Also, users specified in the list will occur instead of any of the implicit
+changes to the attention set. E.g, if a user is added by add_to_attention_set
+in link:#review-input[ReviewInput], but also the change is marked work in
+progress, the user will still be added.
+
[[ids]]
== IDs
@@ -5873,6 +6111,33 @@
should be added as assignee.
|===========================
+[[attention-set-info]]
+=== AttentionSetInfo
+The `AttentionSetInfo` entity contains details of users that are in
+the link:#attention-set[attention set].
+
+[options="header",cols="1,^1,5"]
+|===========================
+|Field Name ||Description
+|`account` || link:rest-api-accounts.html#account-info[AccountInfo] entity.
+|`last_update` || The link:rest-api.html#timestamp[timestamp] of the last update.
+|`reason` | The reason of for adding or removing the user.
+
+|===========================
+[[attention-set-input]]
+=== AttentionSetInput
+The `AttentionSetInput` entity contains details for adding users to the
+link:#attention-set[attention set] and removing them from it.
+
+[options="header",cols="1,^1,5"]
+|===========================
+|Field Name ||Description
+|`user` |optional| link:rest-api-accounts.html#account-id[ID]
+of the account that should be added to the attention set. For removals,
+this field should be empty or the same as the field in the request header.
+|`reason` | The reason of for adding or removing the user.
+|===========================
+
[[blame-info]]
=== BlameInfo
The `BlameInfo` entity stores the commit metadata with the row coordinates where
@@ -5929,6 +6194,9 @@
The name of the target branch. +
The `refs/heads/` prefix is omitted.
|`topic` |optional|The topic to which this change belongs.
+|`attention_set` |optional|
+The map that maps link:rest-api-accounts.html#account-id[account IDs]
+to link:#attention-set-info[AttentionSetInfo] of that account.
|`assignee` |optional|
The assignee of the change as an link:rest-api-accounts.html#account-info[
AccountInfo] entity.
@@ -7166,24 +7434,24 @@
[options="header",cols="1,^1,5"]
|============================
-|Field Name ||Description
-|`message` |optional|
+|Field Name ||Description
+|`message` |optional|
The message to be added as review comment.
-|`tag` |optional|
+|`tag` |optional|
Apply this tag to the review comment message, votes, and inline
comments. Tags may be used by CI or other automated systems to
distinguish them from human reviews. Votes/comments that contain `tag` with
'autogenerated:' prefix can be filtered out in the web UI.
-|`labels` |optional|
+|`labels` |optional|
The votes that should be added to the revision as a map that maps the
label names to the voting values.
-|`comments` |optional|
+|`comments` |optional|
The comments that should be added as a map that maps a file path to a
list of link:#comment-input[CommentInput] entities.
-|`robot_comments` |optional|
+|`robot_comments` |optional|
The robot comments that should be added as a map that maps a file path
to a list of link:#robot-comment-input[RobotCommentInput] entities.
-|`drafts` |optional|
+|`drafts` |optional|
Draft handling that defines how draft comments are handled that are
already in the database but that were not also described in this
input. +
@@ -7192,29 +7460,39 @@
Only `KEEP` is allowed when used in conjunction with `on_behalf_of`. +
If not set, the default is `KEEP`. If `on_behalf_of` is set, then no other value
besides `KEEP` is allowed.
-|`notify` |optional|
+|`notify` |optional|
Notify handling that defines to whom email notifications should be sent
after the review is stored. +
Allowed values are `NONE`, `OWNER`, `OWNER_REVIEWERS` and `ALL`. +
If not set, the default is `ALL`.
-|`notify_details` |optional|
+|`notify_details` |optional|
Additional information about whom to notify about the update as a map
of recipient type to link:#notify-info[NotifyInfo] entity.
-|`omit_duplicate_comments`|optional|
+|`omit_duplicate_comments` |optional|
If `true`, comments with the same content at the same place will be omitted.
-|`on_behalf_of` |optional|
+|`on_behalf_of` |optional|
link:rest-api-accounts.html#account-id[\{account-id\}] the review
should be posted on behalf of. To use this option the caller must
have been granted `labelAs-NAME` permission for all keys of labels.
-|`reviewers` |optional|
+|`reviewers` |optional|
A list of link:rest-api-changes.html#reviewer-input[ReviewerInput]
representing reviewers that should be added to the change.
-|`ready` |optional|
+|`ready` |optional|
If true, and if the change is work in progress, then start review.
It is an error for both `ready` and `work_in_progress` to be true.
-|`work_in_progress` |optional|
+|`work_in_progress` |optional|
If true, mark the change as work in progress. It is an error for both
`ready` and `work_in_progress` to be true.
+|`add_to_attention_set` |optional|
+list of link:#attention-set-input[AttentionSetInput] entities to add
+to the link:#attention-set[attention set].
+remove_from_attention_set` |optional|
+list of link:#attention-set-input[AttentionSetInput] entities to remove
+from the link:#attention-set[attention set].
+ignore_default_attention_set_rules`|optional|
+If set to true, ignore all default attention set rules described in the
+link:#attention-set[attention set]. Updates in add_to_attention_set
+and remove_from_attention_set are not ignored.
|============================
[[review-result]]
diff --git a/README.md b/README.md
index 084f2b0..30b7d0b 100644
--- a/README.md
+++ b/README.md
@@ -77,13 +77,13 @@
Docker images of Gerrit are available on [DockerHub](https://hub.docker.com/u/gerritforge/)
-To run a CentOS 7 based Gerrit image:
+To run a CentOS 8 based Gerrit image:
- docker run -p 8080:8080 gerritforge/gerrit-centos7[:version]
+ docker run -p 8080:8080 gerritcodereview/gerrit[:version]-centos8
-To run a Ubuntu 15.04 based Gerrit image:
+To run a Ubuntu 20.04 based Gerrit image:
- docker run -p 8080:8080 gerritforge/gerrit-ubuntu15.04[:version]
+ docker run -p 8080:8080 gerritcodereview/gerrit[:version]-ubuntu20
_NOTE: release is optional. Last released package of the version is installed if the release
number is omitted._
diff --git a/WORKSPACE b/WORKSPACE
index 91eef76..47c3e9c 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -10,6 +10,8 @@
# @ui_npm folder must not have devDependencies. All dev dependencies must be placed in @ui_dev_npm
# 4. @ui_dev_npm (polygerrit-ui/node_modules) - devDependencies for polygerrit. The packages from these
# folder can be used for testing, but must not be included in the final bundle.
+# 5. @plugins_npm (plugins/node_modules) - plugin dependencies for polygerrit plugins.
+# The packages here are expected to be used in plugins.
# Note: separation between @ui_npm and @ui_dev_npm is necessary because with bazel we can't generate
# two managed directories from the same package.json. At the same time we want to avoid accidental
# usages of code from devDependencies in polygerrit bundle.
@@ -20,6 +22,7 @@
"@ui_npm": ["polygerrit-ui/app/node_modules"],
"@ui_dev_npm": ["polygerrit-ui/node_modules"],
"@tools_npm": ["tools/node_tools/node_modules"],
+ "@plugins_npm": ["plugins/node_modules"],
},
)
@@ -647,18 +650,18 @@
sha1 = "a3ae34e57fa8a4040e28247291d0cc3d6b8c7bcf",
)
-AUTO_VALUE_VERSION = "1.7.2"
+AUTO_VALUE_VERSION = "1.7.3"
maven_jar(
name = "auto-value",
artifact = "com.google.auto.value:auto-value:" + AUTO_VALUE_VERSION,
- sha1 = "895dbc8f1764f162c1dae34cc29e300220d6d4ba",
+ sha1 = "cbd30873f839545c7c9264bed61d500bf85bd33e",
)
maven_jar(
name = "auto-value-annotations",
artifact = "com.google.auto.value:auto-value-annotations:" + AUTO_VALUE_VERSION,
- sha1 = "7eec707327ec1663b9387c8671efb6808750e039",
+ sha1 = "59ce5ee6aea918f674229f1147da95fdf7f31ce6",
)
declare_nongoogle_deps()
@@ -1208,6 +1211,13 @@
yarn_lock = "//:tools/node_tools/yarn.lock",
)
+yarn_install(
+ name = "plugins_npm",
+ args = ["--prod"],
+ package_json = "//:plugins/package.json",
+ yarn_lock = "//:plugins/yarn.lock",
+)
+
# Install all Bazel dependencies needed for npm packages that supply Bazel rules
load("@npm//:install_bazel_dependencies.bzl", "install_bazel_dependencies")
diff --git a/java/com/google/gerrit/acceptance/testsuite/account/AccountOperationsImpl.java b/java/com/google/gerrit/acceptance/testsuite/account/AccountOperationsImpl.java
index f64d7a2..8c1eebd 100644
--- a/java/com/google/gerrit/acceptance/testsuite/account/AccountOperationsImpl.java
+++ b/java/com/google/gerrit/acceptance/testsuite/account/AccountOperationsImpl.java
@@ -15,7 +15,10 @@
package com.google.gerrit.acceptance.testsuite.account;
import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.ImmutableSet.toImmutableSet;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
import com.google.gerrit.entities.Account;
import com.google.gerrit.server.ServerInitiated;
import com.google.gerrit.server.account.AccountState;
@@ -60,8 +63,8 @@
private Account.Id createAccount(TestAccountCreation accountCreation) throws Exception {
AccountsUpdate.AccountUpdater accountUpdater =
- (account, updateBuilder) ->
- fillBuilder(updateBuilder, accountCreation, account.account().id());
+ (accountState, updateBuilder) ->
+ fillBuilder(updateBuilder, accountCreation, accountState.account().id());
AccountState createdAccount = createAccount(accountUpdater);
return createdAccount.account().id();
}
@@ -82,6 +85,11 @@
accountCreation.username().ifPresent(u -> setUsername(builder, accountId, u, httpPassword));
accountCreation.status().ifPresent(builder::setStatus);
accountCreation.active().ifPresent(builder::setActive);
+ accountCreation
+ .secondaryEmails()
+ .forEach(
+ secondaryEmail ->
+ builder.addExternalId(ExternalId.createEmail(accountId, secondaryEmail)));
}
private static InternalAccountUpdate.Builder setPreferredEmail(
@@ -136,6 +144,7 @@
.fullname(Optional.ofNullable(account.fullName()))
.username(accountState.userName())
.active(accountState.account().isActive())
+ .emails(ExternalId.getEmails(accountState.externalIds()).collect(toImmutableSet()))
.build();
}
@@ -147,7 +156,7 @@
private void updateAccount(TestAccountUpdate accountUpdate)
throws IOException, ConfigInvalidException {
AccountsUpdate.AccountUpdater accountUpdater =
- (account, updateBuilder) -> fillBuilder(updateBuilder, accountUpdate, accountId);
+ (accountState, updateBuilder) -> fillBuilder(updateBuilder, accountUpdate, accountState);
Optional<AccountState> updatedAccount = updateAccount(accountUpdater);
checkState(updatedAccount.isPresent(), "Tried to update non-existing test account");
}
@@ -160,13 +169,58 @@
private void fillBuilder(
InternalAccountUpdate.Builder builder,
TestAccountUpdate accountUpdate,
- Account.Id accountId) {
+ AccountState accountState) {
accountUpdate.fullname().ifPresent(builder::setFullName);
accountUpdate.preferredEmail().ifPresent(e -> setPreferredEmail(builder, accountId, e));
String httpPassword = accountUpdate.httpPassword().orElse(null);
accountUpdate.username().ifPresent(u -> setUsername(builder, accountId, u, httpPassword));
accountUpdate.status().ifPresent(builder::setStatus);
accountUpdate.active().ifPresent(builder::setActive);
+
+ ImmutableSet<String> secondaryEmails = getSecondaryEmails(accountUpdate, accountState);
+ ImmutableSet<String> newSecondaryEmails =
+ ImmutableSet.copyOf(accountUpdate.secondaryEmailsModification().apply(secondaryEmails));
+ if (!secondaryEmails.equals(newSecondaryEmails)) {
+ setSecondaryEmails(builder, accountUpdate, accountState, newSecondaryEmails);
+ }
+ }
+
+ private ImmutableSet<String> getSecondaryEmails(
+ TestAccountUpdate accountUpdate, AccountState accountState) {
+ ImmutableSet<String> allEmails =
+ ExternalId.getEmails(accountState.externalIds()).collect(toImmutableSet());
+ if (accountUpdate.preferredEmail().isPresent()) {
+ return ImmutableSet.copyOf(
+ Sets.difference(allEmails, ImmutableSet.of(accountUpdate.preferredEmail().get())));
+ } else if (accountState.account().preferredEmail() != null) {
+ return ImmutableSet.copyOf(
+ Sets.difference(allEmails, ImmutableSet.of(accountState.account().preferredEmail())));
+ }
+ return allEmails;
+ }
+
+ private void setSecondaryEmails(
+ InternalAccountUpdate.Builder builder,
+ TestAccountUpdate accountUpdate,
+ AccountState accountState,
+ ImmutableSet<String> newSecondaryEmails) {
+ // delete all external IDs of SCHEME_MAILTO scheme, then add back SCHEME_MAILTO external IDs
+ // for the new secondary emails and the preferred email
+ builder.deleteExternalIds(
+ accountState.externalIds().stream()
+ .filter(e -> e.isScheme(ExternalId.SCHEME_MAILTO))
+ .collect(toImmutableSet()));
+ builder.addExternalIds(
+ newSecondaryEmails.stream()
+ .map(secondaryEmail -> ExternalId.createEmail(accountId, secondaryEmail))
+ .collect(toImmutableSet()));
+ if (accountUpdate.preferredEmail().isPresent()) {
+ builder.addExternalId(
+ ExternalId.createEmail(accountId, accountUpdate.preferredEmail().get()));
+ } else if (accountState.account().preferredEmail() != null) {
+ builder.addExternalId(
+ ExternalId.createEmail(accountId, accountState.account().preferredEmail()));
+ }
}
@Override
diff --git a/java/com/google/gerrit/acceptance/testsuite/account/TestAccount.java b/java/com/google/gerrit/acceptance/testsuite/account/TestAccount.java
index 2574d55..94b1cc4 100644
--- a/java/com/google/gerrit/acceptance/testsuite/account/TestAccount.java
+++ b/java/com/google/gerrit/acceptance/testsuite/account/TestAccount.java
@@ -15,6 +15,8 @@
package com.google.gerrit.acceptance.testsuite.account;
import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
import com.google.gerrit.entities.Account;
import java.util.Optional;
@@ -30,6 +32,16 @@
public abstract boolean active();
+ public abstract ImmutableSet<String> emails();
+
+ public ImmutableSet<String> secondaryEmails() {
+ if (!preferredEmail().isPresent()) {
+ return emails();
+ }
+
+ return ImmutableSet.copyOf(Sets.difference(emails(), ImmutableSet.of(preferredEmail().get())));
+ }
+
static Builder builder() {
return new AutoValue_TestAccount.Builder();
}
@@ -46,6 +58,8 @@
abstract Builder active(boolean active);
+ abstract Builder emails(ImmutableSet<String> emails);
+
abstract TestAccount build();
}
}
diff --git a/java/com/google/gerrit/acceptance/testsuite/account/TestAccountCreation.java b/java/com/google/gerrit/acceptance/testsuite/account/TestAccountCreation.java
index 983fec0..042dc9a 100644
--- a/java/com/google/gerrit/acceptance/testsuite/account/TestAccountCreation.java
+++ b/java/com/google/gerrit/acceptance/testsuite/account/TestAccountCreation.java
@@ -14,10 +14,14 @@
package com.google.gerrit.acceptance.testsuite.account;
+import static com.google.common.base.Preconditions.checkState;
+
import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableSet;
import com.google.gerrit.acceptance.testsuite.ThrowingFunction;
import com.google.gerrit.entities.Account;
import java.util.Optional;
+import java.util.Set;
@AutoValue
public abstract class TestAccountCreation {
@@ -33,6 +37,8 @@
public abstract Optional<Boolean> active();
+ public abstract ImmutableSet<String> secondaryEmails();
+
abstract ThrowingFunction<TestAccountCreation, Account.Id> accountCreator();
public static Builder builder(ThrowingFunction<TestAccountCreation, Account.Id> accountCreator) {
@@ -83,14 +89,29 @@
return active(false);
}
+ public abstract Builder secondaryEmails(Set<String> secondaryEmails);
+
+ abstract ImmutableSet.Builder<String> secondaryEmailsBuilder();
+
+ public Builder addSecondaryEmail(String secondaryEmail) {
+ secondaryEmailsBuilder().add(secondaryEmail);
+ return this;
+ }
+
abstract Builder accountCreator(
ThrowingFunction<TestAccountCreation, Account.Id> accountCreator);
abstract TestAccountCreation autoBuild();
public Account.Id create() {
- TestAccountCreation accountUpdate = autoBuild();
- return accountUpdate.accountCreator().applyAndThrowSilently(accountUpdate);
+ TestAccountCreation accountCreation = autoBuild();
+ if (accountCreation.preferredEmail().isPresent()) {
+ checkState(
+ !accountCreation.secondaryEmails().contains(accountCreation.preferredEmail().get()),
+ "preferred email %s cannot be secondary email at the same time",
+ accountCreation.preferredEmail().get());
+ }
+ return accountCreation.accountCreator().applyAndThrowSilently(accountCreation);
}
}
}
diff --git a/java/com/google/gerrit/acceptance/testsuite/account/TestAccountUpdate.java b/java/com/google/gerrit/acceptance/testsuite/account/TestAccountUpdate.java
index da599e7..46988eb 100644
--- a/java/com/google/gerrit/acceptance/testsuite/account/TestAccountUpdate.java
+++ b/java/com/google/gerrit/acceptance/testsuite/account/TestAccountUpdate.java
@@ -15,8 +15,12 @@
package com.google.gerrit.acceptance.testsuite.account;
import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
import com.google.gerrit.acceptance.testsuite.ThrowingConsumer;
import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
@AutoValue
public abstract class TestAccountUpdate {
@@ -32,11 +36,14 @@
public abstract Optional<Boolean> active();
+ public abstract Function<ImmutableSet<String>, Set<String>> secondaryEmailsModification();
+
abstract ThrowingConsumer<TestAccountUpdate> accountUpdater();
public static Builder builder(ThrowingConsumer<TestAccountUpdate> accountUpdater) {
return new AutoValue_TestAccountUpdate.Builder()
.accountUpdater(accountUpdater)
+ .secondaryEmailsModification(in -> in)
.httpPassword("http-pass");
}
@@ -82,6 +89,37 @@
return active(false);
}
+ abstract Builder secondaryEmailsModification(
+ Function<ImmutableSet<String>, Set<String>> secondaryEmailsModification);
+
+ abstract Function<ImmutableSet<String>, Set<String>> secondaryEmailsModification();
+
+ public Builder clearSecondaryEmails() {
+ return secondaryEmailsModification(originalSecondaryEmail -> ImmutableSet.of());
+ }
+
+ public Builder addSecondaryEmail(String secondaryEmail) {
+ Function<ImmutableSet<String>, Set<String>> secondaryEmailsModification =
+ secondaryEmailsModification();
+ secondaryEmailsModification(
+ originalSecondaryEmails ->
+ Sets.union(
+ secondaryEmailsModification.apply(originalSecondaryEmails),
+ ImmutableSet.of(secondaryEmail)));
+ return this;
+ }
+
+ public Builder removeSecondaryEmail(String secondaryEmail) {
+ Function<ImmutableSet<String>, Set<String>> previousModification =
+ secondaryEmailsModification();
+ secondaryEmailsModification(
+ originalSecondaryEmails ->
+ Sets.difference(
+ previousModification.apply(originalSecondaryEmails),
+ ImmutableSet.of(secondaryEmail)));
+ return this;
+ }
+
abstract Builder accountUpdater(ThrowingConsumer<TestAccountUpdate> accountUpdater);
abstract TestAccountUpdate autoBuild();
diff --git a/java/com/google/gerrit/common/data/CommentDetail.java b/java/com/google/gerrit/common/data/CommentDetail.java
index 55e0143..053764d 100644
--- a/java/com/google/gerrit/common/data/CommentDetail.java
+++ b/java/com/google/gerrit/common/data/CommentDetail.java
@@ -16,6 +16,7 @@
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.PatchSet;
import java.util.ArrayList;
import java.util.List;
@@ -36,7 +37,7 @@
protected CommentDetail() {}
- public void include(Change.Id changeId, Comment p) {
+ public void include(Change.Id changeId, HumanComment p) {
PatchSet.Id psId = PatchSet.id(changeId, p.key.patchSetId);
if (p.side == 0) {
if (idA == null && idB.equals(psId)) {
diff --git a/java/com/google/gerrit/entities/AttentionSetUpdate.java b/java/com/google/gerrit/entities/AttentionSetUpdate.java
index 45588722..2e58608 100644
--- a/java/com/google/gerrit/entities/AttentionSetUpdate.java
+++ b/java/com/google/gerrit/entities/AttentionSetUpdate.java
@@ -16,6 +16,7 @@
import com.google.auto.value.AutoValue;
import com.google.gerrit.common.Nullable;
+import com.google.gerrit.extensions.api.changes.AttentionSetInput;
import java.time.Instant;
/**
@@ -23,9 +24,7 @@
* in reverse chronological order. Since each update contains all required information and
* invalidates all previous state, only the most recent record is relevant for each user.
*
- * <p>See {@link com.google.gerrit.extensions.api.changes.AddToAttentionSetInput} and {@link
- * com.google.gerrit.extensions.api.changes.RemoveFromAttentionSetInput} for the representation in
- * the API.
+ * <p>See {@link AttentionSetInput} for the representation in the API.
*/
@AutoValue
public abstract class AttentionSetUpdate {
diff --git a/java/com/google/gerrit/entities/Change.java b/java/com/google/gerrit/entities/Change.java
index b36b5f9..845a9bb 100644
--- a/java/com/google/gerrit/entities/Change.java
+++ b/java/com/google/gerrit/entities/Change.java
@@ -39,7 +39,7 @@
* |
* +- {@link PatchSetApproval}: a +/- vote on the change's current state.
* |
- * +- {@link Comment}: comment about a specific line
+ * +- {@link HumanComment}: comment about a specific line
* </pre>
*
* <p>
diff --git a/java/com/google/gerrit/entities/Comment.java b/java/com/google/gerrit/entities/Comment.java
index 9c58fef..2c10c87 100644
--- a/java/com/google/gerrit/entities/Comment.java
+++ b/java/com/google/gerrit/entities/Comment.java
@@ -24,15 +24,15 @@
import org.eclipse.jgit.lib.ObjectId;
/**
- * This class represents inline comments in NoteDb. This means it determines the JSON format for
- * inline comments in the revision notes that NoteDb uses to persist inline comments.
+ * This class is a base class that can be extended by the different types of inline comment
+ * entities.
*
* <p>Changing fields in this class changes the storage format of inline comments in NoteDb and may
* require a corresponding data migration (adding new optional fields is generally okay).
*
- * <p>Consider updating {@link #getApproximateSize()} when adding/changing fields.
+ * <p>Consider updating {@link #getCommentFieldApproximateSize()} when adding/changing fields.
*/
-public class Comment {
+public abstract class Comment {
public enum Status {
DRAFT('d'),
@@ -301,11 +301,13 @@
* Returns the comment's approximate size. This is used to enforce size limits and should
* therefore include all unbounded fields (e.g. String-s).
*/
- public int getApproximateSize() {
+ protected int getCommentFieldApproximateSize() {
return nullableLength(message, parentUuid, tag, revId, serverId)
+ (key != null ? nullableLength(key.filename, key.uuid) : 0);
}
+ public abstract int getApproximateSize();
+
static int nullableLength(String... strings) {
int length = 0;
for (String s : strings) {
diff --git a/java/com/google/gerrit/entities/HumanComment.java b/java/com/google/gerrit/entities/HumanComment.java
new file mode 100644
index 0000000..8b687cc
--- /dev/null
+++ b/java/com/google/gerrit/entities/HumanComment.java
@@ -0,0 +1,67 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.entities;
+
+import java.sql.Timestamp;
+
+/**
+ * This class represents inline human comments in NoteDb. This means it determines the JSON format
+ * for inline comments in the revision notes that NoteDb uses to persist inline comments.
+ *
+ * <p>Changing fields in this class changes the storage format of inline comments in NoteDb and may
+ * require a corresponding data migration (adding new optional fields is generally okay).
+ *
+ * <p>Consider updating {@link #getApproximateSize()} when adding/changing fields.
+ */
+public class HumanComment extends Comment {
+
+ public HumanComment(
+ Key key,
+ Account.Id author,
+ Timestamp writtenOn,
+ short side,
+ String message,
+ String serverId,
+ boolean unresolved) {
+ super(key, author, writtenOn, side, message, serverId, unresolved);
+ }
+
+ public HumanComment(HumanComment comment) {
+ super(comment);
+ }
+
+ @Override
+ public int getApproximateSize() {
+ return super.getCommentFieldApproximateSize();
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper().toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof HumanComment)) {
+ return false;
+ }
+ return super.equals(o);
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode();
+ }
+}
diff --git a/java/com/google/gerrit/entities/Patch.java b/java/com/google/gerrit/entities/Patch.java
index 3926d47..e6b2167 100644
--- a/java/com/google/gerrit/entities/Patch.java
+++ b/java/com/google/gerrit/entities/Patch.java
@@ -19,6 +19,7 @@
import com.google.auto.value.AutoValue;
import com.google.common.base.Splitter;
import com.google.common.primitives.Ints;
+import com.google.gerrit.common.UsedAt;
import java.util.List;
/**
@@ -107,6 +108,16 @@
public char getCode() {
return code;
}
+
+ @UsedAt(UsedAt.Project.COLLABNET)
+ public static ChangeType forCode(char c) {
+ for (ChangeType s : ChangeType.values()) {
+ if (s.code == c) {
+ return s;
+ }
+ }
+ return null;
+ }
}
/** Type of formatting for this patch. */
diff --git a/java/com/google/gerrit/entities/RobotComment.java b/java/com/google/gerrit/entities/RobotComment.java
index 9256e79..03ddad5 100644
--- a/java/com/google/gerrit/entities/RobotComment.java
+++ b/java/com/google/gerrit/entities/RobotComment.java
@@ -42,7 +42,8 @@
@Override
public int getApproximateSize() {
- int approximateSize = super.getApproximateSize() + nullableLength(robotId, robotRunId, url);
+ int approximateSize =
+ super.getCommentFieldApproximateSize() + nullableLength(robotId, robotRunId, url);
approximateSize +=
properties != null
? properties.entrySet().stream()
@@ -66,4 +67,23 @@
.add("fixSuggestions", Objects.toString(fixSuggestions, ""))
.toString();
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof RobotComment)) {
+ return false;
+ }
+ RobotComment c = (RobotComment) o;
+ return super.equals(o)
+ && Objects.equals(robotId, c.robotId)
+ && Objects.equals(robotRunId, c.robotRunId)
+ && Objects.equals(url, c.url)
+ && Objects.equals(properties, c.properties)
+ && Objects.equals(fixSuggestions, c.fixSuggestions);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), robotId, robotRunId, url, properties, fixSuggestions);
+ }
}
diff --git a/java/com/google/gerrit/extensions/api/changes/AttentionSetApi.java b/java/com/google/gerrit/extensions/api/changes/AttentionSetApi.java
index 5086cd8..da9a8c7 100644
--- a/java/com/google/gerrit/extensions/api/changes/AttentionSetApi.java
+++ b/java/com/google/gerrit/extensions/api/changes/AttentionSetApi.java
@@ -20,7 +20,7 @@
/** API for managing the attention set of a change. */
public interface AttentionSetApi {
- void remove(RemoveFromAttentionSetInput input) throws RestApiException;
+ void remove(AttentionSetInput input) throws RestApiException;
/**
* A default implementation which allows source compatibility when adding new methods to the
@@ -28,7 +28,7 @@
*/
class NotImplemented implements AttentionSetApi {
@Override
- public void remove(RemoveFromAttentionSetInput input) throws RestApiException {
+ public void remove(AttentionSetInput input) throws RestApiException {
throw new NotImplementedException();
}
}
diff --git a/java/com/google/gerrit/extensions/api/changes/AddToAttentionSetInput.java b/java/com/google/gerrit/extensions/api/changes/AttentionSetInput.java
similarity index 68%
rename from java/com/google/gerrit/extensions/api/changes/AddToAttentionSetInput.java
rename to java/com/google/gerrit/extensions/api/changes/AttentionSetInput.java
index 39efc64..f0d42c5 100644
--- a/java/com/google/gerrit/extensions/api/changes/AddToAttentionSetInput.java
+++ b/java/com/google/gerrit/extensions/api/changes/AttentionSetInput.java
@@ -14,20 +14,26 @@
package com.google.gerrit.extensions.api.changes;
+import com.google.gerrit.extensions.common.AttentionSetInfo;
+import com.google.gerrit.extensions.restapi.DefaultInput;
+
/**
* Input at API level to add a user to the attention set.
*
- * @see RemoveFromAttentionSetInput
- * @see com.google.gerrit.extensions.common.AttentionSetEntry
+ * @see AttentionSetInfo
*/
-public class AddToAttentionSetInput {
+public class AttentionSetInput {
public String user;
- public String reason;
+ @DefaultInput public String reason;
- public AddToAttentionSetInput(String user, String reason) {
+ public AttentionSetInput(String user, String reason) {
this.user = user;
this.reason = reason;
}
- public AddToAttentionSetInput() {}
+ public AttentionSetInput(String reason) {
+ this.reason = reason;
+ }
+
+ public AttentionSetInput() {}
}
diff --git a/java/com/google/gerrit/extensions/api/changes/ChangeApi.java b/java/com/google/gerrit/extensions/api/changes/ChangeApi.java
index 8df5343..e8b58f9 100644
--- a/java/com/google/gerrit/extensions/api/changes/ChangeApi.java
+++ b/java/com/google/gerrit/extensions/api/changes/ChangeApi.java
@@ -302,7 +302,7 @@
AttentionSetApi attention(String id) throws RestApiException;
/** Adds a user to the attention set. */
- AccountInfo addToAttentionSet(AddToAttentionSetInput input) throws RestApiException;
+ AccountInfo addToAttentionSet(AttentionSetInput input) throws RestApiException;
/** Set the assignee of a change. */
AccountInfo setAssignee(AssigneeInput input) throws RestApiException;
@@ -578,7 +578,7 @@
}
@Override
- public AccountInfo addToAttentionSet(AddToAttentionSetInput input) throws RestApiException {
+ public AccountInfo addToAttentionSet(AttentionSetInput input) throws RestApiException {
throw new NotImplementedException();
}
diff --git a/java/com/google/gerrit/extensions/api/changes/RemoveFromAttentionSetInput.java b/java/com/google/gerrit/extensions/api/changes/RemoveFromAttentionSetInput.java
deleted file mode 100644
index 9212788..0000000
--- a/java/com/google/gerrit/extensions/api/changes/RemoveFromAttentionSetInput.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.extensions.api.changes;
-
-import com.google.gerrit.extensions.restapi.DefaultInput;
-
-/**
- * Input at API level to remove a user from the attention set.
- *
- * @see AddToAttentionSetInput
- * @see com.google.gerrit.extensions.common.AttentionSetEntry
- */
-public class RemoveFromAttentionSetInput {
- @DefaultInput public String reason;
-
- public RemoveFromAttentionSetInput(String reason) {
- this.reason = reason;
- }
-
- public RemoveFromAttentionSetInput() {}
-}
diff --git a/java/com/google/gerrit/extensions/api/changes/ReviewInput.java b/java/com/google/gerrit/extensions/api/changes/ReviewInput.java
index b140064..1f41c07 100644
--- a/java/com/google/gerrit/extensions/api/changes/ReviewInput.java
+++ b/java/com/google/gerrit/extensions/api/changes/ReviewInput.java
@@ -75,6 +75,20 @@
*/
public boolean ready;
+ /** Users that should be added to the attention set of this change. */
+ public List<AttentionSetInput> addToAttentionSet;
+
+ /** Users that should be removed from the attention set of this change. */
+ public List<AttentionSetInput> removeFromAttentionSet;
+
+ /**
+ * Users in the attention set will only be added and removed based on {@link #addToAttentionSet}
+ * and {@link #removeFromAttentionSet}. Normally, they are also added and removed when some events
+ * occur. E.g, adding/removing reviewers, marking a change ready for review or work in progress,
+ * and replying on changes.
+ */
+ public boolean ignoreDefaultAttentionSetRules;
+
public enum DraftHandling {
/** Leave pending drafts alone. */
KEEP,
@@ -139,6 +153,33 @@
return this;
}
+ public ReviewInput addUserToAttentionSet(String user, String reason) {
+ AttentionSetInput input = new AttentionSetInput();
+ input.user = user;
+ input.reason = reason;
+ if (addToAttentionSet == null) {
+ addToAttentionSet = new ArrayList<>();
+ }
+ addToAttentionSet.add(input);
+ return this;
+ }
+
+ public ReviewInput removeUserFromAttentionSet(String user, String reason) {
+ AttentionSetInput input = new AttentionSetInput();
+ input.user = user;
+ input.reason = reason;
+ if (removeFromAttentionSet == null) {
+ removeFromAttentionSet = new ArrayList<>();
+ }
+ removeFromAttentionSet.add(input);
+ return this;
+ }
+
+ public ReviewInput blockDefaultAttentionSetRules() {
+ ignoreDefaultAttentionSetRules = true;
+ return this;
+ }
+
public ReviewInput setWorkInProgress(boolean workInProgress) {
this.workInProgress = workInProgress;
ready = !workInProgress;
@@ -170,4 +211,8 @@
public static ReviewInput reject() {
return new ReviewInput().label("Code-Review", -2);
}
+
+ public static ReviewInput create() {
+ return new ReviewInput();
+ }
}
diff --git a/java/com/google/gerrit/extensions/client/ListOption.java b/java/com/google/gerrit/extensions/client/ListOption.java
index 4dea42f..dba2eee 100644
--- a/java/com/google/gerrit/extensions/client/ListOption.java
+++ b/java/com/google/gerrit/extensions/client/ListOption.java
@@ -48,9 +48,9 @@
return r;
}
- static String toHex(Set<ListChangesOption> options) {
+ static <T extends Enum<T> & ListOption> String toHex(Set<T> options) {
int v = 0;
- for (ListChangesOption option : options) {
+ for (T option : options) {
v |= 1 << option.getValue();
}
diff --git a/java/com/google/gerrit/extensions/common/AttentionSetEntry.java b/java/com/google/gerrit/extensions/common/AttentionSetInfo.java
similarity index 86%
rename from java/com/google/gerrit/extensions/common/AttentionSetEntry.java
rename to java/com/google/gerrit/extensions/common/AttentionSetInfo.java
index 356b38a..f29d32b 100644
--- a/java/com/google/gerrit/extensions/common/AttentionSetEntry.java
+++ b/java/com/google/gerrit/extensions/common/AttentionSetInfo.java
@@ -23,16 +23,16 @@
* <p>See <a href="https://www.gerritcodereview.com/design-docs/attention-set.html">here</a> for
* background.
*/
-public class AttentionSetEntry {
+public class AttentionSetInfo {
/** The user included in the attention set. */
- public AccountInfo accountInfo;
+ public AccountInfo account;
/** The timestamp of the last update. */
public Timestamp lastUpdate;
/** The human readable reason why the user was added. */
public String reason;
- public AttentionSetEntry(AccountInfo accountInfo, Timestamp lastUpdate, String reason) {
- this.accountInfo = accountInfo;
+ public AttentionSetInfo(AccountInfo account, Timestamp lastUpdate, String reason) {
+ this.account = account;
this.lastUpdate = lastUpdate;
this.reason = reason;
}
diff --git a/java/com/google/gerrit/extensions/common/ChangeInfo.java b/java/com/google/gerrit/extensions/common/ChangeInfo.java
index dce6fd1..190a97e 100644
--- a/java/com/google/gerrit/extensions/common/ChangeInfo.java
+++ b/java/com/google/gerrit/extensions/common/ChangeInfo.java
@@ -42,7 +42,7 @@
* for this change. Keyed by account ID. We don't use {@link
* com.google.gerrit.entities.Account.Id} to avoid a circular dependency.
*/
- public Map<Integer, AttentionSetEntry> attentionSet;
+ public Map<Integer, AttentionSetInfo> attentionSet;
public AccountInfo assignee;
public Collection<String> hashtags;
diff --git a/java/com/google/gerrit/mail/HtmlParser.java b/java/com/google/gerrit/mail/HtmlParser.java
index 7905a0a..2fc659d 100644
--- a/java/com/google/gerrit/mail/HtmlParser.java
+++ b/java/com/google/gerrit/mail/HtmlParser.java
@@ -18,7 +18,7 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterators;
import com.google.common.collect.PeekingIterator;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -60,7 +60,7 @@
* @return list of MailComments parsed from the html part of the email
*/
public static List<MailComment> parse(
- MailMessage email, Collection<Comment> comments, String changeUrl) {
+ MailMessage email, Collection<HumanComment> comments, String changeUrl) {
// TODO(hiesel) Add support for Gmail Mobile
// TODO(hiesel) Add tests for other popular email clients
@@ -71,10 +71,10 @@
// Gerrit as these are generally more reliable then the text captions.
List<MailComment> parsedComments = new ArrayList<>();
Document d = Jsoup.parse(email.htmlContent());
- PeekingIterator<Comment> iter = Iterators.peekingIterator(comments.iterator());
+ PeekingIterator<HumanComment> iter = Iterators.peekingIterator(comments.iterator());
String lastEncounteredFileName = null;
- Comment lastEncounteredComment = null;
+ HumanComment lastEncounteredComment = null;
for (Element e : d.body().getAllElements()) {
String elementName = e.tagName();
boolean isInBlockQuote =
@@ -91,7 +91,7 @@
if (!iter.hasNext()) {
continue;
}
- Comment perspectiveComment = iter.peek();
+ HumanComment perspectiveComment = iter.peek();
if (href.equals(ParserUtil.filePath(changeUrl, perspectiveComment))) {
if (lastEncounteredFileName == null
|| !lastEncounteredFileName.equals(perspectiveComment.key.filename)) {
diff --git a/java/com/google/gerrit/mail/MailComment.java b/java/com/google/gerrit/mail/MailComment.java
index f024f17..3e7da10 100644
--- a/java/com/google/gerrit/mail/MailComment.java
+++ b/java/com/google/gerrit/mail/MailComment.java
@@ -14,7 +14,7 @@
package com.google.gerrit.mail;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import java.util.Objects;
/** A comment parsed from inbound email */
@@ -26,7 +26,7 @@
}
CommentType type;
- Comment inReplyTo;
+ HumanComment inReplyTo;
String fileName;
String message;
boolean isLink;
@@ -34,7 +34,7 @@
public MailComment() {}
public MailComment(
- String message, String fileName, Comment inReplyTo, CommentType type, boolean isLink) {
+ String message, String fileName, HumanComment inReplyTo, CommentType type, boolean isLink) {
this.message = message;
this.fileName = fileName;
this.inReplyTo = inReplyTo;
@@ -46,7 +46,7 @@
return type;
}
- public Comment getInReplyTo() {
+ public HumanComment getInReplyTo() {
return inReplyTo;
}
diff --git a/java/com/google/gerrit/mail/TextParser.java b/java/com/google/gerrit/mail/TextParser.java
index dac3deb..a33c66f 100644
--- a/java/com/google/gerrit/mail/TextParser.java
+++ b/java/com/google/gerrit/mail/TextParser.java
@@ -18,7 +18,7 @@
import com.google.common.base.Strings;
import com.google.common.collect.Iterators;
import com.google.common.collect.PeekingIterator;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -31,15 +31,15 @@
* Parses comments from plaintext email.
*
* @param email @param email the message as received from the email service
- * @param comments list of {@link Comment}s previously persisted on the change that caused the
- * original notification email to be sent out. Ordering must be the same as in the outbound
- * email
+ * @param comments list of {@link HumanComment}s previously persisted on the change that caused
+ * the original notification email to be sent out. Ordering must be the same as in the
+ * outbound email
* @param changeUrl canonical change url that points to the change on this Gerrit instance.
* Example: https://go-review.googlesource.com/#/c/91570
* @return list of MailComments parsed from the plaintext part of the email
*/
public static List<MailComment> parse(
- MailMessage email, Collection<Comment> comments, String changeUrl) {
+ MailMessage email, Collection<HumanComment> comments, String changeUrl) {
String body = email.textContent();
// Replace CR-LF by \n
body = body.replace("\r\n", "\n");
@@ -62,11 +62,11 @@
body = body.replace(doubleQuotePattern, singleQuotePattern);
}
- PeekingIterator<Comment> iter = Iterators.peekingIterator(comments.iterator());
+ PeekingIterator<HumanComment> iter = Iterators.peekingIterator(comments.iterator());
MailComment currentComment = null;
String lastEncounteredFileName = null;
- Comment lastEncounteredComment = null;
+ HumanComment lastEncounteredComment = null;
for (String line : Splitter.on('\n').split(body)) {
if (line.equals(">")) {
// Skip empty lines
@@ -89,7 +89,7 @@
if (!iter.hasNext()) {
continue;
}
- Comment perspectiveComment = iter.peek();
+ HumanComment perspectiveComment = iter.peek();
if (line.equals(ParserUtil.filePath(changeUrl, perspectiveComment))) {
if (lastEncounteredFileName == null
|| !lastEncounteredFileName.equals(perspectiveComment.key.filename)) {
diff --git a/java/com/google/gerrit/server/CommentsUtil.java b/java/com/google/gerrit/server/CommentsUtil.java
index e8b44aa..0b3d1cb 100644
--- a/java/com/google/gerrit/server/CommentsUtil.java
+++ b/java/com/google/gerrit/server/CommentsUtil.java
@@ -28,6 +28,7 @@
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.ChangeMessage;
import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.Patch;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.RefNames;
@@ -116,7 +117,7 @@
this.serverId = serverId;
}
- public Comment newComment(
+ public HumanComment newHumanComment(
ChangeContext ctx,
String path,
PatchSet.Id psId,
@@ -132,15 +133,15 @@
} else {
// Inherit unresolved value from inReplyTo comment if not specified.
Comment.Key key = new Comment.Key(parentUuid, path, psId.get());
- Optional<Comment> parent = getPublished(ctx.getNotes(), key);
+ Optional<HumanComment> parent = getPublishedHumanComment(ctx.getNotes(), key);
if (!parent.isPresent()) {
throw new UnprocessableEntityException("Invalid parentUuid supplied for comment");
}
unresolved = parent.get().unresolved;
}
}
- Comment c =
- new Comment(
+ HumanComment c =
+ new HumanComment(
new Comment.Key(ChangeUtil.messageUuid(), path, psId.get()),
ctx.getUser().getAccountId(),
ctx.getWhen(),
@@ -175,19 +176,21 @@
return c;
}
- public Optional<Comment> getPublished(ChangeNotes notes, Comment.Key key) {
- return publishedByChange(notes).stream().filter(c -> key.equals(c.key)).findFirst();
+ public Optional<HumanComment> getPublishedHumanComment(ChangeNotes notes, Comment.Key key) {
+ return publishedHumanCommentsByChange(notes).stream()
+ .filter(c -> key.equals(c.key))
+ .findFirst();
}
- public Optional<Comment> getDraft(ChangeNotes notes, IdentifiedUser user, Comment.Key key) {
+ public Optional<HumanComment> getDraft(ChangeNotes notes, IdentifiedUser user, Comment.Key key) {
return draftByChangeAuthor(notes, user.getAccountId()).stream()
.filter(c -> key.equals(c.key))
.findFirst();
}
- public List<Comment> publishedByChange(ChangeNotes notes) {
+ public List<HumanComment> publishedHumanCommentsByChange(ChangeNotes notes) {
notes.load();
- return sort(Lists.newArrayList(notes.getComments().values()));
+ return sort(Lists.newArrayList(notes.getHumanComments().values()));
}
public List<RobotComment> robotCommentsByChange(ChangeNotes notes) {
@@ -195,8 +198,8 @@
return sort(Lists.newArrayList(notes.getRobotComments().values()));
}
- public List<Comment> draftByChange(ChangeNotes notes) {
- List<Comment> comments = new ArrayList<>();
+ public List<HumanComment> draftByChange(ChangeNotes notes) {
+ List<HumanComment> comments = new ArrayList<>();
for (Ref ref : getDraftRefs(notes.getChangeId())) {
Account.Id account = Account.Id.fromRefSuffix(ref.getName());
if (account != null) {
@@ -206,8 +209,8 @@
return sort(comments);
}
- public List<Comment> byPatchSet(ChangeNotes notes, PatchSet.Id psId) {
- List<Comment> comments = new ArrayList<>();
+ public List<HumanComment> byPatchSet(ChangeNotes notes, PatchSet.Id psId) {
+ List<HumanComment> comments = new ArrayList<>();
comments.addAll(publishedByPatchSet(notes, psId));
for (Ref ref : getDraftRefs(notes.getChangeId())) {
@@ -219,13 +222,13 @@
return sort(comments);
}
- public List<Comment> publishedByChangeFile(ChangeNotes notes, String file) {
- return commentsOnFile(notes.load().getComments().values(), file);
+ public List<HumanComment> publishedByChangeFile(ChangeNotes notes, String file) {
+ return commentsOnFile(notes.load().getHumanComments().values(), file);
}
- public List<Comment> publishedByPatchSet(ChangeNotes notes, PatchSet.Id psId) {
+ public List<HumanComment> publishedByPatchSet(ChangeNotes notes, PatchSet.Id psId) {
return removeCommentsOnAncestorOfCommitMessage(
- commentsOnPatchSet(notes.load().getComments().values(), psId));
+ commentsOnPatchSet(notes.load().getHumanComments().values(), psId));
}
public List<RobotComment> robotCommentsByPatchSet(ChangeNotes notes, PatchSet.Id psId) {
@@ -288,29 +291,31 @@
* auto-merge was done. From that time there may still be comments on the auto-merge commit
* message and those we want to filter out.
*/
- private List<Comment> removeCommentsOnAncestorOfCommitMessage(List<Comment> list) {
+ private List<HumanComment> removeCommentsOnAncestorOfCommitMessage(List<HumanComment> list) {
return list.stream()
.filter(c -> c.side != 0 || !Patch.COMMIT_MSG.equals(c.key.filename))
.collect(toList());
}
- public List<Comment> draftByPatchSetAuthor(
+ public List<HumanComment> draftByPatchSetAuthor(
PatchSet.Id psId, Account.Id author, ChangeNotes notes) {
return commentsOnPatchSet(notes.load().getDraftComments(author).values(), psId);
}
- public List<Comment> draftByChangeFileAuthor(ChangeNotes notes, String file, Account.Id author) {
+ public List<HumanComment> draftByChangeFileAuthor(
+ ChangeNotes notes, String file, Account.Id author) {
return commentsOnFile(notes.load().getDraftComments(author).values(), file);
}
- public List<Comment> draftByChangeAuthor(ChangeNotes notes, Account.Id author) {
- List<Comment> comments = new ArrayList<>();
+ public List<HumanComment> draftByChangeAuthor(ChangeNotes notes, Account.Id author) {
+ List<HumanComment> comments = new ArrayList<>();
comments.addAll(notes.getDraftComments(author).values());
return sort(comments);
}
- public void putComments(ChangeUpdate update, Comment.Status status, Iterable<Comment> comments) {
- for (Comment c : comments) {
+ public void putHumanComments(
+ ChangeUpdate update, HumanComment.Status status, Iterable<HumanComment> comments) {
+ for (HumanComment c : comments) {
update.putComment(status, c);
}
}
@@ -321,8 +326,8 @@
}
}
- public void deleteComments(ChangeUpdate update, Iterable<Comment> comments) {
- for (Comment c : comments) {
+ public void deleteHumanComments(ChangeUpdate update, Iterable<HumanComment> comments) {
+ for (HumanComment c : comments) {
update.deleteComment(c);
}
}
@@ -332,9 +337,10 @@
update.deleteCommentByRewritingHistory(commentKey.uuid, newMessage);
}
- private static List<Comment> commentsOnFile(Collection<Comment> allComments, String file) {
- List<Comment> result = new ArrayList<>(allComments.size());
- for (Comment c : allComments) {
+ private static List<HumanComment> commentsOnFile(
+ Collection<HumanComment> allComments, String file) {
+ List<HumanComment> result = new ArrayList<>(allComments.size());
+ for (HumanComment c : allComments) {
String currentFilename = c.key.filename;
if (currentFilename.equals(file)) {
result.add(c);
diff --git a/java/com/google/gerrit/server/PublishCommentUtil.java b/java/com/google/gerrit/server/PublishCommentUtil.java
index 3d34d6b..658af15 100644
--- a/java/com/google/gerrit/server/PublishCommentUtil.java
+++ b/java/com/google/gerrit/server/PublishCommentUtil.java
@@ -20,8 +20,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
-import com.google.gerrit.entities.Comment;
-import com.google.gerrit.entities.Comment.Status;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.validators.CommentForValidation;
@@ -60,7 +59,7 @@
public void publish(
ChangeContext ctx,
ChangeUpdate changeUpdate,
- Collection<Comment> draftComments,
+ Collection<HumanComment> draftComments,
@Nullable String tag) {
ChangeNotes notes = ctx.getNotes();
checkArgument(notes != null);
@@ -70,8 +69,8 @@
Map<PatchSet.Id, PatchSet> patchSets =
psUtil.getAsMap(notes, draftComments.stream().map(d -> psId(notes, d)).collect(toSet()));
- Set<Comment> commentsToPublish = new HashSet<>();
- for (Comment draftComment : draftComments) {
+ Set<HumanComment> commentsToPublish = new HashSet<>();
+ for (HumanComment draftComment : draftComments) {
PatchSet.Id psIdOfDraftComment = psId(notes, draftComment);
PatchSet ps = patchSets.get(psIdOfDraftComment);
if (ps == null) {
@@ -109,10 +108,10 @@
}
commentsToPublish.add(draftComment);
}
- commentsUtil.putComments(changeUpdate, Status.PUBLISHED, commentsToPublish);
+ commentsUtil.putHumanComments(changeUpdate, HumanComment.Status.PUBLISHED, commentsToPublish);
}
- private static PatchSet.Id psId(ChangeNotes notes, Comment c) {
+ private static PatchSet.Id psId(ChangeNotes notes, HumanComment c) {
return PatchSet.id(notes.getChangeId(), c.key.patchSetId);
}
diff --git a/java/com/google/gerrit/server/PublishCommentsOp.java b/java/com/google/gerrit/server/PublishCommentsOp.java
index 745755b..358ce92 100644
--- a/java/com/google/gerrit/server/PublishCommentsOp.java
+++ b/java/com/google/gerrit/server/PublishCommentsOp.java
@@ -16,7 +16,7 @@
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.entities.ChangeMessage;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Project;
import com.google.gerrit.exceptions.StorageException;
@@ -58,7 +58,7 @@
private final PatchSet.Id psId;
private final PublishCommentUtil publishCommentUtil;
- private List<Comment> comments = new ArrayList<>();
+ private List<HumanComment> comments = new ArrayList<>();
private ChangeMessage message;
private IdentifiedUser user;
diff --git a/java/com/google/gerrit/server/api/changes/AttentionSetApiImpl.java b/java/com/google/gerrit/server/api/changes/AttentionSetApiImpl.java
index 8dc44b7..6c79296 100644
--- a/java/com/google/gerrit/server/api/changes/AttentionSetApiImpl.java
+++ b/java/com/google/gerrit/server/api/changes/AttentionSetApiImpl.java
@@ -17,7 +17,7 @@
import static com.google.gerrit.server.api.ApiUtil.asRestApiException;
import com.google.gerrit.extensions.api.changes.AttentionSetApi;
-import com.google.gerrit.extensions.api.changes.RemoveFromAttentionSetInput;
+import com.google.gerrit.extensions.api.changes.AttentionSetInput;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.server.change.AttentionSetEntryResource;
import com.google.gerrit.server.restapi.change.RemoveFromAttentionSet;
@@ -41,7 +41,7 @@
}
@Override
- public void remove(RemoveFromAttentionSetInput input) throws RestApiException {
+ public void remove(AttentionSetInput input) throws RestApiException {
try {
removeFromAttentionSet.apply(attentionSetEntryResource, input);
} catch (Exception e) {
diff --git a/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java b/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java
index 5122f8a..b4a5da7 100644
--- a/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java
+++ b/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java
@@ -23,9 +23,9 @@
import com.google.gerrit.extensions.api.changes.AbandonInput;
import com.google.gerrit.extensions.api.changes.AddReviewerInput;
import com.google.gerrit.extensions.api.changes.AddReviewerResult;
-import com.google.gerrit.extensions.api.changes.AddToAttentionSetInput;
import com.google.gerrit.extensions.api.changes.AssigneeInput;
import com.google.gerrit.extensions.api.changes.AttentionSetApi;
+import com.google.gerrit.extensions.api.changes.AttentionSetInput;
import com.google.gerrit.extensions.api.changes.ChangeApi;
import com.google.gerrit.extensions.api.changes.ChangeEditApi;
import com.google.gerrit.extensions.api.changes.ChangeMessageApi;
@@ -543,7 +543,7 @@
}
@Override
- public AccountInfo addToAttentionSet(AddToAttentionSetInput input) throws RestApiException {
+ public AccountInfo addToAttentionSet(AttentionSetInput input) throws RestApiException {
try {
return addToAttentionSet.apply(change, input).value();
} catch (Exception e) {
diff --git a/java/com/google/gerrit/server/api/changes/CommentApiImpl.java b/java/com/google/gerrit/server/api/changes/CommentApiImpl.java
index c5fcab1..35dd9c1 100644
--- a/java/com/google/gerrit/server/api/changes/CommentApiImpl.java
+++ b/java/com/google/gerrit/server/api/changes/CommentApiImpl.java
@@ -20,7 +20,7 @@
import com.google.gerrit.extensions.api.changes.DeleteCommentInput;
import com.google.gerrit.extensions.common.CommentInfo;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.server.change.CommentResource;
+import com.google.gerrit.server.change.HumanCommentResource;
import com.google.gerrit.server.restapi.change.DeleteComment;
import com.google.gerrit.server.restapi.change.GetComment;
import com.google.inject.Inject;
@@ -28,16 +28,16 @@
class CommentApiImpl implements CommentApi {
interface Factory {
- CommentApiImpl create(CommentResource c);
+ CommentApiImpl create(HumanCommentResource c);
}
private final GetComment getComment;
private final DeleteComment deleteComment;
- private final CommentResource comment;
+ private final HumanCommentResource comment;
@Inject
CommentApiImpl(
- GetComment getComment, DeleteComment deleteComment, @Assisted CommentResource comment) {
+ GetComment getComment, DeleteComment deleteComment, @Assisted HumanCommentResource comment) {
this.getComment = getComment;
this.deleteComment = deleteComment;
this.comment = comment;
diff --git a/java/com/google/gerrit/server/change/AddToAttentionSetOp.java b/java/com/google/gerrit/server/change/AddToAttentionSetOp.java
index 829c290..48de684 100644
--- a/java/com/google/gerrit/server/change/AddToAttentionSetOp.java
+++ b/java/com/google/gerrit/server/change/AddToAttentionSetOp.java
@@ -14,23 +14,16 @@
package com.google.gerrit.server.change;
-import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static java.util.Objects.requireNonNull;
-import com.google.common.collect.ImmutableSet;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.AttentionSetUpdate;
-import com.google.gerrit.entities.AttentionSetUpdate.Operation;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.notedb.ChangeUpdate;
-import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
-import java.util.Map;
-import java.util.function.Function;
/** Add a specified user to the attention set. */
public class AddToAttentionSetOp implements BatchUpdateOp {
@@ -39,47 +32,27 @@
AddToAttentionSetOp create(Account.Id attentionUserId, String reason);
}
- private final ChangeData.Factory changeDataFactory;
- private final ChangeMessagesUtil cmUtil;
private final Account.Id attentionUserId;
private final String reason;
+ /**
+ * Add a specified user to the attention set.
+ *
+ * @param attentionUserId the id of the user we want to add to the attention set.
+ * @param reason The reason for adding that user.
+ */
@Inject
- AddToAttentionSetOp(
- ChangeData.Factory changeDataFactory,
- ChangeMessagesUtil cmUtil,
- @Assisted Account.Id attentionUserId,
- @Assisted String reason) {
- this.changeDataFactory = changeDataFactory;
- this.cmUtil = cmUtil;
+ AddToAttentionSetOp(@Assisted Account.Id attentionUserId, @Assisted String reason) {
this.attentionUserId = requireNonNull(attentionUserId, "user");
this.reason = requireNonNull(reason, "reason");
}
@Override
public boolean updateChange(ChangeContext ctx) throws RestApiException {
- ChangeData changeData = changeDataFactory.create(ctx.getNotes());
- Map<Account.Id, AttentionSetUpdate> attentionMap =
- changeData.attentionSet().stream()
- .collect(toImmutableMap(AttentionSetUpdate::account, Function.identity()));
- AttentionSetUpdate existingEntry = attentionMap.get(attentionUserId);
- if (existingEntry != null && existingEntry.operation() == Operation.ADD) {
- return false;
- }
-
ChangeUpdate update = ctx.getUpdate(ctx.getChange().currentPatchSetId());
- update.setAttentionSetUpdates(
- ImmutableSet.of(
- AttentionSetUpdate.createForWrite(
- attentionUserId, AttentionSetUpdate.Operation.ADD, reason)));
- addMessage(ctx, update);
+ update.addToPlannedAttentionSetUpdates(
+ AttentionSetUpdate.createForWrite(
+ attentionUserId, AttentionSetUpdate.Operation.ADD, reason));
return true;
}
-
- private void addMessage(ChangeContext ctx, ChangeUpdate update) {
- String message = "Added to attention set: " + attentionUserId;
- cmUtil.addChangeMessage(
- update,
- ChangeMessagesUtil.newMessage(ctx, message, ChangeMessagesUtil.TAG_UPDATE_ATTENTION_SET));
- }
}
diff --git a/java/com/google/gerrit/server/change/AttentionSetUnchangedOp.java b/java/com/google/gerrit/server/change/AttentionSetUnchangedOp.java
new file mode 100644
index 0000000..cfb54e1
--- /dev/null
+++ b/java/com/google/gerrit/server/change/AttentionSetUnchangedOp.java
@@ -0,0 +1,34 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.change;
+
+import com.google.gerrit.extensions.restapi.RestApiException;
+import com.google.gerrit.server.notedb.ChangeUpdate;
+import com.google.gerrit.server.update.BatchUpdateOp;
+import com.google.gerrit.server.update.ChangeContext;
+
+/**
+ * Ensures that the attention set will not be changed, thus blocks {@link RemoveFromAttentionSetOp}
+ * and {@link AddToAttentionSetOp}.
+ */
+public class AttentionSetUnchangedOp implements BatchUpdateOp {
+
+ @Override
+ public boolean updateChange(ChangeContext ctx) throws RestApiException {
+ ChangeUpdate update = ctx.getUpdate(ctx.getChange().currentPatchSetId());
+ update.ignoreDefaultAttentionSetRules();
+ return true;
+ }
+}
diff --git a/java/com/google/gerrit/server/change/ChangeJson.java b/java/com/google/gerrit/server/change/ChangeJson.java
index 8f97b68..d0e9288 100644
--- a/java/com/google/gerrit/server/change/ChangeJson.java
+++ b/java/com/google/gerrit/server/change/ChangeJson.java
@@ -62,7 +62,7 @@
import com.google.gerrit.extensions.client.ReviewerState;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.ApprovalInfo;
-import com.google.gerrit.extensions.common.AttentionSetEntry;
+import com.google.gerrit.extensions.common.AttentionSetInfo;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.ChangeMessageInfo;
import com.google.gerrit.extensions.common.LabelInfo;
@@ -515,7 +515,7 @@
toImmutableMap(
a -> a.account().get(),
a ->
- new AttentionSetEntry(
+ new AttentionSetInfo(
accountLoader.get(a.account()),
Timestamp.from(a.timestamp()),
a.reason())));
diff --git a/java/com/google/gerrit/server/change/DraftCommentResource.java b/java/com/google/gerrit/server/change/DraftCommentResource.java
index 3d3e8f9..e0648cf 100644
--- a/java/com/google/gerrit/server/change/DraftCommentResource.java
+++ b/java/com/google/gerrit/server/change/DraftCommentResource.java
@@ -15,7 +15,7 @@
package com.google.gerrit.server.change;
import com.google.gerrit.entities.Change;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.extensions.restapi.RestResource;
import com.google.gerrit.extensions.restapi.RestView;
@@ -27,9 +27,9 @@
new TypeLiteral<RestView<DraftCommentResource>>() {};
private final RevisionResource rev;
- private final Comment comment;
+ private final HumanComment comment;
- public DraftCommentResource(RevisionResource rev, Comment c) {
+ public DraftCommentResource(RevisionResource rev, HumanComment c) {
this.rev = rev;
this.comment = c;
}
@@ -46,7 +46,7 @@
return rev.getPatchSet();
}
- public Comment getComment() {
+ public HumanComment getComment() {
return comment;
}
diff --git a/java/com/google/gerrit/server/change/EmailReviewComments.java b/java/com/google/gerrit/server/change/EmailReviewComments.java
index f1eff6f..b30a6a3 100644
--- a/java/com/google/gerrit/server/change/EmailReviewComments.java
+++ b/java/com/google/gerrit/server/change/EmailReviewComments.java
@@ -65,7 +65,7 @@
PatchSet patchSet,
IdentifiedUser user,
ChangeMessage message,
- List<Comment> comments,
+ List<? extends Comment> comments,
String patchSetComment,
List<LabelVote> labels,
RepoView repoView);
@@ -82,7 +82,7 @@
private final PatchSet patchSet;
private final IdentifiedUser user;
private final ChangeMessage message;
- private final List<Comment> comments;
+ private final List<? extends Comment> comments;
private final String patchSetComment;
private final List<LabelVote> labels;
private final RepoView repoView;
@@ -99,7 +99,7 @@
@Assisted PatchSet patchSet,
@Assisted IdentifiedUser user,
@Assisted ChangeMessage message,
- @Assisted List<Comment> comments,
+ @Assisted List<? extends Comment> comments,
@Nullable @Assisted String patchSetComment,
@Assisted List<LabelVote> labels,
@Assisted RepoView repoView) {
diff --git a/java/com/google/gerrit/server/change/CommentResource.java b/java/com/google/gerrit/server/change/HumanCommentResource.java
similarity index 76%
rename from java/com/google/gerrit/server/change/CommentResource.java
rename to java/com/google/gerrit/server/change/HumanCommentResource.java
index dbe7a76..1611aaa 100644
--- a/java/com/google/gerrit/server/change/CommentResource.java
+++ b/java/com/google/gerrit/server/change/HumanCommentResource.java
@@ -15,20 +15,20 @@
package com.google.gerrit.server.change;
import com.google.gerrit.entities.Account;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.extensions.restapi.RestResource;
import com.google.gerrit.extensions.restapi.RestView;
import com.google.inject.TypeLiteral;
-public class CommentResource implements RestResource {
- public static final TypeLiteral<RestView<CommentResource>> COMMENT_KIND =
- new TypeLiteral<RestView<CommentResource>>() {};
+public class HumanCommentResource implements RestResource {
+ public static final TypeLiteral<RestView<HumanCommentResource>> COMMENT_KIND =
+ new TypeLiteral<RestView<HumanCommentResource>>() {};
private final RevisionResource rev;
- private final Comment comment;
+ private final HumanComment comment;
- public CommentResource(RevisionResource rev, Comment c) {
+ public HumanCommentResource(RevisionResource rev, HumanComment c) {
this.rev = rev;
this.comment = c;
}
@@ -37,7 +37,7 @@
return rev.getPatchSet();
}
- public Comment getComment() {
+ public HumanComment getComment() {
return comment;
}
diff --git a/java/com/google/gerrit/server/change/RemoveFromAttentionSetOp.java b/java/com/google/gerrit/server/change/RemoveFromAttentionSetOp.java
index 07f0d78..6be1343 100644
--- a/java/com/google/gerrit/server/change/RemoveFromAttentionSetOp.java
+++ b/java/com/google/gerrit/server/change/RemoveFromAttentionSetOp.java
@@ -14,23 +14,17 @@
package com.google.gerrit.server.change;
-import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static java.util.Objects.requireNonNull;
-import com.google.common.collect.ImmutableSet;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.AttentionSetUpdate;
import com.google.gerrit.entities.AttentionSetUpdate.Operation;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.notedb.ChangeUpdate;
-import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
-import java.util.Map;
-import java.util.function.Function;
/** Remove a specified user from the attention set. */
public class RemoveFromAttentionSetOp implements BatchUpdateOp {
@@ -39,46 +33,26 @@
RemoveFromAttentionSetOp create(Account.Id attentionUserId, String reason);
}
- private final ChangeData.Factory changeDataFactory;
- private final ChangeMessagesUtil cmUtil;
private final Account.Id attentionUserId;
private final String reason;
+ /**
+ * Remove a specified user from the attention set.
+ *
+ * @param attentionUserId the id of the user we want to add to the attention set.
+ * @param reason The reason for adding that user.
+ */
@Inject
- RemoveFromAttentionSetOp(
- ChangeData.Factory changeDataFactory,
- ChangeMessagesUtil cmUtil,
- @Assisted Account.Id attentionUserId,
- @Assisted String reason) {
- this.changeDataFactory = changeDataFactory;
- this.cmUtil = cmUtil;
+ RemoveFromAttentionSetOp(@Assisted Account.Id attentionUserId, @Assisted String reason) {
this.attentionUserId = requireNonNull(attentionUserId, "user");
this.reason = requireNonNull(reason, "reason");
}
@Override
public boolean updateChange(ChangeContext ctx) throws RestApiException {
- ChangeData changeData = changeDataFactory.create(ctx.getNotes());
- Map<Account.Id, AttentionSetUpdate> attentionMap =
- changeData.attentionSet().stream()
- .collect(toImmutableMap(AttentionSetUpdate::account, Function.identity()));
- AttentionSetUpdate existingEntry = attentionMap.get(attentionUserId);
- if (existingEntry == null || existingEntry.operation() == Operation.REMOVE) {
- return false;
- }
-
ChangeUpdate update = ctx.getUpdate(ctx.getChange().currentPatchSetId());
- update.setAttentionSetUpdates(
- ImmutableSet.of(
- AttentionSetUpdate.createForWrite(attentionUserId, Operation.REMOVE, reason)));
- addMessage(ctx, update);
+ update.addToPlannedAttentionSetUpdates(
+ AttentionSetUpdate.createForWrite(attentionUserId, Operation.REMOVE, reason));
return true;
}
-
- private void addMessage(ChangeContext ctx, ChangeUpdate update) {
- String message = "Removed from attention set: " + attentionUserId;
- cmUtil.addChangeMessage(
- update,
- ChangeMessagesUtil.newMessage(ctx, message, ChangeMessagesUtil.TAG_UPDATE_ATTENTION_SET));
- }
}
diff --git a/java/com/google/gerrit/server/config/SitePaths.java b/java/com/google/gerrit/server/config/SitePaths.java
index ee95c6f..5e268da 100644
--- a/java/com/google/gerrit/server/config/SitePaths.java
+++ b/java/com/google/gerrit/server/config/SitePaths.java
@@ -30,6 +30,7 @@
public static final String HEADER_FILENAME = "GerritSiteHeader.html";
public static final String FOOTER_FILENAME = "GerritSiteFooter.html";
public static final String THEME_FILENAME = "gerrit-theme.html";
+ public static final String THEME_JS_FILENAME = "gerrit-theme.js";
public final Path site_path;
public final Path bin_dir;
@@ -69,6 +70,7 @@
public final Path site_header;
public final Path site_footer;
public final Path site_theme; // For PolyGerrit UI only.
+ public final Path site_theme_js; // For PolyGerrit UI only.
public final Path site_gitweb;
/** {@code true} if {@link #site_path} has not been initialized. */
@@ -119,6 +121,7 @@
// For PolyGerrit UI.
site_theme = static_dir.resolve(THEME_FILENAME);
+ site_theme_js = static_dir.resolve(THEME_JS_FILENAME);
boolean isNew;
try (DirectoryStream<Path> files = Files.newDirectoryStream(site_path)) {
diff --git a/java/com/google/gerrit/server/events/EventFactory.java b/java/com/google/gerrit/server/events/EventFactory.java
index f0da560..19d2f3d 100644
--- a/java/com/google/gerrit/server/events/EventFactory.java
+++ b/java/com/google/gerrit/server/events/EventFactory.java
@@ -28,7 +28,7 @@
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.ChangeMessage;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.PatchSetApproval;
import com.google.gerrit.entities.UserIdentity;
@@ -380,8 +380,8 @@
}
public void addPatchSetComments(
- PatchSetAttribute patchSetAttribute, Collection<Comment> comments) {
- for (Comment comment : comments) {
+ PatchSetAttribute patchSetAttribute, Collection<HumanComment> comments) {
+ for (HumanComment comment : comments) {
if (comment.key.patchSetId == patchSetAttribute.number) {
if (patchSetAttribute.comments == null) {
patchSetAttribute.comments = new ArrayList<>();
@@ -547,7 +547,7 @@
return a;
}
- public PatchSetCommentAttribute asPatchSetLineAttribute(Comment c) {
+ public PatchSetCommentAttribute asPatchSetLineAttribute(HumanComment c) {
PatchSetCommentAttribute a = new PatchSetCommentAttribute();
a.reviewer = asAccountAttribute(c.author.getId());
a.file = c.key.filename;
diff --git a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
index 404fa3c..5436db7 100644
--- a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
+++ b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
@@ -69,7 +69,7 @@
import com.google.gerrit.entities.BooleanProjectConfig;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.PatchSetInfo;
import com.google.gerrit.entities.Project;
@@ -2022,7 +2022,7 @@
}
if (magicBranch != null && magicBranch.shouldPublishComments()) {
- List<Comment> drafts =
+ List<HumanComment> drafts =
commentsUtil.draftByChangeAuthor(
notesFactory.createChecked(change), user.getAccountId());
ImmutableList<CommentForValidation> draftsForValidation =
@@ -2144,9 +2144,10 @@
// A's group.
// C) Commit is a PatchSet of a pre-existing change uploaded with a
// different target branch.
- for (Ref ref : existingRefs) {
- updateGroups.add(new UpdateGroupsRequest(ref, c));
- }
+ existingRefs.stream()
+ .map(r -> PatchSet.Id.fromRef(r.getName()))
+ .filter(Objects::nonNull)
+ .forEach(i -> updateGroups.add(new UpdateGroupsRequest(i, c)));
if (!(newChangeForAllNotInTarget || magicBranch.base != null)) {
continue;
}
@@ -3019,8 +3020,8 @@
final RevCommit commit;
List<String> groups = ImmutableList.of();
- UpdateGroupsRequest(Ref ref, RevCommit commit) {
- this.psId = requireNonNull(PatchSet.Id.fromRef(ref.getName()));
+ UpdateGroupsRequest(PatchSet.Id psId, RevCommit commit) {
+ this.psId = psId;
this.commit = commit;
}
diff --git a/java/com/google/gerrit/server/git/validators/CommentCountValidator.java b/java/com/google/gerrit/server/git/validators/CommentCountValidator.java
index 67aa3bd..a554f90 100644
--- a/java/com/google/gerrit/server/git/validators/CommentCountValidator.java
+++ b/java/com/google/gerrit/server/git/validators/CommentCountValidator.java
@@ -45,7 +45,7 @@
ChangeNotes notes =
notesFactory.createChecked(Project.nameKey(ctx.getProject()), Change.id(ctx.getChangeId()));
int numExistingCommentsAndChangeMessages =
- notes.getComments().size()
+ notes.getHumanComments().size()
+ notes.getRobotComments().size()
+ notes.getChangeMessages().size();
if (!comments.isEmpty()
diff --git a/java/com/google/gerrit/server/git/validators/CommentCumulativeSizeValidator.java b/java/com/google/gerrit/server/git/validators/CommentCumulativeSizeValidator.java
index d9a1420..d507531 100644
--- a/java/com/google/gerrit/server/git/validators/CommentCumulativeSizeValidator.java
+++ b/java/com/google/gerrit/server/git/validators/CommentCumulativeSizeValidator.java
@@ -51,7 +51,7 @@
notesFactory.createChecked(Project.nameKey(ctx.getProject()), Change.id(ctx.getChangeId()));
int existingCumulativeSize =
Stream.concat(
- notes.getComments().values().stream(),
+ notes.getHumanComments().values().stream(),
notes.getRobotComments().values().stream())
.mapToInt(Comment::getApproximateSize)
.sum()
diff --git a/java/com/google/gerrit/server/mail/receive/MailProcessor.java b/java/com/google/gerrit/server/mail/receive/MailProcessor.java
index f004e4b..b38bef6 100644
--- a/java/com/google/gerrit/server/mail/receive/MailProcessor.java
+++ b/java/com/google/gerrit/server/mail/receive/MailProcessor.java
@@ -24,7 +24,7 @@
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.ChangeMessage;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Project;
import com.google.gerrit.exceptions.StorageException;
@@ -257,7 +257,7 @@
// Get all comments; filter and sort them to get the original list of
// comments from the outbound email.
// TODO(hiesel) Also filter by original comment author.
- Collection<Comment> comments =
+ Collection<HumanComment> comments =
cd.publishedComments().stream()
.filter(c -> (c.writtenOn.getTime() / 1000) == (metadata.timestamp.getTime() / 1000))
.sorted(CommentsUtil.COMMENT_ORDER)
@@ -319,7 +319,7 @@
private final List<MailComment> parsedComments;
private final String tag;
private ChangeMessage changeMessage;
- private List<Comment> comments;
+ private List<HumanComment> comments;
private PatchSet patchSet;
private ChangeNotes notes;
@@ -349,8 +349,10 @@
comments.add(
persistentCommentFromMailComment(ctx, c, targetPatchSetForComment(ctx, c, patchSet)));
}
- commentsUtil.putComments(
- ctx.getUpdate(ctx.getChange().currentPatchSetId()), Comment.Status.PUBLISHED, comments);
+ commentsUtil.putHumanComments(
+ ctx.getUpdate(ctx.getChange().currentPatchSetId()),
+ HumanComment.Status.PUBLISHED,
+ comments);
return true;
}
@@ -416,7 +418,7 @@
return current;
}
- private Comment persistentCommentFromMailComment(
+ private HumanComment persistentCommentFromMailComment(
ChangeContext ctx, MailComment mailComment, PatchSet patchSetForComment)
throws UnprocessableEntityException, PatchListNotAvailableException {
String fileName;
@@ -431,8 +433,8 @@
side = Side.REVISION;
}
- Comment comment =
- commentsUtil.newComment(
+ HumanComment comment =
+ commentsUtil.newHumanComment(
ctx,
fileName,
patchSetForComment.id(),
diff --git a/java/com/google/gerrit/server/mail/send/CommentSender.java b/java/com/google/gerrit/server/mail/send/CommentSender.java
index f3cccf2..0ba5da51 100644
--- a/java/com/google/gerrit/server/mail/send/CommentSender.java
+++ b/java/com/google/gerrit/server/mail/send/CommentSender.java
@@ -22,6 +22,7 @@
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.KeyUtil;
import com.google.gerrit.entities.Patch;
import com.google.gerrit.entities.Project;
@@ -114,7 +115,7 @@
}
}
- private List<Comment> inlineComments = Collections.emptyList();
+ private List<? extends Comment> inlineComments = Collections.emptyList();
private String patchSetComment;
private List<LabelVote> labels = Collections.emptyList();
private final CommentsUtil commentsUtil;
@@ -136,7 +137,7 @@
this.replyToAddress = cfg.getString("sendemail", null, "replyToAddress");
}
- public void setComments(List<Comment> comments) {
+ public void setComments(List<? extends Comment> comments) {
inlineComments = comments;
}
@@ -244,23 +245,21 @@
/** Get the set of accounts whose comments have been replied to in this email. */
private HashSet<Account.Id> getReplyAccounts() {
HashSet<Account.Id> replyAccounts = new HashSet<>();
-
// Track visited parent UUIDs to avoid cycles.
HashSet<String> visitedUuids = new HashSet<>();
for (Comment comment : inlineComments) {
visitedUuids.add(comment.key.uuid);
-
// Traverse the parent relation to the top of the comment thread.
Comment current = comment;
while (current.parentUuid != null && !visitedUuids.contains(current.parentUuid)) {
- Optional<Comment> optParent = getParent(current);
+ Optional<HumanComment> optParent = getParent(current);
if (!optParent.isPresent()) {
// There is a parent UUID, but it cannot be loaded, break from the comment thread.
break;
}
- Comment parent = optParent.get();
+ HumanComment parent = optParent.get();
replyAccounts.add(parent.author.getId());
visitedUuids.add(current.parentUuid);
current = parent;
@@ -307,14 +306,13 @@
* @return an optional comment that will be present if the given comment has a parent, and is
* empty if it does not.
*/
- private Optional<Comment> getParent(Comment child) {
+ private Optional<HumanComment> getParent(Comment child) {
if (child.parentUuid == null) {
return Optional.empty();
}
-
Comment.Key key = new Comment.Key(child.parentUuid, child.key.filename, child.key.patchSetId);
try {
- return commentsUtil.getPublished(changeData.notes(), key);
+ return commentsUtil.getPublishedHumanComment(changeData.notes(), key);
} catch (StorageException e) {
logger.atWarning().log("Could not find the parent of this comment: %s", child);
return Optional.empty();
@@ -448,7 +446,7 @@
// If the comment has a quote, don't bother loading the parent message.
if (!hasQuote(blocks)) {
// Set parent comment info.
- Optional<Comment> parent = getParent(comment);
+ Optional<HumanComment> parent = getParent(comment);
if (parent.isPresent()) {
commentData.put("parentMessage", getShortenedCommentMessage(parent.get()));
}
diff --git a/java/com/google/gerrit/server/notedb/ChangeDraftUpdate.java b/java/com/google/gerrit/server/notedb/ChangeDraftUpdate.java
index 07b58f2..57f6353 100644
--- a/java/com/google/gerrit/server/notedb/ChangeDraftUpdate.java
+++ b/java/com/google/gerrit/server/notedb/ChangeDraftUpdate.java
@@ -22,6 +22,7 @@
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.exceptions.StorageException;
@@ -82,13 +83,13 @@
FIXED
}
- private static Key key(Comment c) {
+ private static Key key(HumanComment c) {
return new AutoValue_ChangeDraftUpdate_Key(c.getCommitId(), c.key);
}
private final AllUsersName draftsProject;
- private List<Comment> put = new ArrayList<>();
+ private List<HumanComment> put = new ArrayList<>();
private Map<Key, DeleteReason> delete = new HashMap<>();
@AssistedInject
@@ -119,7 +120,7 @@
this.draftsProject = allUsers;
}
- public void putComment(Comment c) {
+ public void putComment(HumanComment c) {
checkState(!put.contains(c), "comment already added");
verifyComment(c);
put.add(c);
@@ -128,7 +129,7 @@
/**
* Marks a comment for deletion. Called when the comment is deleted because the user published it.
*/
- public void markCommentPublished(Comment c) {
+ public void markCommentPublished(HumanComment c) {
checkState(!delete.containsKey(key(c)), "comment already marked for deletion");
verifyComment(c);
delete.put(key(c), DeleteReason.PUBLISHED);
@@ -137,7 +138,7 @@
/**
* Marks a comment for deletion. Called when the comment is deleted because the user removed it.
*/
- public void deleteComment(Comment c) {
+ public void deleteComment(HumanComment c) {
checkState(!delete.containsKey(key(c)), "comment already marked for deletion");
verifyComment(c);
delete.put(key(c), DeleteReason.DELETED);
@@ -191,7 +192,7 @@
RevisionNoteMap<ChangeRevisionNote> rnm = getRevisionNoteMap(rw, curr);
RevisionNoteBuilder.Cache cache = new RevisionNoteBuilder.Cache(rnm);
- for (Comment c : put) {
+ for (HumanComment c : put) {
if (!delete.keySet().contains(key(c))) {
cache.get(c.getCommitId()).putComment(c);
}
@@ -259,7 +260,7 @@
// Even though reading from changes might not be enabled, we need to
// parse any existing revision notes so we can merge them.
return RevisionNoteMap.parse(
- noteUtil.getChangeNoteJson(), rw.getObjectReader(), noteMap, Comment.Status.DRAFT);
+ noteUtil.getChangeNoteJson(), rw.getObjectReader(), noteMap, HumanComment.Status.DRAFT);
}
@Override
diff --git a/java/com/google/gerrit/server/notedb/ChangeNotes.java b/java/com/google/gerrit/server/notedb/ChangeNotes.java
index 36a61cc0..cf854c7 100644
--- a/java/com/google/gerrit/server/notedb/ChangeNotes.java
+++ b/java/com/google/gerrit/server/notedb/ChangeNotes.java
@@ -45,6 +45,7 @@
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.ChangeMessage;
import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.PatchSetApproval;
import com.google.gerrit.entities.Project;
@@ -435,14 +436,14 @@
}
/** @return inline comments on each revision. */
- public ImmutableListMultimap<ObjectId, Comment> getComments() {
+ public ImmutableListMultimap<ObjectId, HumanComment> getHumanComments() {
return state.publishedComments();
}
public ImmutableSet<Comment.Key> getCommentKeys() {
if (commentKeys == null) {
ImmutableSet.Builder<Comment.Key> b = ImmutableSet.builder();
- for (Comment c : getComments().values()) {
+ for (Comment c : getHumanComments().values()) {
b.add(new Comment.Key(c.key));
}
commentKeys = b.build();
@@ -454,11 +455,11 @@
return state.updateCount();
}
- public ImmutableListMultimap<ObjectId, Comment> getDraftComments(Account.Id author) {
+ public ImmutableListMultimap<ObjectId, HumanComment> getDraftComments(Account.Id author) {
return getDraftComments(author, null);
}
- public ImmutableListMultimap<ObjectId, Comment> getDraftComments(
+ public ImmutableListMultimap<ObjectId, HumanComment> getDraftComments(
Account.Id author, @Nullable Ref ref) {
loadDraftComments(author, ref);
// Filter out any zombie draft comments. These are drafts that are also in
@@ -502,7 +503,7 @@
return robotCommentNotes;
}
- public boolean containsComment(Comment c) {
+ public boolean containsComment(HumanComment c) {
if (containsCommentPublished(c)) {
return true;
}
@@ -511,7 +512,7 @@
}
public boolean containsCommentPublished(Comment c) {
- for (Comment l : getComments().values()) {
+ for (Comment l : getHumanComments().values()) {
if (c.key.equals(l.key)) {
return true;
}
diff --git a/java/com/google/gerrit/server/notedb/ChangeNotesParser.java b/java/com/google/gerrit/server/notedb/ChangeNotesParser.java
index a884b70..f639f49 100644
--- a/java/com/google/gerrit/server/notedb/ChangeNotesParser.java
+++ b/java/com/google/gerrit/server/notedb/ChangeNotesParser.java
@@ -61,7 +61,7 @@
import com.google.gerrit.entities.AttentionSetUpdate;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.ChangeMessage;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.LabelId;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.PatchSetApproval;
@@ -121,7 +121,7 @@
private final List<AssigneeStatusUpdate> assigneeUpdates;
private final List<SubmitRecord> submitRecords;
- private final ListMultimap<ObjectId, Comment> comments;
+ private final ListMultimap<ObjectId, HumanComment> humanComments;
private final Map<PatchSet.Id, PatchSet.Builder> patchSets;
private final Set<PatchSet.Id> deletedPatchSets;
private final Map<PatchSet.Id, PatchSetState> patchSetStates;
@@ -178,7 +178,7 @@
assigneeUpdates = new ArrayList<>();
submitRecords = Lists.newArrayListWithExpectedSize(1);
allChangeMessages = new ArrayList<>();
- comments = MultimapBuilder.hashKeys().arrayListValues().build();
+ humanComments = MultimapBuilder.hashKeys().arrayListValues().build();
patchSets = new HashMap<>();
deletedPatchSets = new HashSet<>();
patchSetStates = new HashMap<>();
@@ -249,7 +249,7 @@
assigneeUpdates,
submitRecords,
buildAllMessages(),
- comments,
+ humanComments,
firstNonNull(isPrivate, false),
firstNonNull(workInProgress, false),
firstNonNull(hasReviewStarted, true),
@@ -735,12 +735,12 @@
ChangeNotesCommit tipCommit = walk.parseCommit(tip);
revisionNoteMap =
RevisionNoteMap.parse(
- changeNoteJson, reader, NoteMap.read(reader, tipCommit), Comment.Status.PUBLISHED);
+ changeNoteJson, reader, NoteMap.read(reader, tipCommit), HumanComment.Status.PUBLISHED);
Map<ObjectId, ChangeRevisionNote> rns = revisionNoteMap.revisionNotes;
for (Map.Entry<ObjectId, ChangeRevisionNote> e : rns.entrySet()) {
- for (Comment c : e.getValue().getEntities()) {
- comments.put(e.getKey(), c);
+ for (HumanComment c : e.getValue().getEntities()) {
+ humanComments.put(e.getKey(), c);
}
}
@@ -1055,7 +1055,7 @@
pruneEntitiesForMissingPatchSets(allChangeMessages, ChangeMessage::getPatchSetId, missing);
pruned +=
pruneEntitiesForMissingPatchSets(
- comments.values(), c -> PatchSet.id(id, c.key.patchSetId), missing);
+ humanComments.values(), c -> PatchSet.id(id, c.key.patchSetId), missing);
pruned +=
pruneEntitiesForMissingPatchSets(
approvals.values(), psa -> psa.key().patchSetId(), missing);
diff --git a/java/com/google/gerrit/server/notedb/ChangeNotesState.java b/java/com/google/gerrit/server/notedb/ChangeNotesState.java
index 0f27b75..a2ca066 100644
--- a/java/com/google/gerrit/server/notedb/ChangeNotesState.java
+++ b/java/com/google/gerrit/server/notedb/ChangeNotesState.java
@@ -39,7 +39,7 @@
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.ChangeMessage;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.PatchSetApproval;
import com.google.gerrit.entities.Project;
@@ -123,7 +123,7 @@
List<AssigneeStatusUpdate> assigneeUpdates,
List<SubmitRecord> submitRecords,
List<ChangeMessage> changeMessages,
- ListMultimap<ObjectId, Comment> publishedComments,
+ ListMultimap<ObjectId, HumanComment> publishedComments,
boolean isPrivate,
boolean workInProgress,
boolean reviewStarted,
@@ -314,7 +314,7 @@
abstract ImmutableList<ChangeMessage> changeMessages();
- abstract ImmutableListMultimap<ObjectId, Comment> publishedComments();
+ abstract ImmutableListMultimap<ObjectId, HumanComment> publishedComments();
abstract int updateCount();
@@ -427,7 +427,7 @@
abstract Builder changeMessages(List<ChangeMessage> changeMessages);
- abstract Builder publishedComments(ListMultimap<ObjectId, Comment> publishedComments);
+ abstract Builder publishedComments(ListMultimap<ObjectId, HumanComment> publishedComments);
abstract Builder updateCount(int updateCount);
@@ -634,8 +634,8 @@
.collect(toImmutableList()))
.publishedComments(
proto.getPublishedCommentList().stream()
- .map(r -> GSON.fromJson(r, Comment.class))
- .collect(toImmutableListMultimap(Comment::getCommitId, c -> c)))
+ .map(r -> GSON.fromJson(r, HumanComment.class))
+ .collect(toImmutableListMultimap(HumanComment::getCommitId, c -> c)))
.updateCount(proto.getUpdateCount());
return b.build();
}
diff --git a/java/com/google/gerrit/server/notedb/ChangeRevisionNote.java b/java/com/google/gerrit/server/notedb/ChangeRevisionNote.java
index 4e52093..bf2cf07 100644
--- a/java/com/google/gerrit/server/notedb/ChangeRevisionNote.java
+++ b/java/com/google/gerrit/server/notedb/ChangeRevisionNote.java
@@ -16,7 +16,7 @@
import static java.nio.charset.StandardCharsets.UTF_8;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -29,13 +29,13 @@
import org.eclipse.jgit.util.MutableInteger;
/** Implements the parsing of comment data, handling JSON decoding and push certificates. */
-class ChangeRevisionNote extends RevisionNote<Comment> {
+class ChangeRevisionNote extends RevisionNote<HumanComment> {
private final ChangeNoteJson noteJson;
- private final Comment.Status status;
+ private final HumanComment.Status status;
private String pushCert;
ChangeRevisionNote(
- ChangeNoteJson noteJson, ObjectReader reader, ObjectId noteId, Comment.Status status) {
+ ChangeNoteJson noteJson, ObjectReader reader, ObjectId noteId, HumanComment.Status status) {
super(reader, noteId);
this.noteJson = noteJson;
this.status = status;
@@ -47,12 +47,13 @@
}
@Override
- protected List<Comment> parse(byte[] raw, int offset) throws IOException, ConfigInvalidException {
+ protected List<HumanComment> parse(byte[] raw, int offset)
+ throws IOException, ConfigInvalidException {
MutableInteger p = new MutableInteger();
p.value = offset;
- RevisionNoteData data = parseJson(noteJson, raw, p.value);
- if (status == Comment.Status.PUBLISHED) {
+ HumanCommentsRevisionNoteData data = parseJson(noteJson, raw, p.value);
+ if (status == HumanComment.Status.PUBLISHED) {
pushCert = data.pushCert;
} else {
pushCert = null;
@@ -60,11 +61,11 @@
return data.comments;
}
- private RevisionNoteData parseJson(ChangeNoteJson noteUtil, byte[] raw, int offset)
+ private HumanCommentsRevisionNoteData parseJson(ChangeNoteJson noteUtil, byte[] raw, int offset)
throws IOException {
try (InputStream is = new ByteArrayInputStream(raw, offset, raw.length - offset);
Reader r = new InputStreamReader(is, UTF_8)) {
- return noteUtil.getGson().fromJson(r, RevisionNoteData.class);
+ return noteUtil.getGson().fromJson(r, HumanCommentsRevisionNoteData.class);
}
}
}
diff --git a/java/com/google/gerrit/server/notedb/ChangeUpdate.java b/java/com/google/gerrit/server/notedb/ChangeUpdate.java
index 41b1b94..348ab7d 100644
--- a/java/com/google/gerrit/server/notedb/ChangeUpdate.java
+++ b/java/com/google/gerrit/server/notedb/ChangeUpdate.java
@@ -50,6 +50,7 @@
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Table;
import com.google.common.collect.TreeBasedTable;
import com.google.gerrit.common.data.SubmitRecord;
@@ -57,6 +58,7 @@
import com.google.gerrit.entities.AttentionSetUpdate;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RobotComment;
import com.google.gerrit.entities.SubmissionId;
@@ -65,6 +67,7 @@
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.project.ProjectCache;
+import com.google.gerrit.server.util.AttentionSetUtil;
import com.google.gerrit.server.util.LabelVote;
import com.google.gerrit.server.validators.ValidationException;
import com.google.inject.assistedinject.Assisted;
@@ -73,6 +76,7 @@
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
@@ -80,6 +84,7 @@
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
+import java.util.stream.Collectors;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.ObjectId;
@@ -118,7 +123,7 @@
private final Table<String, Account.Id, Optional<Short>> approvals;
private final Map<Account.Id, ReviewerStateInternal> reviewers = new LinkedHashMap<>();
private final Map<Address, ReviewerStateInternal> reviewersByEmail = new LinkedHashMap<>();
- private final List<Comment> comments = new ArrayList<>();
+ private final List<HumanComment> comments = new ArrayList<>();
private String commitSubject;
private String subject;
@@ -129,7 +134,8 @@
private String submissionId;
private String topic;
private String commit;
- private Set<AttentionSetUpdate> attentionSetUpdates;
+ private Map<Account.Id, AttentionSetUpdate> plannedAttentionSetUpdates;
+ private boolean ignoreDefaultAttentionSetRules;
private Optional<Account.Id> assignee;
private Set<String> hashtags;
private String changeMessage;
@@ -285,10 +291,10 @@
this.psDescription = psDescription;
}
- public void putComment(Comment.Status status, Comment c) {
+ public void putComment(HumanComment.Status status, HumanComment c) {
verifyComment(c);
createDraftUpdateIfNull();
- if (status == Comment.Status.DRAFT) {
+ if (status == HumanComment.Status.DRAFT) {
draftUpdate.putComment(c);
} else {
comments.add(c);
@@ -302,7 +308,7 @@
robotCommentUpdate.putComment(c);
}
- public void deleteComment(Comment c) {
+ public void deleteComment(HumanComment c) {
verifyComment(c);
createDraftUpdateIfNull().deleteComment(c);
}
@@ -372,17 +378,45 @@
/**
* All updates must have a timestamp of null since we use the commit's timestamp. There also must
- * not be multiple updates for a single user.
+ * not be multiple updates for a single user. Only the first update takes place because of the
+ * different priorities: e.g, if we want to add someone to the attention set but also want to
+ * remove someone from the attention set, we should ensure to add/remove that user based on the
+ * priority of the addition and removal. If most importantly we want to remove the user, then we
+ * must first create the removal, and the addition will not take effect.
*/
- public void setAttentionSetUpdates(Set<AttentionSetUpdate> attentionSetUpdates) {
+ public void addToPlannedAttentionSetUpdates(Set<AttentionSetUpdate> updates) {
+ if (updates == null || updates.isEmpty()) {
+ return;
+ }
checkArgument(
- attentionSetUpdates.stream().noneMatch(a -> a.timestamp() != null),
+ updates.stream().noneMatch(a -> a.timestamp() != null),
"must not specify timestamp for write");
+
checkArgument(
- attentionSetUpdates.stream().map(AttentionSetUpdate::account).distinct().count()
- == attentionSetUpdates.size(),
+ updates.stream().map(AttentionSetUpdate::account).distinct().count() == updates.size(),
"must not specify multiple updates for single user");
- this.attentionSetUpdates = attentionSetUpdates;
+
+ if (plannedAttentionSetUpdates == null) {
+ plannedAttentionSetUpdates = new HashMap<>();
+ }
+
+ Set<Account.Id> currentAccountUpdates =
+ plannedAttentionSetUpdates.values().stream()
+ .map(AttentionSetUpdate::account)
+ .collect(Collectors.toSet());
+ updates.stream()
+ .filter(u -> !currentAccountUpdates.contains(u.account()))
+ .forEach(u -> plannedAttentionSetUpdates.putIfAbsent(u.account(), u));
+ }
+
+ /**
+ * If we need to ignore default attention set rules, no need to add any new updates in this class.
+ */
+ public void addToPlannedAttentionSetUpdates(AttentionSetUpdate update) {
+ if (ignoreDefaultAttentionSetRules) {
+ return;
+ }
+ addToPlannedAttentionSetUpdates(ImmutableSet.of(update));
}
public void setAssignee(Account.Id assignee) {
@@ -449,7 +483,7 @@
RevisionNoteMap<ChangeRevisionNote> rnm = getRevisionNoteMap(rw, curr);
RevisionNoteBuilder.Cache cache = new RevisionNoteBuilder.Cache(rnm);
- for (Comment c : comments) {
+ for (HumanComment c : comments) {
c.tag = tag;
cache.get(c.getCommitId()).putComment(c);
}
@@ -486,7 +520,7 @@
// Even though reading from changes might not be enabled, we need to
// parse any existing revision notes so we can merge them.
return RevisionNoteMap.parse(
- noteUtil.getChangeNoteJson(), rw.getObjectReader(), noteMap, Comment.Status.PUBLISHED);
+ noteUtil.getChangeNoteJson(), rw.getObjectReader(), noteMap, HumanComment.Status.PUBLISHED);
}
private void checkComments(
@@ -583,6 +617,12 @@
if (status != null) {
addFooter(msg, FOOTER_STATUS, status.name().toLowerCase());
+ if (status.equals(Change.Status.ABANDONED)) {
+ clearAttentionSet("Change was abandoned");
+ }
+ if (status.equals(Change.Status.MERGED)) {
+ clearAttentionSet("Change was submitted");
+ }
}
if (topic != null) {
@@ -593,12 +633,6 @@
addFooter(msg, FOOTER_COMMIT, commit);
}
- if (attentionSetUpdates != null) {
- for (AttentionSetUpdate attentionSetUpdate : attentionSetUpdates) {
- addFooter(msg, FOOTER_ATTENTION, noteUtil.attentionSetUpdateToJson(attentionSetUpdate));
- }
- }
-
if (assignee != null) {
if (assignee.isPresent()) {
addFooter(msg, FOOTER_ASSIGNEE);
@@ -625,7 +659,7 @@
addFooter(msg, e.getValue().getFooterKey());
noteUtil.appendAccountIdIdentString(msg, e.getKey()).append('\n');
}
-
+ applyReviewerUpdatesToAttentionSet();
for (Map.Entry<Address, ReviewerStateInternal> e : reviewersByEmail.entrySet()) {
addFooter(msg, e.getValue().getByEmailFooterKey(), e.getKey().toString());
}
@@ -686,6 +720,11 @@
if (workInProgress != null) {
addFooter(msg, FOOTER_WORK_IN_PROGRESS, workInProgress);
+ if (workInProgress) {
+ clearAttentionSet("Change was marked work in progress");
+ } else {
+ addAllReviewersToAttentionSet();
+ }
}
if (revertOf != null) {
@@ -696,6 +735,10 @@
addFooter(msg, FOOTER_CHERRY_PICK_OF, cherryPickOf);
}
+ if (plannedAttentionSetUpdates != null) {
+ updateAttentionSet(msg);
+ }
+
CommitBuilder cb = new CommitBuilder();
cb.setMessage(msg.toString());
try {
@@ -709,6 +752,91 @@
return cb;
}
+ private void clearAttentionSet(String reason) {
+ if (getNotes().getAttentionSet() == null) {
+ return;
+ }
+ AttentionSetUtil.additionsOnly(getNotes().getAttentionSet()).stream()
+ .map(
+ a ->
+ AttentionSetUpdate.createForWrite(
+ a.account(), AttentionSetUpdate.Operation.REMOVE, reason))
+ .forEach(this::addToPlannedAttentionSetUpdates);
+ }
+
+ private void applyReviewerUpdatesToAttentionSet() {
+ if ((workInProgress != null && workInProgress == true)
+ || getNotes().getChange().isWorkInProgress()) {
+ // Users shouldn't be added to the attention set if the change is work in progress.
+ return;
+ }
+ Set<Account.Id> currentReviewers =
+ getNotes().getReviewers().byState(ReviewerStateInternal.REVIEWER);
+ Set<AttentionSetUpdate> updates = new HashSet<>();
+ for (Map.Entry<Account.Id, ReviewerStateInternal> reviewer : reviewers.entrySet()) {
+ // Only add new reviewers to the attention set.
+ if (reviewer.getValue().equals(ReviewerStateInternal.REVIEWER)
+ && !currentReviewers.contains(reviewer.getKey())) {
+ updates.add(
+ AttentionSetUpdate.createForWrite(
+ reviewer.getKey(), AttentionSetUpdate.Operation.ADD, "Reviewer was added"));
+ }
+ // Treat both REMOVED and CC as "removed reviewers".
+ if (!reviewer.getValue().equals(ReviewerStateInternal.REVIEWER)
+ && currentReviewers.contains(reviewer.getKey())) {
+ updates.add(
+ AttentionSetUpdate.createForWrite(
+ reviewer.getKey(), AttentionSetUpdate.Operation.REMOVE, "Reviewer was removed"));
+ }
+ }
+ addToPlannedAttentionSetUpdates(updates);
+ }
+
+ private void addAllReviewersToAttentionSet() {
+ getNotes().getReviewers().byState(ReviewerStateInternal.REVIEWER).stream()
+ .map(
+ r ->
+ AttentionSetUpdate.createForWrite(
+ r, AttentionSetUpdate.Operation.ADD, "Change was marked ready for review"))
+ .forEach(this::addToPlannedAttentionSetUpdates);
+ }
+
+ /**
+ * Any updates to the attention set must be done in {@link #addToPlannedAttentionSetUpdates}. This
+ * method is called after all the updates are finished to do the updates once and for real.
+ */
+ private void updateAttentionSet(StringBuilder msg) {
+ if (plannedAttentionSetUpdates == null) {
+ return;
+ }
+ Set<Account.Id> currentUsersInAttentionSet =
+ AttentionSetUtil.additionsOnly(getNotes().getAttentionSet()).stream()
+ .map(AttentionSetUpdate::account)
+ .collect(Collectors.toSet());
+ for (AttentionSetUpdate attentionSetUpdate : plannedAttentionSetUpdates.values()) {
+ if (attentionSetUpdate.operation() == AttentionSetUpdate.Operation.ADD
+ && currentUsersInAttentionSet.contains(attentionSetUpdate.account())) {
+ // Skip users that are already in the attention set: no need to re-add them.
+ continue;
+ }
+
+ if (attentionSetUpdate.operation() == AttentionSetUpdate.Operation.REMOVE
+ && !currentUsersInAttentionSet.contains(attentionSetUpdate.account())) {
+ // Skip users that are not in the attention set: no need to remove them.
+ continue;
+ }
+ addFooter(msg, FOOTER_ATTENTION, noteUtil.attentionSetUpdateToJson(attentionSetUpdate));
+ }
+ }
+
+ /**
+ * When set, default attention set rules are ignored (E.g, adding reviewers -> adds to attention
+ * set, etc).
+ */
+ public void ignoreDefaultAttentionSetRules() {
+ ignoreDefaultAttentionSetRules = true;
+ }
+
private void addPatchSetFooter(StringBuilder sb, int ps) {
addFooter(sb, FOOTER_PATCH_SET).append(ps);
if (psState != null) {
@@ -735,7 +863,7 @@
&& status == null
&& submissionId == null
&& submitRecords == null
- && attentionSetUpdates == null
+ && plannedAttentionSetUpdates == null
&& assignee == null
&& hashtags == null
&& topic == null
diff --git a/java/com/google/gerrit/server/notedb/DeleteCommentRewriter.java b/java/com/google/gerrit/server/notedb/DeleteCommentRewriter.java
index 9c8b369..d0b6247 100644
--- a/java/com/google/gerrit/server/notedb/DeleteCommentRewriter.java
+++ b/java/com/google/gerrit/server/notedb/DeleteCommentRewriter.java
@@ -15,14 +15,13 @@
package com.google.gerrit.server.notedb;
import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.gerrit.entities.Comment.Status;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
import com.google.common.annotations.VisibleForTesting;
import com.google.gerrit.entities.Change;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.RefNames;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
@@ -94,14 +93,14 @@
ObjectReader reader = revWalk.getObjectReader();
RevCommit newTipCommit = revWalk.next(); // The first commit will not be rewritten.
- Map<String, Comment> parentComments =
+ Map<String, HumanComment> parentComments =
getPublishedComments(noteUtil, reader, NoteMap.read(reader, newTipCommit));
boolean rewrite = false;
RevCommit originalCommit;
while ((originalCommit = revWalk.next()) != null) {
NoteMap noteMap = NoteMap.read(reader, originalCommit);
- Map<String, Comment> currComments = getPublishedComments(noteUtil, reader, noteMap);
+ Map<String, HumanComment> currComments = getPublishedComments(noteUtil, reader, noteMap);
if (!rewrite && currComments.containsKey(uuid)) {
rewrite = true;
@@ -113,8 +112,8 @@
continue;
}
- List<Comment> putInComments = getPutInComments(parentComments, currComments);
- List<Comment> deletedComments = getDeletedComments(parentComments, currComments);
+ List<HumanComment> putInComments = getPutInComments(parentComments, currComments);
+ List<HumanComment> deletedComments = getDeletedComments(parentComments, currComments);
newTipCommit =
revWalk.parseCommit(
rewriteCommit(
@@ -130,16 +129,16 @@
* the previous commits.
*/
@VisibleForTesting
- public static Map<String, Comment> getPublishedComments(
+ public static Map<String, HumanComment> getPublishedComments(
ChangeNoteJson changeNoteJson, ObjectReader reader, NoteMap noteMap)
throws IOException, ConfigInvalidException {
- return RevisionNoteMap.parse(changeNoteJson, reader, noteMap, Status.PUBLISHED).revisionNotes
- .values().stream()
+ return RevisionNoteMap.parse(changeNoteJson, reader, noteMap, HumanComment.Status.PUBLISHED)
+ .revisionNotes.values().stream()
.flatMap(n -> n.getEntities().stream())
.collect(toMap(c -> c.key.uuid, Function.identity()));
}
- public static Map<String, Comment> getPublishedComments(
+ public static Map<String, HumanComment> getPublishedComments(
ChangeNoteUtil noteUtil, ObjectReader reader, NoteMap noteMap)
throws IOException, ConfigInvalidException {
return getPublishedComments(noteUtil.getChangeNoteJson(), reader, noteMap);
@@ -152,11 +151,12 @@
* @param curMap the comment map of the current commit.
* @return The comments put in by the current commit.
*/
- private List<Comment> getPutInComments(Map<String, Comment> parMap, Map<String, Comment> curMap) {
- List<Comment> comments = new ArrayList<>();
+ private List<HumanComment> getPutInComments(
+ Map<String, HumanComment> parMap, Map<String, HumanComment> curMap) {
+ List<HumanComment> comments = new ArrayList<>();
for (String key : curMap.keySet()) {
if (!parMap.containsKey(key)) {
- Comment comment = curMap.get(key);
+ HumanComment comment = curMap.get(key);
if (key.equals(uuid)) {
comment.message = newMessage;
}
@@ -173,8 +173,8 @@
* @param curMap the comment map of the current commit.
* @return The comments deleted by the current commit.
*/
- private List<Comment> getDeletedComments(
- Map<String, Comment> parMap, Map<String, Comment> curMap) {
+ private List<HumanComment> getDeletedComments(
+ Map<String, HumanComment> parMap, Map<String, HumanComment> curMap) {
return parMap.entrySet().stream()
.filter(c -> !curMap.containsKey(c.getKey()))
.map(Map.Entry::getValue)
@@ -199,22 +199,22 @@
RevCommit parentCommit,
ObjectInserter inserter,
ObjectReader reader,
- List<Comment> putInComments,
- List<Comment> deletedComments)
+ List<HumanComment> putInComments,
+ List<HumanComment> deletedComments)
throws IOException, ConfigInvalidException {
RevisionNoteMap<ChangeRevisionNote> revNotesMap =
RevisionNoteMap.parse(
noteUtil.getChangeNoteJson(),
reader,
NoteMap.read(reader, parentCommit),
- Status.PUBLISHED);
+ HumanComment.Status.PUBLISHED);
RevisionNoteBuilder.Cache cache = new RevisionNoteBuilder.Cache(revNotesMap);
- for (Comment c : putInComments) {
+ for (HumanComment c : putInComments) {
cache.get(c.getCommitId()).putComment(c);
}
- for (Comment c : deletedComments) {
+ for (HumanComment c : deletedComments) {
cache.get(c.getCommitId()).deleteComment(c.key);
}
diff --git a/java/com/google/gerrit/server/notedb/DraftCommentNotes.java b/java/com/google/gerrit/server/notedb/DraftCommentNotes.java
index 3966396..9b403e8 100644
--- a/java/com/google/gerrit/server/notedb/DraftCommentNotes.java
+++ b/java/com/google/gerrit/server/notedb/DraftCommentNotes.java
@@ -26,7 +26,7 @@
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Change;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.Project;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
@@ -50,7 +50,7 @@
private final Account.Id author;
private final Ref ref;
- private ImmutableListMultimap<ObjectId, Comment> comments;
+ private ImmutableListMultimap<ObjectId, HumanComment> comments;
private RevisionNoteMap<ChangeRevisionNote> revisionNoteMap;
@AssistedInject
@@ -80,12 +80,12 @@
return author;
}
- public ImmutableListMultimap<ObjectId, Comment> getComments() {
+ public ImmutableListMultimap<ObjectId, HumanComment> getComments() {
return comments;
}
- public boolean containsComment(Comment c) {
- for (Comment existing : comments.values()) {
+ public boolean containsComment(HumanComment c) {
+ for (HumanComment existing : comments.values()) {
if (c.key.equals(existing.key)) {
return true;
}
@@ -120,10 +120,13 @@
ObjectReader reader = handle.walk().getObjectReader();
revisionNoteMap =
RevisionNoteMap.parse(
- args.changeNoteJson, reader, NoteMap.read(reader, tipCommit), Comment.Status.DRAFT);
- ListMultimap<ObjectId, Comment> cs = MultimapBuilder.hashKeys().arrayListValues().build();
+ args.changeNoteJson,
+ reader,
+ NoteMap.read(reader, tipCommit),
+ HumanComment.Status.DRAFT);
+ ListMultimap<ObjectId, HumanComment> cs = MultimapBuilder.hashKeys().arrayListValues().build();
for (ChangeRevisionNote rn : revisionNoteMap.revisionNotes.values()) {
- for (Comment c : rn.getEntities()) {
+ for (HumanComment c : rn.getEntities()) {
cs.put(c.getCommitId(), c);
}
}
diff --git a/java/com/google/gerrit/server/notedb/HumanCommentsRevisionNoteData.java b/java/com/google/gerrit/server/notedb/HumanCommentsRevisionNoteData.java
new file mode 100644
index 0000000..e570412
--- /dev/null
+++ b/java/com/google/gerrit/server/notedb/HumanCommentsRevisionNoteData.java
@@ -0,0 +1,28 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.notedb;
+
+import com.google.gerrit.entities.HumanComment;
+import java.util.List;
+
+/**
+ * Holds the raw data of a RevisionNote.
+ *
+ * <p>It is intended for deserialization from JSON only. It is used for human comments only.
+ */
+class HumanCommentsRevisionNoteData {
+ String pushCert;
+ List<HumanComment> comments;
+}
diff --git a/java/com/google/gerrit/server/notedb/RevisionNoteData.java b/java/com/google/gerrit/server/notedb/RevisionNoteData.java
index c0e09ed..da15b34 100644
--- a/java/com/google/gerrit/server/notedb/RevisionNoteData.java
+++ b/java/com/google/gerrit/server/notedb/RevisionNoteData.java
@@ -20,7 +20,8 @@
/**
* Holds the raw data of a RevisionNote.
*
- * <p>It is intended for (de)serialization to JSON only.
+ * <p>It is intended for serialization to JSON only. It is used for human comments and robot
+ * comments.
*/
class RevisionNoteData {
String pushCert;
diff --git a/java/com/google/gerrit/server/notedb/RevisionNoteMap.java b/java/com/google/gerrit/server/notedb/RevisionNoteMap.java
index 98c9873..5a0b67b 100644
--- a/java/com/google/gerrit/server/notedb/RevisionNoteMap.java
+++ b/java/com/google/gerrit/server/notedb/RevisionNoteMap.java
@@ -16,6 +16,7 @@
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import java.io.IOException;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.ObjectId;
@@ -41,7 +42,7 @@
}
static RevisionNoteMap<ChangeRevisionNote> parse(
- ChangeNoteJson noteJson, ObjectReader reader, NoteMap noteMap, Comment.Status status)
+ ChangeNoteJson noteJson, ObjectReader reader, NoteMap noteMap, HumanComment.Status status)
throws ConfigInvalidException, IOException {
ImmutableMap.Builder<ObjectId, ChangeRevisionNote> result = ImmutableMap.builder();
for (Note note : noteMap) {
diff --git a/java/com/google/gerrit/server/notedb/RobotCommentsRevisionNote.java b/java/com/google/gerrit/server/notedb/RobotCommentsRevisionNote.java
index fc4c9fd..010206c 100644
--- a/java/com/google/gerrit/server/notedb/RobotCommentsRevisionNote.java
+++ b/java/com/google/gerrit/server/notedb/RobotCommentsRevisionNote.java
@@ -26,7 +26,11 @@
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
-/** Like {@link RevisionNote} but for robot comments. */
+/**
+ * Holds the raw data of a RevisionNote.
+ *
+ * <p>It is intended for deserialization from JSON only. It is used for robot comments only.
+ */
public class RobotCommentsRevisionNote extends RevisionNote<RobotComment> {
private final ChangeNoteJson noteUtil;
diff --git a/java/com/google/gerrit/server/patch/PatchListLoader.java b/java/com/google/gerrit/server/patch/PatchListLoader.java
index c3d9a1d..be0895b 100644
--- a/java/com/google/gerrit/server/patch/PatchListLoader.java
+++ b/java/com/google/gerrit/server/patch/PatchListLoader.java
@@ -26,10 +26,12 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.Patch;
import com.google.gerrit.entities.Project;
+import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace;
import com.google.gerrit.server.config.ConfigUtil;
import com.google.gerrit.server.config.GerritServerConfig;
@@ -41,6 +43,7 @@
import com.google.inject.assistedinject.Assisted;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
@@ -59,6 +62,7 @@
import org.eclipse.jgit.diff.HistogramDiff;
import org.eclipse.jgit.diff.RawText;
import org.eclipse.jgit.diff.RawTextComparator;
+import org.eclipse.jgit.lib.AbbreviatedObjectId;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
@@ -383,8 +387,20 @@
Set<ContextAwareEdit> editsDueToRebase)
throws IOException {
FileHeader fileHeader = toFileHeader(key.getNewId(), diffFormatter, diffEntry);
- long oldSize = getFileSize(objectReader, diffEntry.getOldMode(), diffEntry.getOldPath(), treeA);
- long newSize = getFileSize(objectReader, diffEntry.getNewMode(), diffEntry.getNewPath(), treeB);
+ long oldSize =
+ getFileSize(
+ objectReader,
+ diffEntry.getOldId(),
+ diffEntry.getOldMode(),
+ diffEntry.getOldPath(),
+ treeA);
+ long newSize =
+ getFileSize(
+ objectReader,
+ diffEntry.getNewId(),
+ diffEntry.getNewMode(),
+ diffEntry.getNewPath(),
+ treeB);
Set<Edit> contentEditsDueToRebase = getContentEdits(editsDueToRebase);
PatchListEntry patchListEntry =
newEntry(treeA, fileHeader, contentEditsDueToRebase, newSize, newSize - oldSize);
@@ -417,14 +433,18 @@
return ComparisonType.againstOtherPatchSet();
}
- private static long getFileSize(ObjectReader reader, FileMode mode, String path, RevTree t)
+ private static long getFileSize(
+ ObjectReader reader, AbbreviatedObjectId abbreviatedId, FileMode mode, String path, RevTree t)
throws IOException {
if (!isBlob(mode)) {
return 0;
}
- try (TreeWalk tw = TreeWalk.forPath(reader, path, t)) {
- return tw != null ? reader.open(tw.getObjectId(0), OBJ_BLOB).getSize() : 0;
+ ObjectId fileId =
+ toObjectId(reader, abbreviatedId).orElseGet(() -> lookupObjectId(reader, path, t));
+ if (ObjectId.zeroId().equals(fileId)) {
+ return 0;
}
+ return reader.getObjectSize(fileId, OBJ_BLOB);
}
private static boolean isBlob(FileMode mode) {
@@ -432,6 +452,37 @@
return t == FileMode.TYPE_FILE || t == FileMode.TYPE_SYMLINK;
}
+ private static Optional<ObjectId> toObjectId(
+ ObjectReader reader, AbbreviatedObjectId abbreviatedId) throws IOException {
+ if (abbreviatedId == null) {
+ // In theory, DiffEntry#getOldId or DiffEntry#getNewId can be null for pure renames or pure
+ // mode changes (e.g. DiffEntry#modify doesn't set the IDs). However, the method we call
+ // for diffs (DiffFormatter#scan) seems to always produce DiffEntries with set IDs, even for
+ // pure renames.
+ return Optional.empty();
+ }
+ if (abbreviatedId.isComplete()) {
+ // With the current JGit version and the method we call for diffs (DiffFormatter#scan), this
+ // is the only code path taken right now.
+ return Optional.ofNullable(abbreviatedId.toObjectId());
+ }
+ Collection<ObjectId> objectIds = reader.resolve(abbreviatedId);
+ // It seems very unlikely that an ObjectId which was just abbreviated by the diff computation
+ // now can't be resolved to exactly one ObjectId. The API allows this possibility, though.
+ return objectIds.size() == 1
+ ? Optional.of(Iterables.getOnlyElement(objectIds))
+ : Optional.empty();
+ }
+
+ private static ObjectId lookupObjectId(ObjectReader reader, String path, RevTree tree) {
+ // This variant is very expensive.
+ try (TreeWalk treeWalk = TreeWalk.forPath(reader, path, tree)) {
+ return treeWalk != null ? treeWalk.getObjectId(0) : ObjectId.zeroId();
+ } catch (IOException e) {
+ throw new StorageException(e);
+ }
+ }
+
private FileHeader toFileHeader(
ObjectId commitB, DiffFormatter diffFormatter, DiffEntry diffEntry) throws IOException {
diff --git a/java/com/google/gerrit/server/patch/PatchScriptFactory.java b/java/com/google/gerrit/server/patch/PatchScriptFactory.java
index 29a89d6..30930ec 100644
--- a/java/com/google/gerrit/server/patch/PatchScriptFactory.java
+++ b/java/com/google/gerrit/server/patch/PatchScriptFactory.java
@@ -24,7 +24,7 @@
import com.google.gerrit.common.data.PatchScript;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Change;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.Patch.ChangeType;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Project;
@@ -381,13 +381,13 @@
}
private void loadPublished(String file) {
- for (Comment c : commentsUtil.publishedByChangeFile(notes, file)) {
+ for (HumanComment c : commentsUtil.publishedByChangeFile(notes, file)) {
comments.include(notes.getChangeId(), c);
}
}
private void loadDrafts(Account.Id me, String file) {
- for (Comment c : commentsUtil.draftByChangeFileAuthor(notes, file, me)) {
+ for (HumanComment c : commentsUtil.draftByChangeFileAuthor(notes, file, me)) {
comments.include(notes.getChangeId(), c);
}
}
diff --git a/java/com/google/gerrit/server/plugins/AutoRegisterModules.java b/java/com/google/gerrit/server/plugins/AutoRegisterModules.java
index fde61ff..9d93ed2 100644
--- a/java/com/google/gerrit/server/plugins/AutoRegisterModules.java
+++ b/java/com/google/gerrit/server/plugins/AutoRegisterModules.java
@@ -158,7 +158,7 @@
return;
}
- if (is("org.apache.sshd.server.Command", clazz)) {
+ if (is("org.apache.sshd.server.command.Command", clazz)) {
sshGen.export(export, clazz);
} else if (is("javax.servlet.http.HttpServlet", clazz)) {
httpGen.export(export, clazz);
diff --git a/java/com/google/gerrit/server/plugins/PluginGuiceEnvironment.java b/java/com/google/gerrit/server/plugins/PluginGuiceEnvironment.java
index c032c46..87e1ca9 100644
--- a/java/com/google/gerrit/server/plugins/PluginGuiceEnvironment.java
+++ b/java/com/google/gerrit/server/plugins/PluginGuiceEnvironment.java
@@ -589,7 +589,7 @@
return false;
}
- if (is("org.apache.sshd.server.Command", type)) {
+ if (is("org.apache.sshd.server.command.Command", type)) {
return false;
}
diff --git a/java/com/google/gerrit/server/query/change/ChangeData.java b/java/com/google/gerrit/server/query/change/ChangeData.java
index 01d2c31..34c96dd 100644
--- a/java/com/google/gerrit/server/query/change/ChangeData.java
+++ b/java/com/google/gerrit/server/query/change/ChangeData.java
@@ -41,6 +41,7 @@
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.ChangeMessage;
import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.PatchSetApproval;
import com.google.gerrit.entities.Project;
@@ -277,7 +278,7 @@
private List<PatchSetApproval> currentApprovals;
private List<String> currentFiles;
private Optional<DiffSummary> diffSummary;
- private Collection<Comment> publishedComments;
+ private Collection<HumanComment> publishedComments;
private Collection<RobotComment> robotComments;
private CurrentUser visibleTo;
private List<ChangeMessage> messages;
@@ -760,12 +761,12 @@
return reviewerUpdates;
}
- public Collection<Comment> publishedComments() {
+ public Collection<HumanComment> publishedComments() {
if (publishedComments == null) {
if (!lazyLoad) {
return Collections.emptyList();
}
- publishedComments = commentsUtil.publishedByChange(notes());
+ publishedComments = commentsUtil.publishedHumanCommentsByChange(notes());
}
return publishedComments;
}
diff --git a/java/com/google/gerrit/server/query/change/CommentByPredicate.java b/java/com/google/gerrit/server/query/change/CommentByPredicate.java
index bd7981c..b8cf100 100644
--- a/java/com/google/gerrit/server/query/change/CommentByPredicate.java
+++ b/java/com/google/gerrit/server/query/change/CommentByPredicate.java
@@ -16,7 +16,7 @@
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.ChangeMessage;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.server.index.change.ChangeField;
import java.util.Objects;
@@ -39,7 +39,7 @@
return true;
}
}
- for (Comment c : cd.publishedComments()) {
+ for (HumanComment c : cd.publishedComments()) {
if (Objects.equals(c.author.getId(), id)) {
return true;
}
diff --git a/java/com/google/gerrit/server/restapi/account/DeleteDraftComments.java b/java/com/google/gerrit/server/restapi/account/DeleteDraftComments.java
index 4b505c6..f29c6e6 100644
--- a/java/com/google/gerrit/server/restapi/account/DeleteDraftComments.java
+++ b/java/com/google/gerrit/server/restapi/account/DeleteDraftComments.java
@@ -22,7 +22,7 @@
import com.google.common.collect.ImmutableList;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.api.accounts.DeleteDraftCommentsInput;
@@ -48,7 +48,7 @@
import com.google.gerrit.server.query.change.HasDraftByPredicate;
import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.gerrit.server.restapi.change.CommentJson;
-import com.google.gerrit.server.restapi.change.CommentJson.CommentFormatter;
+import com.google.gerrit.server.restapi.change.CommentJson.HumanCommentFormatter;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.BatchUpdate.Factory;
import com.google.gerrit.server.update.BatchUpdateListener;
@@ -123,7 +123,8 @@
throw new AuthException("Cannot delete drafts of other user");
}
- CommentFormatter commentFormatter = commentJsonProvider.get().newCommentFormatter();
+ HumanCommentFormatter humanCommentFormatter =
+ commentJsonProvider.get().newHumanCommentFormatter();
Account.Id accountId = rsrc.getUser().getAccountId();
Timestamp now = TimeUtil.nowTs();
Map<Project.NameKey, BatchUpdate> updates = new LinkedHashMap<>();
@@ -137,7 +138,7 @@
BatchUpdate update =
updates.computeIfAbsent(
cd.project(), p -> batchUpdateFactory.create(p, rsrc.getUser(), now));
- Op op = new Op(commentFormatter, accountId);
+ Op op = new Op(humanCommentFormatter, accountId);
update.addOp(cd.getId(), op);
ops.add(op);
}
@@ -165,12 +166,12 @@
}
private class Op implements BatchUpdateOp {
- private final CommentFormatter commentFormatter;
+ private final HumanCommentFormatter humanCommentFormatter;
private final Account.Id accountId;
private DeletedDraftCommentInfo result;
- Op(CommentFormatter commentFormatter, Account.Id accountId) {
- this.commentFormatter = commentFormatter;
+ Op(HumanCommentFormatter humanCommentFormatter, Account.Id accountId) {
+ this.humanCommentFormatter = humanCommentFormatter;
this.accountId = accountId;
}
@@ -179,12 +180,12 @@
throws PatchListNotAvailableException, PermissionBackendException {
ImmutableList.Builder<CommentInfo> comments = ImmutableList.builder();
boolean dirty = false;
- for (Comment c : commentsUtil.draftByChangeAuthor(ctx.getNotes(), accountId)) {
+ for (HumanComment c : commentsUtil.draftByChangeAuthor(ctx.getNotes(), accountId)) {
dirty = true;
PatchSet.Id psId = PatchSet.id(ctx.getChange().getId(), c.key.patchSetId);
setCommentCommitId(c, patchListCache, ctx.getChange(), psUtil.get(ctx.getNotes(), psId));
- commentsUtil.deleteComments(ctx.getUpdate(psId), Collections.singleton(c));
- comments.add(commentFormatter.format(c));
+ commentsUtil.deleteHumanComments(ctx.getUpdate(psId), Collections.singleton(c));
+ comments.add(humanCommentFormatter.format(c));
}
if (dirty) {
result = new DeletedDraftCommentInfo();
diff --git a/java/com/google/gerrit/server/restapi/change/AddToAttentionSet.java b/java/com/google/gerrit/server/restapi/change/AddToAttentionSet.java
index 5176fe9..a8b65bd 100644
--- a/java/com/google/gerrit/server/restapi/change/AddToAttentionSet.java
+++ b/java/com/google/gerrit/server/restapi/change/AddToAttentionSet.java
@@ -14,12 +14,10 @@
package com.google.gerrit.server.restapi.change;
-import com.google.common.base.Strings;
import com.google.gerrit.entities.Account;
-import com.google.gerrit.extensions.api.changes.AddToAttentionSetInput;
+import com.google.gerrit.extensions.api.changes.AttentionSetInput;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.restapi.AuthException;
-import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestCollectionModifyView;
import com.google.gerrit.server.account.AccountLoader;
@@ -30,6 +28,7 @@
import com.google.gerrit.server.permissions.ChangePermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.update.BatchUpdate;
+import com.google.gerrit.server.util.AttentionSetUtil;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@@ -38,7 +37,7 @@
@Singleton
public class AddToAttentionSet
implements RestCollectionModifyView<
- ChangeResource, AttentionSetEntryResource, AddToAttentionSetInput> {
+ ChangeResource, AttentionSetEntryResource, AttentionSetInput> {
private final BatchUpdate.Factory updateFactory;
private final AccountResolver accountResolver;
private final AddToAttentionSetOp.Factory opFactory;
@@ -60,16 +59,9 @@
}
@Override
- public Response<AccountInfo> apply(ChangeResource changeResource, AddToAttentionSetInput input)
+ public Response<AccountInfo> apply(ChangeResource changeResource, AttentionSetInput input)
throws Exception {
- input.user = Strings.nullToEmpty(input.user).trim();
- if (input.user.isEmpty()) {
- throw new BadRequestException("missing field: user");
- }
- input.reason = Strings.nullToEmpty(input.reason).trim();
- if (input.reason.isEmpty()) {
- throw new BadRequestException("missing field: reason");
- }
+ AttentionSetUtil.validateInput(input);
Account.Id attentionUserId = accountResolver.resolve(input.user).asUnique().account().id();
try {
diff --git a/java/com/google/gerrit/server/restapi/change/CommentJson.java b/java/com/google/gerrit/server/restapi/change/CommentJson.java
index 03898b1..4bb6327 100644
--- a/java/com/google/gerrit/server/restapi/change/CommentJson.java
+++ b/java/com/google/gerrit/server/restapi/change/CommentJson.java
@@ -25,6 +25,7 @@
import com.google.gerrit.entities.Comment;
import com.google.gerrit.entities.FixReplacement;
import com.google.gerrit.entities.FixSuggestion;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.RobotComment;
import com.google.gerrit.extensions.client.Comment.Range;
import com.google.gerrit.extensions.client.Side;
@@ -63,8 +64,8 @@
return this;
}
- public CommentFormatter newCommentFormatter() {
- return new CommentFormatter();
+ public HumanCommentFormatter newHumanCommentFormatter() {
+ return new HumanCommentFormatter();
}
public RobotCommentFormatter newRobotCommentFormatter() {
@@ -161,15 +162,15 @@
}
}
- public class CommentFormatter extends BaseCommentFormatter<Comment, CommentInfo> {
+ public class HumanCommentFormatter extends BaseCommentFormatter<HumanComment, CommentInfo> {
@Override
- protected CommentInfo toInfo(Comment c, AccountLoader loader) {
+ protected CommentInfo toInfo(HumanComment c, AccountLoader loader) {
CommentInfo ci = new CommentInfo();
fillCommentInfo(c, ci, loader);
return ci;
}
- private CommentFormatter() {}
+ private HumanCommentFormatter() {}
}
class RobotCommentFormatter extends BaseCommentFormatter<RobotComment, RobotCommentInfo> {
diff --git a/java/com/google/gerrit/server/restapi/change/Comments.java b/java/com/google/gerrit/server/restapi/change/Comments.java
index 078c239..00566f3 100644
--- a/java/com/google/gerrit/server/restapi/change/Comments.java
+++ b/java/com/google/gerrit/server/restapi/change/Comments.java
@@ -14,28 +14,28 @@
package com.google.gerrit.server.restapi.change;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.restapi.ChildCollection;
import com.google.gerrit.extensions.restapi.IdString;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.server.CommentsUtil;
-import com.google.gerrit.server.change.CommentResource;
+import com.google.gerrit.server.change.HumanCommentResource;
import com.google.gerrit.server.change.RevisionResource;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@Singleton
-public class Comments implements ChildCollection<RevisionResource, CommentResource> {
- private final DynamicMap<RestView<CommentResource>> views;
+public class Comments implements ChildCollection<RevisionResource, HumanCommentResource> {
+ private final DynamicMap<RestView<HumanCommentResource>> views;
private final ListRevisionComments list;
private final CommentsUtil commentsUtil;
@Inject
Comments(
- DynamicMap<RestView<CommentResource>> views,
+ DynamicMap<RestView<HumanCommentResource>> views,
ListRevisionComments list,
CommentsUtil commentsUtil) {
this.views = views;
@@ -44,7 +44,7 @@
}
@Override
- public DynamicMap<RestView<CommentResource>> views() {
+ public DynamicMap<RestView<HumanCommentResource>> views() {
return views;
}
@@ -54,13 +54,14 @@
}
@Override
- public CommentResource parse(RevisionResource rev, IdString id) throws ResourceNotFoundException {
+ public HumanCommentResource parse(RevisionResource rev, IdString id)
+ throws ResourceNotFoundException {
String uuid = id.get();
ChangeNotes notes = rev.getNotes();
- for (Comment c : commentsUtil.publishedByPatchSet(notes, rev.getPatchSet().id())) {
+ for (HumanComment c : commentsUtil.publishedByPatchSet(notes, rev.getPatchSet().id())) {
if (uuid.equals(c.key.uuid)) {
- return new CommentResource(rev, c);
+ return new HumanCommentResource(rev, c);
}
}
throw new ResourceNotFoundException(id);
diff --git a/java/com/google/gerrit/server/restapi/change/CreateDraftComment.java b/java/com/google/gerrit/server/restapi/change/CreateDraftComment.java
index 42032f7..d99d7014 100644
--- a/java/com/google/gerrit/server/restapi/change/CreateDraftComment.java
+++ b/java/com/google/gerrit/server/restapi/change/CreateDraftComment.java
@@ -18,7 +18,7 @@
import static com.google.gerrit.server.CommentsUtil.setCommentCommitId;
import com.google.common.base.Strings;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.extensions.api.changes.DraftInput;
import com.google.gerrit.extensions.common.CommentInfo;
@@ -89,7 +89,7 @@
bu.addOp(rsrc.getChange().getId(), op);
bu.execute();
return Response.created(
- commentJson.get().setFillAccounts(false).newCommentFormatter().format(op.comment));
+ commentJson.get().setFillAccounts(false).newHumanCommentFormatter().format(op.comment));
}
}
@@ -97,7 +97,7 @@
private final PatchSet.Id psId;
private final DraftInput in;
- private Comment comment;
+ private HumanComment comment;
private Op(PatchSet.Id psId, DraftInput in) {
this.psId = psId;
@@ -115,15 +115,15 @@
String parentUuid = Url.decode(in.inReplyTo);
comment =
- commentsUtil.newComment(
+ commentsUtil.newHumanComment(
ctx, in.path, ps.id(), in.side(), in.message.trim(), in.unresolved, parentUuid);
comment.setLineNbrAndRange(in.line, in.range);
comment.tag = in.tag;
setCommentCommitId(comment, patchListCache, ctx.getChange(), ps);
- commentsUtil.putComments(
- ctx.getUpdate(psId), Comment.Status.DRAFT, Collections.singleton(comment));
+ commentsUtil.putHumanComments(
+ ctx.getUpdate(psId), HumanComment.Status.DRAFT, Collections.singleton(comment));
return true;
}
}
diff --git a/java/com/google/gerrit/server/restapi/change/DeleteComment.java b/java/com/google/gerrit/server/restapi/change/DeleteComment.java
index f915728..8580229 100644
--- a/java/com/google/gerrit/server/restapi/change/DeleteComment.java
+++ b/java/com/google/gerrit/server/restapi/change/DeleteComment.java
@@ -15,7 +15,7 @@
package com.google.gerrit.server.restapi.change;
import com.google.common.base.Strings;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.extensions.api.changes.DeleteCommentInput;
import com.google.gerrit.extensions.common.CommentInfo;
@@ -26,7 +26,7 @@
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.CurrentUser;
-import com.google.gerrit.server.change.CommentResource;
+import com.google.gerrit.server.change.HumanCommentResource;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.permissions.GlobalPermission;
import com.google.gerrit.server.permissions.PermissionBackend;
@@ -45,7 +45,7 @@
import org.eclipse.jgit.errors.ConfigInvalidException;
@Singleton
-public class DeleteComment implements RestModifyView<CommentResource, DeleteCommentInput> {
+public class DeleteComment implements RestModifyView<HumanCommentResource, DeleteCommentInput> {
private final Provider<CurrentUser> userProvider;
private final PermissionBackend permissionBackend;
@@ -71,7 +71,7 @@
}
@Override
- public Response<CommentInfo> apply(CommentResource rsrc, DeleteCommentInput input)
+ public Response<CommentInfo> apply(HumanCommentResource rsrc, DeleteCommentInput input)
throws RestApiException, IOException, ConfigInvalidException, PermissionBackendException,
UpdateException {
CurrentUser user = userProvider.get();
@@ -90,15 +90,15 @@
ChangeNotes updatedNotes =
notesFactory.createChecked(rsrc.getRevisionResource().getChange().getId());
- List<Comment> changeComments = commentsUtil.publishedByChange(updatedNotes);
- Optional<Comment> updatedComment =
+ List<HumanComment> changeComments = commentsUtil.publishedHumanCommentsByChange(updatedNotes);
+ Optional<HumanComment> updatedComment =
changeComments.stream().filter(c -> c.key.equals(rsrc.getComment().key)).findFirst();
if (!updatedComment.isPresent()) {
// This should not happen as this endpoint should not remove the whole comment.
throw new ResourceNotFoundException("comment not found: " + rsrc.getComment().key);
}
- return Response.ok(commentJson.get().newCommentFormatter().format(updatedComment.get()));
+ return Response.ok(commentJson.get().newHumanCommentFormatter().format(updatedComment.get()));
}
private static String getCommentNewMessage(String name, String reason) {
@@ -110,10 +110,10 @@
}
private class DeleteCommentOp implements BatchUpdateOp {
- private final CommentResource rsrc;
+ private final HumanCommentResource rsrc;
private final String newMessage;
- DeleteCommentOp(CommentResource rsrc, String newMessage) {
+ DeleteCommentOp(HumanCommentResource rsrc, String newMessage) {
this.rsrc = rsrc;
this.newMessage = newMessage;
}
diff --git a/java/com/google/gerrit/server/restapi/change/DeleteDraftComment.java b/java/com/google/gerrit/server/restapi/change/DeleteDraftComment.java
index 89fc3b7..71fd4d2 100644
--- a/java/com/google/gerrit/server/restapi/change/DeleteDraftComment.java
+++ b/java/com/google/gerrit/server/restapi/change/DeleteDraftComment.java
@@ -17,6 +17,7 @@
import static com.google.gerrit.server.CommentsUtil.setCommentCommitId;
import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.extensions.common.CommentInfo;
import com.google.gerrit.extensions.common.Input;
@@ -80,7 +81,7 @@
@Override
public boolean updateChange(ChangeContext ctx)
throws ResourceNotFoundException, PatchListNotAvailableException {
- Optional<Comment> maybeComment =
+ Optional<HumanComment> maybeComment =
commentsUtil.getDraft(ctx.getNotes(), ctx.getIdentifiedUser(), key);
if (!maybeComment.isPresent()) {
return false; // Nothing to do.
@@ -90,9 +91,9 @@
if (ps == null) {
throw new ResourceNotFoundException("patch set not found: " + psId);
}
- Comment c = maybeComment.get();
+ HumanComment c = maybeComment.get();
setCommentCommitId(c, patchListCache, ctx.getChange(), ps);
- commentsUtil.deleteComments(ctx.getUpdate(psId), Collections.singleton(c));
+ commentsUtil.deleteHumanComments(ctx.getUpdate(psId), Collections.singleton(c));
return true;
}
}
diff --git a/java/com/google/gerrit/server/restapi/change/DraftComments.java b/java/com/google/gerrit/server/restapi/change/DraftComments.java
index bab1ac9..ab5b9f4 100644
--- a/java/com/google/gerrit/server/restapi/change/DraftComments.java
+++ b/java/com/google/gerrit/server/restapi/change/DraftComments.java
@@ -14,7 +14,7 @@
package com.google.gerrit.server.restapi.change;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.ChildCollection;
@@ -64,7 +64,7 @@
throws ResourceNotFoundException, AuthException {
checkIdentifiedUser();
String uuid = id.get();
- for (Comment c :
+ for (HumanComment c :
commentsUtil.draftByPatchSetAuthor(
rev.getPatchSet().id(), rev.getAccountId(), rev.getNotes())) {
if (uuid.equals(c.key.uuid)) {
diff --git a/java/com/google/gerrit/server/restapi/change/GetAttentionSet.java b/java/com/google/gerrit/server/restapi/change/GetAttentionSet.java
index 08a963b..6822d91 100644
--- a/java/com/google/gerrit/server/restapi/change/GetAttentionSet.java
+++ b/java/com/google/gerrit/server/restapi/change/GetAttentionSet.java
@@ -18,7 +18,7 @@
import static com.google.gerrit.server.util.AttentionSetUtil.additionsOnly;
import com.google.common.collect.ImmutableSet;
-import com.google.gerrit.extensions.common.AttentionSetEntry;
+import com.google.gerrit.extensions.common.AttentionSetInfo;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.server.account.AccountLoader;
@@ -41,15 +41,15 @@
}
@Override
- public Response<Set<AttentionSetEntry>> apply(ChangeResource changeResource)
+ public Response<Set<AttentionSetInfo>> apply(ChangeResource changeResource)
throws PermissionBackendException {
AccountLoader accountLoader = accountLoaderFactory.create(true);
- ImmutableSet<AttentionSetEntry> response =
+ ImmutableSet<AttentionSetInfo> response =
// This filtering should match ChangeJson.
additionsOnly(changeResource.getNotes().getAttentionSet()).stream()
.map(
a ->
- new AttentionSetEntry(
+ new AttentionSetInfo(
accountLoader.get(a.account()), Timestamp.from(a.timestamp()), a.reason()))
.collect(toImmutableSet());
accountLoader.fill();
diff --git a/java/com/google/gerrit/server/restapi/change/GetComment.java b/java/com/google/gerrit/server/restapi/change/GetComment.java
index 5103325..24085df 100644
--- a/java/com/google/gerrit/server/restapi/change/GetComment.java
+++ b/java/com/google/gerrit/server/restapi/change/GetComment.java
@@ -17,14 +17,14 @@
import com.google.gerrit.extensions.common.CommentInfo;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestReadView;
-import com.google.gerrit.server.change.CommentResource;
+import com.google.gerrit.server.change.HumanCommentResource;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
@Singleton
-public class GetComment implements RestReadView<CommentResource> {
+public class GetComment implements RestReadView<HumanCommentResource> {
private final Provider<CommentJson> commentJson;
@@ -34,7 +34,7 @@
}
@Override
- public Response<CommentInfo> apply(CommentResource rsrc) throws PermissionBackendException {
- return Response.ok(commentJson.get().newCommentFormatter().format(rsrc.getComment()));
+ public Response<CommentInfo> apply(HumanCommentResource rsrc) throws PermissionBackendException {
+ return Response.ok(commentJson.get().newHumanCommentFormatter().format(rsrc.getComment()));
}
}
diff --git a/java/com/google/gerrit/server/restapi/change/GetDraftComment.java b/java/com/google/gerrit/server/restapi/change/GetDraftComment.java
index 797dc9e..ba07b47 100644
--- a/java/com/google/gerrit/server/restapi/change/GetDraftComment.java
+++ b/java/com/google/gerrit/server/restapi/change/GetDraftComment.java
@@ -35,6 +35,6 @@
@Override
public Response<CommentInfo> apply(DraftCommentResource rsrc) throws PermissionBackendException {
- return Response.ok(commentJson.get().newCommentFormatter().format(rsrc.getComment()));
+ return Response.ok(commentJson.get().newHumanCommentFormatter().format(rsrc.getComment()));
}
}
diff --git a/java/com/google/gerrit/server/restapi/change/ListChangeComments.java b/java/com/google/gerrit/server/restapi/change/ListChangeComments.java
index 409b0d5..b842f55 100644
--- a/java/com/google/gerrit/server/restapi/change/ListChangeComments.java
+++ b/java/com/google/gerrit/server/restapi/change/ListChangeComments.java
@@ -18,7 +18,7 @@
import com.google.common.collect.ImmutableList;
import com.google.gerrit.entities.ChangeMessage;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.extensions.common.CommentInfo;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.Response;
@@ -28,7 +28,6 @@
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.query.change.ChangeData;
-import com.google.gerrit.server.restapi.change.CommentJson.CommentFormatter;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
@@ -64,12 +63,12 @@
return getAsList(listComments(rsrc), rsrc);
}
- private Iterable<Comment> listComments(ChangeResource rsrc) {
+ private Iterable<HumanComment> listComments(ChangeResource rsrc) {
ChangeData cd = changeDataFactory.create(rsrc.getNotes());
- return commentsUtil.publishedByChange(cd.notes());
+ return commentsUtil.publishedHumanCommentsByChange(cd.notes());
}
- private ImmutableList<CommentInfo> getAsList(Iterable<Comment> comments, ChangeResource rsrc)
+ private ImmutableList<CommentInfo> getAsList(Iterable<HumanComment> comments, ChangeResource rsrc)
throws PermissionBackendException {
ImmutableList<CommentInfo> commentInfos = getCommentFormatter().formatAsList(comments);
List<ChangeMessage> changeMessages = changeMessagesUtil.byChange(rsrc.getNotes());
@@ -77,8 +76,8 @@
return commentInfos;
}
- private Map<String, List<CommentInfo>> getAsMap(Iterable<Comment> comments, ChangeResource rsrc)
- throws PermissionBackendException {
+ private Map<String, List<CommentInfo>> getAsMap(
+ Iterable<HumanComment> comments, ChangeResource rsrc) throws PermissionBackendException {
Map<String, List<CommentInfo>> commentInfosMap = getCommentFormatter().format(comments);
List<CommentInfo> commentInfos =
commentInfosMap.values().stream().flatMap(List::stream).collect(toList());
@@ -87,7 +86,7 @@
return commentInfosMap;
}
- private CommentFormatter getCommentFormatter() {
- return commentJson.get().setFillAccounts(true).setFillPatchSet(true).newCommentFormatter();
+ private CommentJson.HumanCommentFormatter getCommentFormatter() {
+ return commentJson.get().setFillAccounts(true).setFillPatchSet(true).newHumanCommentFormatter();
}
}
diff --git a/java/com/google/gerrit/server/restapi/change/ListChangeDrafts.java b/java/com/google/gerrit/server/restapi/change/ListChangeDrafts.java
index 24e1d40..3841dc1 100644
--- a/java/com/google/gerrit/server/restapi/change/ListChangeDrafts.java
+++ b/java/com/google/gerrit/server/restapi/change/ListChangeDrafts.java
@@ -14,7 +14,7 @@
package com.google.gerrit.server.restapi.change;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.extensions.common.CommentInfo;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.Response;
@@ -23,7 +23,7 @@
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.query.change.ChangeData;
-import com.google.gerrit.server.restapi.change.CommentJson.CommentFormatter;
+import com.google.gerrit.server.restapi.change.CommentJson.HumanCommentFormatter;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
@@ -46,7 +46,7 @@
this.commentsUtil = commentsUtil;
}
- private Iterable<Comment> listComments(ChangeResource rsrc) {
+ private Iterable<HumanComment> listComments(ChangeResource rsrc) {
ChangeData cd = changeDataFactory.create(rsrc.getNotes());
return commentsUtil.draftByChangeAuthor(cd.notes(), rsrc.getUser().getAccountId());
}
@@ -68,7 +68,11 @@
return getCommentFormatter().formatAsList(listComments(rsrc));
}
- private CommentFormatter getCommentFormatter() {
- return commentJson.get().setFillAccounts(false).setFillPatchSet(true).newCommentFormatter();
+ private HumanCommentFormatter getCommentFormatter() {
+ return commentJson
+ .get()
+ .setFillAccounts(false)
+ .setFillPatchSet(true)
+ .newHumanCommentFormatter();
}
}
diff --git a/java/com/google/gerrit/server/restapi/change/ListRevisionComments.java b/java/com/google/gerrit/server/restapi/change/ListRevisionComments.java
index de05d2a..88309ed 100644
--- a/java/com/google/gerrit/server/restapi/change/ListRevisionComments.java
+++ b/java/com/google/gerrit/server/restapi/change/ListRevisionComments.java
@@ -14,7 +14,7 @@
package com.google.gerrit.server.restapi.change;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.change.RevisionResource;
import com.google.gerrit.server.notedb.ChangeNotes;
@@ -35,7 +35,7 @@
}
@Override
- protected Iterable<Comment> listComments(RevisionResource rsrc) {
+ protected Iterable<HumanComment> listComments(RevisionResource rsrc) {
ChangeNotes notes = rsrc.getNotes();
return commentsUtil.publishedByPatchSet(notes, rsrc.getPatchSet().id());
}
diff --git a/java/com/google/gerrit/server/restapi/change/ListRevisionDrafts.java b/java/com/google/gerrit/server/restapi/change/ListRevisionDrafts.java
index 199a752..a5fbd92 100644
--- a/java/com/google/gerrit/server/restapi/change/ListRevisionDrafts.java
+++ b/java/com/google/gerrit/server/restapi/change/ListRevisionDrafts.java
@@ -15,7 +15,7 @@
package com.google.gerrit.server.restapi.change;
import com.google.common.collect.ImmutableList;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.extensions.common.CommentInfo;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestReadView;
@@ -39,7 +39,7 @@
this.commentsUtil = commentsUtil;
}
- protected Iterable<Comment> listComments(RevisionResource rsrc) {
+ protected Iterable<HumanComment> listComments(RevisionResource rsrc) {
return commentsUtil.draftByPatchSetAuthor(
rsrc.getPatchSet().id(), rsrc.getAccountId(), rsrc.getNotes());
}
@@ -55,7 +55,7 @@
commentJson
.get()
.setFillAccounts(includeAuthorInfo())
- .newCommentFormatter()
+ .newHumanCommentFormatter()
.format(listComments(rsrc)));
}
@@ -64,7 +64,7 @@
return commentJson
.get()
.setFillAccounts(includeAuthorInfo())
- .newCommentFormatter()
+ .newHumanCommentFormatter()
.formatAsList(listComments(rsrc));
}
}
diff --git a/java/com/google/gerrit/server/restapi/change/Module.java b/java/com/google/gerrit/server/restapi/change/Module.java
index 387d0a8..52a8f47 100644
--- a/java/com/google/gerrit/server/restapi/change/Module.java
+++ b/java/com/google/gerrit/server/restapi/change/Module.java
@@ -18,10 +18,10 @@
import static com.google.gerrit.server.change.ChangeEditResource.CHANGE_EDIT_KIND;
import static com.google.gerrit.server.change.ChangeMessageResource.CHANGE_MESSAGE_KIND;
import static com.google.gerrit.server.change.ChangeResource.CHANGE_KIND;
-import static com.google.gerrit.server.change.CommentResource.COMMENT_KIND;
import static com.google.gerrit.server.change.DraftCommentResource.DRAFT_COMMENT_KIND;
import static com.google.gerrit.server.change.FileResource.FILE_KIND;
import static com.google.gerrit.server.change.FixResource.FIX_KIND;
+import static com.google.gerrit.server.change.HumanCommentResource.COMMENT_KIND;
import static com.google.gerrit.server.change.ReviewerResource.REVIEWER_KIND;
import static com.google.gerrit.server.change.RevisionResource.REVISION_KIND;
import static com.google.gerrit.server.change.RobotCommentResource.ROBOT_COMMENT_KIND;
diff --git a/java/com/google/gerrit/server/restapi/change/PostReview.java b/java/com/google/gerrit/server/restapi/change/PostReview.java
index a16d4f9..6edbdb0 100644
--- a/java/com/google/gerrit/server/restapi/change/PostReview.java
+++ b/java/com/google/gerrit/server/restapi/change/PostReview.java
@@ -49,6 +49,7 @@
import com.google.gerrit.entities.Comment;
import com.google.gerrit.entities.FixReplacement;
import com.google.gerrit.entities.FixSuggestion;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.Patch;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.PatchSetApproval;
@@ -177,6 +178,7 @@
private final ProjectCache projectCache;
private final PermissionBackend permissionBackend;
private final PluginSetContext<CommentValidator> commentValidators;
+ private final PostReviewAttentionSet postReviewAttentionSet;
private final boolean strictLabels;
@Inject
@@ -200,7 +202,8 @@
WorkInProgressOp.Factory workInProgressOpFactory,
ProjectCache projectCache,
PermissionBackend permissionBackend,
- PluginSetContext<CommentValidator> commentValidators) {
+ PluginSetContext<CommentValidator> commentValidators,
+ PostReviewAttentionSet postReviewAttentionSet) {
this.updateFactory = updateFactory;
this.changeResourceFactory = changeResourceFactory;
this.changeDataFactory = changeDataFactory;
@@ -220,6 +223,7 @@
this.projectCache = projectCache;
this.permissionBackend = permissionBackend;
this.commentValidators = commentValidators;
+ this.postReviewAttentionSet = postReviewAttentionSet;
this.strictLabels = gerritConfig.getBoolean("change", "strictLabels", false);
}
@@ -378,6 +382,8 @@
NotifyResolver.Result notify = notifyResolver.resolve(input.notify, input.notifyDetails);
bu.setNotify(notify);
+ // Adjust the attention set based on the input
+ postReviewAttentionSet.updateAttentionSet(bu, revision, input, reviewerResults);
bu.execute();
// Re-read change to take into account results of the update.
@@ -811,8 +817,8 @@
}
/**
- * Used to compare existing {@link Comment}-s with {@link CommentInput} comments by copying only
- * the fields to compare.
+ * Used to compare existing {@link HumanComment}-s with {@link CommentInput} comments by copying
+ * only the fields to compare.
*/
@AutoValue
abstract static class CommentSetEntry {
@@ -942,7 +948,7 @@
// HashMap instead of Collections.emptyMap() avoids warning about remove() on immutable
// object.
- Map<String, Comment> drafts = new HashMap<>();
+ Map<String, HumanComment> drafts = new HashMap<>();
// If there are inputComments we need the deduplication loop below, so we have to read (and
// publish) drafts here.
if (!inputComments.isEmpty() || in.drafts != DraftHandling.KEEP) {
@@ -954,7 +960,7 @@
}
// This will be populated with Comment-s created from inputComments.
- List<Comment> toPublish = new ArrayList<>();
+ List<HumanComment> toPublish = new ArrayList<>();
Set<CommentSetEntry> existingComments =
in.omitDuplicateComments ? readExistingComments(ctx) : Collections.emptySet();
@@ -965,11 +971,11 @@
for (Map.Entry<String, List<CommentInput>> entry : inputComments.entrySet()) {
String path = entry.getKey();
for (CommentInput inputComment : entry.getValue()) {
- Comment comment = drafts.remove(Url.decode(inputComment.id));
+ HumanComment comment = drafts.remove(Url.decode(inputComment.id));
if (comment == null) {
String parent = Url.decode(inputComment.inReplyTo);
comment =
- commentsUtil.newComment(
+ commentsUtil.newHumanComment(
ctx,
path,
psId,
@@ -1014,7 +1020,7 @@
break;
}
ChangeUpdate changeUpdate = ctx.getUpdate(psId);
- commentsUtil.putComments(changeUpdate, Comment.Status.PUBLISHED, toPublish);
+ commentsUtil.putHumanComments(changeUpdate, HumanComment.Status.PUBLISHED, toPublish);
comments.addAll(toPublish);
return !toPublish.isEmpty();
}
@@ -1134,7 +1140,7 @@
}
private Set<CommentSetEntry> readExistingComments(ChangeContext ctx) {
- return commentsUtil.publishedByChange(ctx.getNotes()).stream()
+ return commentsUtil.publishedHumanCommentsByChange(ctx.getNotes()).stream()
.map(CommentSetEntry::create)
.collect(toSet());
}
@@ -1145,7 +1151,7 @@
.collect(toSet());
}
- private Map<String, Comment> changeDrafts(ChangeContext ctx) {
+ private Map<String, HumanComment> changeDrafts(ChangeContext ctx) {
return commentsUtil.draftByChangeAuthor(ctx.getNotes(), user.getAccountId()).stream()
.collect(
Collectors.toMap(
@@ -1156,7 +1162,7 @@
}));
}
- private Map<String, Comment> patchSetDrafts(ChangeContext ctx) {
+ private Map<String, HumanComment> patchSetDrafts(ChangeContext ctx) {
return commentsUtil.draftByPatchSetAuthor(psId, user.getAccountId(), ctx.getNotes()).stream()
.collect(Collectors.toMap(c -> c.key.uuid, c -> c));
}
diff --git a/java/com/google/gerrit/server/restapi/change/PostReviewAttentionSet.java b/java/com/google/gerrit/server/restapi/change/PostReviewAttentionSet.java
new file mode 100644
index 0000000..3541ef0
--- /dev/null
+++ b/java/com/google/gerrit/server/restapi/change/PostReviewAttentionSet.java
@@ -0,0 +1,238 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.restapi.change;
+
+import static com.google.gerrit.server.notedb.ReviewerStateInternal.REVIEWER;
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toSet;
+
+import com.google.gerrit.entities.Account;
+import com.google.gerrit.extensions.api.changes.AttentionSetInput;
+import com.google.gerrit.extensions.api.changes.ReviewInput;
+import com.google.gerrit.extensions.restapi.AuthException;
+import com.google.gerrit.extensions.restapi.BadRequestException;
+import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
+import com.google.gerrit.server.ApprovalsUtil;
+import com.google.gerrit.server.account.AccountResolver;
+import com.google.gerrit.server.change.AddToAttentionSetOp;
+import com.google.gerrit.server.change.AttentionSetUnchangedOp;
+import com.google.gerrit.server.change.RemoveFromAttentionSetOp;
+import com.google.gerrit.server.change.ReviewerAdder;
+import com.google.gerrit.server.change.RevisionResource;
+import com.google.gerrit.server.notedb.ChangeUpdate;
+import com.google.gerrit.server.permissions.ChangePermission;
+import com.google.gerrit.server.permissions.PermissionBackend;
+import com.google.gerrit.server.permissions.PermissionBackendException;
+import com.google.gerrit.server.update.BatchUpdate;
+import com.google.gerrit.server.util.AttentionSetUtil;
+import com.google.inject.Inject;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.eclipse.jgit.errors.ConfigInvalidException;
+
+/**
+ * This class is used by {@link PostReview} to update the attention set when performing a review.
+ */
+public class PostReviewAttentionSet {
+
+ private final PermissionBackend permissionBackend;
+ private final AddToAttentionSetOp.Factory addToAttentionSetOpFactory;
+ private final RemoveFromAttentionSetOp.Factory removeFromAttentionSetOpFactory;
+ private final ApprovalsUtil approvalsUtil;
+ private final AccountResolver accountResolver;
+
+ @Inject
+ PostReviewAttentionSet(
+ PermissionBackend permissionBackend,
+ AddToAttentionSetOp.Factory addToAttentionSetOpFactory,
+ RemoveFromAttentionSetOp.Factory removeFromAttentionSetOpFactory,
+ ApprovalsUtil approvalsUtil,
+ AccountResolver accountResolver) {
+ this.permissionBackend = permissionBackend;
+ this.addToAttentionSetOpFactory = addToAttentionSetOpFactory;
+ this.removeFromAttentionSetOpFactory = removeFromAttentionSetOpFactory;
+ this.approvalsUtil = approvalsUtil;
+ this.accountResolver = accountResolver;
+ }
+
+ /**
+ * Adjusts the attention set by adding and removing users. If the same user should be added and
+ * removed or added/removed twice, the user will only be added/removed once, based on first
+ * addition/removal.
+ */
+ public void updateAttentionSet(
+ BatchUpdate bu,
+ RevisionResource revision,
+ ReviewInput input,
+ List<ReviewerAdder.ReviewerAddition> reviewerResults)
+ throws BadRequestException, IOException, PermissionBackendException,
+ UnprocessableEntityException, ConfigInvalidException {
+ processManualUpdates(bu, revision, input);
+ if (input.ignoreDefaultAttentionSetRules) {
+
+ // If We ignore default attention set rules it means we need to pass this information to
+ // ChangeUpdate. Also, we should stop all other attention set update that are part of
+ // this method (that happen in PostReview.
+ bu.addOp(revision.getChange().getId(), new AttentionSetUnchangedOp());
+ return;
+ }
+ processRules(bu, revision, input, reviewerResults);
+ }
+
+ /**
+ * Process the default rules of the attention set. All of the default rules except adding/removing
+ * reviewers and entering/exiting WIP state are done here, and the rest are done in {@link
+ * ChangeUpdate}
+ */
+ private void processRules(
+ BatchUpdate bu,
+ RevisionResource revision,
+ ReviewInput input,
+ List<ReviewerAdder.ReviewerAddition> reviewerResults) {
+ // Replying removes the publishing user from the attention set.
+ RemoveFromAttentionSetOp removeFromAttentionSetOp =
+ removeFromAttentionSetOpFactory.create(revision.getAccountId(), "removed on reply");
+ bu.addOp(revision.getChange().getId(), removeFromAttentionSetOp);
+
+ // The rest of the conditions only apply if the change is ready for review
+ if (!isReadyForReview(revision, input)) {
+ return;
+ }
+ Account.Id uploader = revision.getPatchSet().uploader();
+ Account.Id owner = revision.getChange().getOwner();
+ Account.Id currentUser = revision.getAccountId();
+ if (currentUser.equals(uploader) && !uploader.equals(owner)) {
+ // When the uploader replies, add the owner to the attention set.
+ AddToAttentionSetOp addToAttentionSetOp =
+ addToAttentionSetOpFactory.create(owner, "uploader replied");
+ bu.addOp(revision.getChange().getId(), addToAttentionSetOp);
+ }
+ if (currentUser.equals(uploader) || currentUser.equals(owner)) {
+ // When the owner or uploader replies, add the reviewers to the attention set.
+ // Filter by users that are currently reviewers.
+ Set<Account.Id> finalCCs =
+ reviewerResults.stream()
+ .filter(r -> r.result.ccs == null)
+ .map(r -> r.reviewers)
+ .flatMap(x -> x.stream())
+ .collect(toSet());
+ for (Account.Id reviewer :
+ approvalsUtil.getReviewers(revision.getChangeResource().getNotes()).byState(REVIEWER)
+ .stream()
+ .filter(r -> !finalCCs.contains(r))
+ .collect(toList())) {
+ AddToAttentionSetOp addToAttentionSetOp =
+ addToAttentionSetOpFactory.create(reviewer, "owner or uploader replied");
+ bu.addOp(revision.getChange().getId(), addToAttentionSetOp);
+ }
+ }
+ if (!currentUser.equals(uploader) && !currentUser.equals(owner)) {
+ // When neither the uploader nor the owner (reviewer or cc) replies, add the owner and the
+ // uploader to the attention set.
+ AddToAttentionSetOp addToAttentionSetOp =
+ addToAttentionSetOpFactory.create(owner, "reviewer or cc replied");
+ bu.addOp(revision.getChange().getId(), addToAttentionSetOp);
+
+ if (owner.get() != uploader.get()) {
+ addToAttentionSetOp = addToAttentionSetOpFactory.create(uploader, "reviewer or cc replied");
+ bu.addOp(revision.getChange().getId(), addToAttentionSetOp);
+ }
+ }
+ }
+
+ /** Process the manual updates of the attention set. */
+ private void processManualUpdates(BatchUpdate bu, RevisionResource revision, ReviewInput input)
+ throws BadRequestException, IOException, PermissionBackendException,
+ UnprocessableEntityException, ConfigInvalidException {
+ Set<Account.Id> accountsChangedInCommit = new HashSet();
+ // If we specify a user to remove, and the user is in the attention set, we remove it.
+ if (input.removeFromAttentionSet != null) {
+ for (AttentionSetInput remove : input.removeFromAttentionSet) {
+ removeFromAttentionSet(bu, revision, remove, accountsChangedInCommit);
+ }
+ }
+
+ // If we don't specify a user to remove, but we specify addition for that user, the user will be
+ // added if they are not in the attention set yet.
+ if (input.addToAttentionSet != null) {
+ for (AttentionSetInput add : input.addToAttentionSet) {
+ addToAttentionSet(bu, revision, add, accountsChangedInCommit);
+ }
+ }
+ }
+
+ private static boolean isReadyForReview(RevisionResource revision, ReviewInput input) {
+ return (!revision.getChange().isWorkInProgress() && !input.workInProgress) || input.ready;
+ }
+
+ private void addToAttentionSet(
+ BatchUpdate bu,
+ RevisionResource revision,
+ AttentionSetInput add,
+ Set<Account.Id> accountsChangedInCommitv)
+ throws BadRequestException, IOException, PermissionBackendException,
+ UnprocessableEntityException, ConfigInvalidException {
+ AttentionSetUtil.validateInput(add);
+ Account.Id attentionUserId =
+ getAccountIdAndValidateUser(revision, add.user, accountsChangedInCommitv);
+
+ AddToAttentionSetOp addToAttentionSetOp =
+ addToAttentionSetOpFactory.create(attentionUserId, add.reason);
+ bu.addOp(revision.getChange().getId(), addToAttentionSetOp);
+ }
+
+ private void removeFromAttentionSet(
+ BatchUpdate bu,
+ RevisionResource revision,
+ AttentionSetInput remove,
+ Set<Account.Id> accountsChangedInCommit)
+ throws BadRequestException, IOException, PermissionBackendException,
+ UnprocessableEntityException, ConfigInvalidException {
+ AttentionSetUtil.validateInput(remove);
+ Account.Id attentionUserId =
+ getAccountIdAndValidateUser(revision, remove.user, accountsChangedInCommit);
+
+ RemoveFromAttentionSetOp removeFromAttentionSetOp =
+ removeFromAttentionSetOpFactory.create(attentionUserId, remove.reason);
+ bu.addOp(revision.getChange().getId(), removeFromAttentionSetOp);
+ }
+
+ private Account.Id getAccountIdAndValidateUser(
+ RevisionResource revision, String user, Set<Account.Id> accountsChangedInCommit)
+ throws ConfigInvalidException, IOException, PermissionBackendException,
+ UnprocessableEntityException, BadRequestException {
+ Account.Id attentionUserId = accountResolver.resolve(user).asUnique().account().id();
+ try {
+ permissionBackend
+ .absentUser(attentionUserId)
+ .change(revision.getNotes())
+ .check(ChangePermission.READ);
+ } catch (AuthException e) {
+ throw new UnprocessableEntityException(
+ "Can't add to attention set: Read not permitted for " + attentionUserId, e);
+ }
+ if (accountsChangedInCommit.contains(attentionUserId)) {
+ throw new BadRequestException(
+ String.format(
+ "%s can not be added/removed twice, and can not be added and "
+ + "removed at the same time",
+ user));
+ }
+ accountsChangedInCommit.add(attentionUserId);
+ return attentionUserId;
+ }
+}
diff --git a/java/com/google/gerrit/server/restapi/change/PutDraftComment.java b/java/com/google/gerrit/server/restapi/change/PutDraftComment.java
index ea58365..f327f16 100644
--- a/java/com/google/gerrit/server/restapi/change/PutDraftComment.java
+++ b/java/com/google/gerrit/server/restapi/change/PutDraftComment.java
@@ -18,6 +18,7 @@
import static com.google.gerrit.server.CommentsUtil.setCommentCommitId;
import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.extensions.api.changes.DraftInput;
import com.google.gerrit.extensions.common.CommentInfo;
@@ -93,7 +94,7 @@
bu.addOp(rsrc.getChange().getId(), op);
bu.execute();
return Response.ok(
- commentJson.get().setFillAccounts(false).newCommentFormatter().format(op.comment));
+ commentJson.get().setFillAccounts(false).newHumanCommentFormatter().format(op.comment));
}
}
@@ -101,7 +102,7 @@
private final Comment.Key key;
private final DraftInput in;
- private Comment comment;
+ private HumanComment comment;
private Op(Comment.Key key, DraftInput in) {
this.key = key;
@@ -111,15 +112,15 @@
@Override
public boolean updateChange(ChangeContext ctx)
throws ResourceNotFoundException, PatchListNotAvailableException {
- Optional<Comment> maybeComment =
+ Optional<HumanComment> maybeComment =
commentsUtil.getDraft(ctx.getNotes(), ctx.getIdentifiedUser(), key);
if (!maybeComment.isPresent()) {
// Disappeared out from under us. Can't easily fall back to insert,
// because the input might be missing required fields. Just give up.
throw new ResourceNotFoundException("comment not found: " + key);
}
- Comment origComment = maybeComment.get();
- comment = new Comment(origComment);
+ HumanComment origComment = maybeComment.get();
+ comment = new HumanComment(origComment);
// Copy constructor preserved old real author; replace with current real
// user.
ctx.getUser().updateRealAccountId(comment::setRealAuthor);
@@ -135,17 +136,19 @@
// Updating the path alters the primary key, which isn't possible.
// Delete then recreate the comment instead of an update.
- commentsUtil.deleteComments(update, Collections.singleton(origComment));
+ commentsUtil.deleteHumanComments(update, Collections.singleton(origComment));
comment.key.filename = in.path;
}
setCommentCommitId(comment, patchListCache, ctx.getChange(), ps);
- commentsUtil.putComments(
- update, Comment.Status.DRAFT, Collections.singleton(update(comment, in, ctx.getWhen())));
+ commentsUtil.putHumanComments(
+ update,
+ HumanComment.Status.DRAFT,
+ Collections.singleton(update(comment, in, ctx.getWhen())));
return true;
}
}
- private static Comment update(Comment e, DraftInput in, Timestamp when) {
+ private static HumanComment update(HumanComment e, DraftInput in, Timestamp when) {
if (in.side != null) {
e.side = in.side();
}
diff --git a/java/com/google/gerrit/server/restapi/change/RemoveFromAttentionSet.java b/java/com/google/gerrit/server/restapi/change/RemoveFromAttentionSet.java
index ccf375a..ae2f2bf 100644
--- a/java/com/google/gerrit/server/restapi/change/RemoveFromAttentionSet.java
+++ b/java/com/google/gerrit/server/restapi/change/RemoveFromAttentionSet.java
@@ -15,11 +15,13 @@
package com.google.gerrit.server.restapi.change;
import com.google.common.base.Strings;
-import com.google.gerrit.extensions.api.changes.RemoveFromAttentionSetInput;
+import com.google.gerrit.entities.Account;
+import com.google.gerrit.extensions.api.changes.AttentionSetInput;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.RestModifyView;
+import com.google.gerrit.server.account.AccountResolver;
import com.google.gerrit.server.change.AttentionSetEntryResource;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.change.RemoveFromAttentionSetOp;
@@ -33,20 +35,24 @@
/** Removes a single user from the attention set. */
public class RemoveFromAttentionSet
- implements RestModifyView<AttentionSetEntryResource, RemoveFromAttentionSetInput> {
+ implements RestModifyView<AttentionSetEntryResource, AttentionSetInput> {
private final BatchUpdate.Factory updateFactory;
private final RemoveFromAttentionSetOp.Factory opFactory;
+ private final AccountResolver accountResolver;
@Inject
RemoveFromAttentionSet(
- BatchUpdate.Factory updateFactory, RemoveFromAttentionSetOp.Factory opFactory) {
+ BatchUpdate.Factory updateFactory,
+ RemoveFromAttentionSetOp.Factory opFactory,
+ AccountResolver accountResolver) {
this.updateFactory = updateFactory;
this.opFactory = opFactory;
+ this.accountResolver = accountResolver;
}
@Override
public Response<Object> apply(
- AttentionSetEntryResource attentionResource, RemoveFromAttentionSetInput input)
+ AttentionSetEntryResource attentionResource, AttentionSetInput input)
throws RestApiException, PermissionBackendException, IOException, ConfigInvalidException,
UpdateException {
if (input == null) {
@@ -56,6 +62,20 @@
if (input.reason.isEmpty()) {
throw new BadRequestException("missing field: reason");
}
+ input.user = Strings.nullToEmpty(input.user).trim();
+ if (!input.user.isEmpty()) {
+ Account.Id attentionUserId = null;
+ try {
+ attentionUserId = accountResolver.resolve(input.user).asUnique().account().id();
+ } catch (AccountResolver.UnresolvableAccountException ex) {
+ throw new BadRequestException(
+ "The user specified in the input body couldn't be found.", ex);
+ }
+ if (attentionUserId.get() != attentionResource.getAccountId().get()) {
+ throw new BadRequestException(
+ "The field \"user\" must be empty, or must match the user specified in the URL.");
+ }
+ }
ChangeResource changeResource = attentionResource.getChangeResource();
try (BatchUpdate bu =
updateFactory.create(
diff --git a/java/com/google/gerrit/server/restapi/config/GetServerInfo.java b/java/com/google/gerrit/server/restapi/config/GetServerInfo.java
index c83bf42..0198c36 100644
--- a/java/com/google/gerrit/server/restapi/config/GetServerInfo.java
+++ b/java/com/google/gerrit/server/restapi/config/GetServerInfo.java
@@ -335,11 +335,14 @@
}
private static final String DEFAULT_THEME = "/static/" + SitePaths.THEME_FILENAME;
+ private static final String DEFAULT_THEME_JS = "/static/" + SitePaths.THEME_JS_FILENAME;
private String getDefaultTheme() {
if (config.getString("theme", null, "enableDefault") == null) {
// If not explicitly enabled or disabled, check for the existence of the theme file.
- return Files.exists(sitePaths.site_theme) ? DEFAULT_THEME : null;
+ return Files.exists(sitePaths.site_theme_js)
+ ? DEFAULT_THEME_JS
+ : Files.exists(sitePaths.site_theme) ? DEFAULT_THEME : null;
}
if (config.getBoolean("theme", null, "enableDefault", true)) {
// Return non-null theme path without checking for file existence. Even if the file doesn't
diff --git a/java/com/google/gerrit/server/submit/MergeOp.java b/java/com/google/gerrit/server/submit/MergeOp.java
index 9018d9d..f96b0c5 100644
--- a/java/com/google/gerrit/server/submit/MergeOp.java
+++ b/java/com/google/gerrit/server/submit/MergeOp.java
@@ -635,13 +635,13 @@
throw e;
}
- // BatchUpdate may have inadvertently wrapped an IntegrationException
+ // BatchUpdate may have inadvertently wrapped an IntegrationConflictException
// thrown by some legacy SubmitStrategyOp code that intended the error
// message to be user-visible. Copy the message from the wrapped
// exception.
//
// If you happen across one of these, the correct fix is to convert the
- // inner IntegrationException to a ResourceConflictException.
+ // inner IntegrationConflictException to a ResourceConflictException.
if (e.getCause() instanceof IntegrationConflictException) {
throw (IntegrationConflictException) e.getCause();
}
diff --git a/java/com/google/gerrit/server/submit/SubmitStrategyOp.java b/java/com/google/gerrit/server/submit/SubmitStrategyOp.java
index 5558c74..ab28aa9 100644
--- a/java/com/google/gerrit/server/submit/SubmitStrategyOp.java
+++ b/java/com/google/gerrit/server/submit/SubmitStrategyOp.java
@@ -23,7 +23,6 @@
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.data.SubmitRecord;
-import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.ChangeMessage;
@@ -36,13 +35,11 @@
import com.google.gerrit.server.ApprovalsUtil;
import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.IdentifiedUser;
-import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.change.LabelNormalizer;
import com.google.gerrit.server.git.CodeReviewCommit;
import com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk;
import com.google.gerrit.server.git.GroupCollector;
import com.google.gerrit.server.git.MergeUtil;
-import com.google.gerrit.server.notedb.ChangeNoteUtil;
import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.project.ProjectConfig;
import com.google.gerrit.server.project.ProjectState;
@@ -394,24 +391,13 @@
}
}
- private String getByAccountName() {
- requireNonNull(submitter, "getByAccountName called before submitter populated");
- Optional<Account> account =
- args.accountCache.get(submitter.accountId()).map(AccountState::account);
- if (account.isPresent() && account.get().fullName() != null) {
- return " by " + ChangeNoteUtil.getAccountIdAsUsername(account.get().id());
- }
- return "";
- }
-
private ChangeMessage message(ChangeContext ctx, CodeReviewCommit commit, CommitMergeStatus s) {
requireNonNull(s, "CommitMergeStatus may not be null");
String txt = s.getDescription();
if (s == CommitMergeStatus.CLEAN_MERGE) {
- return message(ctx, commit.getPatchsetId(), txt + getByAccountName());
+ return message(ctx, commit.getPatchsetId(), txt);
} else if (s == CommitMergeStatus.CLEAN_REBASE || s == CommitMergeStatus.CLEAN_PICK) {
- return message(
- ctx, commit.getPatchsetId(), txt + " as " + commit.name() + getByAccountName());
+ return message(ctx, commit.getPatchsetId(), txt + " as " + commit.name());
} else if (s == CommitMergeStatus.SKIPPED_IDENTICAL_TREE) {
return message(ctx, commit.getPatchsetId(), txt);
} else if (s == CommitMergeStatus.ALREADY_MERGED) {
diff --git a/java/com/google/gerrit/server/util/AttentionSetUtil.java b/java/com/google/gerrit/server/util/AttentionSetUtil.java
index ad2c98c..8252e8e 100644
--- a/java/com/google/gerrit/server/util/AttentionSetUtil.java
+++ b/java/com/google/gerrit/server/util/AttentionSetUtil.java
@@ -14,9 +14,12 @@
package com.google.gerrit.server.util;
+import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.entities.AttentionSetUpdate;
import com.google.gerrit.entities.AttentionSetUpdate.Operation;
+import com.google.gerrit.extensions.api.changes.AttentionSetInput;
+import com.google.gerrit.extensions.restapi.BadRequestException;
import java.util.Collection;
/** Common helpers for dealing with attention set data structures. */
@@ -29,5 +32,21 @@
.collect(ImmutableSet.toImmutableSet());
}
+ /**
+ * Validates the input for AttentionSetInput. This must be called for all inputs that relate to
+ * adding or removing attention set entries, except for {@link
+ * com.google.gerrit.server.restapi.change.RemoveFromAttentionSet}.
+ */
+ public static void validateInput(AttentionSetInput input) throws BadRequestException {
+ input.user = Strings.nullToEmpty(input.user).trim();
+ if (input.user.isEmpty()) {
+ throw new BadRequestException("missing field: user");
+ }
+ input.reason = Strings.nullToEmpty(input.reason).trim();
+ if (input.reason.isEmpty()) {
+ throw new BadRequestException("missing field: reason");
+ }
+ }
+
private AttentionSetUtil() {}
}
diff --git a/java/com/google/gerrit/truth/NullAwareCorrespondence.java b/java/com/google/gerrit/truth/NullAwareCorrespondence.java
new file mode 100644
index 0000000..687ad94
--- /dev/null
+++ b/java/com/google/gerrit/truth/NullAwareCorrespondence.java
@@ -0,0 +1,92 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.truth;
+
+import com.google.common.base.Function;
+import com.google.common.truth.Correspondence;
+import java.util.Optional;
+
+/** Utility class for constructing null aware {@link Correspondence}s. */
+public class NullAwareCorrespondence {
+ /**
+ * Constructs a {@link Correspondence} that compares elements by transforming the actual elements
+ * using the given function and testing for equality with the expected elements.
+ *
+ * <p>If the actual element is null, it will correspond to a null expected element. This is
+ * different to {@link Correspondence#transforming(Function, String)} which would invoke the
+ * function with a {@code null} argument, requiring the function being able to handle {@code
+ * null}.
+ *
+ * @param actualTransform a {@link Function} taking an actual value and returning a new value
+ * which will be compared with an expected value to determine whether they correspond
+ * @param description should fill the gap in a failure message of the form {@code "not true that
+ * <some actual element> is an element that <description> <some expected element>"}, e.g.
+ * {@code "has an ID of"}
+ */
+ public static <A, E> Correspondence<A, E> transforming(
+ Function<A, ? extends E> actualTransform, String description) {
+ return Correspondence.transforming(
+ actualValue -> Optional.ofNullable(actualValue).map(actualTransform).orElse(null),
+ description);
+ }
+
+ /**
+ * Constructs a {@link Correspondence} that compares elements by transforming the actual elements
+ * using the given function and testing for equality with the expected elements.
+ *
+ * <p>If the actual element is null, it will correspond to a null expected element. This is
+ * different to {@link Correspondence#transforming(Function, Function, String)} which would invoke
+ * the function with a {@code null} argument, requiring the function being able to handle {@code
+ * null}.
+ *
+ * <p>If the expected element is null, it will correspond to a new null expected element. This is
+ * different to {@link Correspondence#transforming(Function, Function, String)} which would invoke
+ * the function with a {@code null} argument, requiring the function being able to handle {@code
+ * null}.
+ *
+ * @param actualTransform a {@link Function} taking an actual value and returning a new value
+ * which will be compared with an expected value to determine whether they correspond
+ * @param expectedTransform a {@link Function} taking an expected value and returning a new value
+ * which will be compared with a transformed actual value
+ * @param description should fill the gap in a failure message of the form {@code "not true that
+ * <some actual element> is an element that <description> <some expected element>"}, e.g.
+ * {@code "has an ID of"}
+ */
+ public static <A, E> Correspondence<A, E> transforming(
+ Function<A, ? extends E> actualTransform,
+ Function<E, ?> expectedTransform,
+ String description) {
+ return Correspondence.transforming(
+ actualValue -> Optional.ofNullable(actualValue).map(actualTransform).orElse(null),
+ expectedValue -> Optional.ofNullable(expectedValue).map(expectedTransform).orElse(null),
+ description);
+ }
+
+ /**
+ * Private constructor to prevent instantiation of this class.
+ *
+ * <p>This class contains only static method and hence never needs to be instantiated.
+ */
+ private NullAwareCorrespondence() {}
+}
diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java b/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
index f9ba8a2..0cd6182 100644
--- a/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
@@ -148,6 +148,7 @@
import com.google.gerrit.server.validators.ValidationException;
import com.google.gerrit.testing.ConfigSuite;
import com.google.gerrit.testing.FakeEmailSender.Message;
+import com.google.gerrit.truth.NullAwareCorrespondence;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.jcraft.jsch.KeyPair;
@@ -161,7 +162,6 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
-import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -2901,12 +2901,7 @@
}
private static Correspondence<GroupInfo, String> getGroupToNameCorrespondence() {
- return Correspondence.from(
- (actualGroup, expectedName) -> {
- String groupName = actualGroup == null ? null : actualGroup.name;
- return Objects.equals(groupName, expectedName);
- },
- "has name");
+ return NullAwareCorrespondence.transforming(groupInfo -> groupInfo.name, "has name");
}
private void assertSequenceNumbers(List<SshKeyInfo> sshKeys) {
diff --git a/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java b/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
index dcf2afd..8bc9cd1 100644
--- a/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
@@ -100,6 +100,7 @@
import com.google.gerrit.server.util.MagicBranch;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.gerrit.testing.GerritJUnit.ThrowingRunnable;
+import com.google.gerrit.truth.NullAwareCorrespondence;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Module;
@@ -111,7 +112,6 @@
import java.util.Collection;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
import java.util.stream.Stream;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.junit.TestRepository;
@@ -1517,12 +1517,8 @@
}
private static Correspondence<AccountInfo, String> getAccountToUsernameCorrespondence() {
- return Correspondence.from(
- (actualAccount, expectedName) -> {
- String username = actualAccount == null ? null : actualAccount.username;
- return Objects.equals(username, expectedName);
- },
- "has username");
+ return NullAwareCorrespondence.transforming(
+ accountInfo -> accountInfo.username, "has username");
}
private void assertStaleGroupAndReindex(AccountGroup.UUID groupUuid) throws IOException {
diff --git a/javatests/com/google/gerrit/acceptance/rest/account/ImpersonationIT.java b/javatests/com/google/gerrit/acceptance/rest/account/ImpersonationIT.java
index a3c0295..840853c 100644
--- a/javatests/com/google/gerrit/acceptance/rest/account/ImpersonationIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/account/ImpersonationIT.java
@@ -41,7 +41,7 @@
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.ChangeMessage;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.Patch;
import com.google.gerrit.entities.PatchSetApproval;
import com.google.gerrit.entities.RobotComment;
@@ -225,7 +225,8 @@
assertThat(psa.realAccountId()).isEqualTo(admin.id());
ChangeData cd = r.getChange();
- Comment c = Iterables.getOnlyElement(commentsUtil.publishedByChange(cd.notes()));
+ HumanComment c =
+ Iterables.getOnlyElement(commentsUtil.publishedHumanCommentsByChange(cd.notes()));
assertThat(c.message).isEqualTo(ci.message);
assertThat(c.author.getId()).isEqualTo(user.id());
assertThat(c.getRealAuthor().getId()).isEqualTo(admin.id());
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java b/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
index 2901361..75950e2 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
@@ -1344,11 +1344,11 @@
assertThat(messages).hasSize(3);
String last = Iterables.getLast(messages);
if (getSubmitType() == SubmitType.CHERRY_PICK) {
- assertThat(last).startsWith("Change has been successfully cherry-picked as ");
+ assertThat(last).startsWith("Change has been successfully cherry-picked as");
} else if (getSubmitType() == SubmitType.REBASE_ALWAYS) {
assertThat(last).startsWith("Change has been successfully rebased and submitted as");
} else {
- assertThat(last).isEqualTo("Change has been successfully merged by Gerrit User 1000000");
+ assertThat(last).isEqualTo("Change has been successfully merged");
}
}
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/AttentionSetIT.java b/javatests/com/google/gerrit/acceptance/rest/change/AttentionSetIT.java
index caa8832..640109a 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/AttentionSetIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/AttentionSetIT.java
@@ -15,25 +15,44 @@
package com.google.gerrit.acceptance.rest.change;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.gerrit.testing.GerritJUnit.assertThrows;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
import com.google.gerrit.acceptance.AbstractDaemonTest;
+import com.google.gerrit.acceptance.GitUtil;
import com.google.gerrit.acceptance.NoHttpd;
import com.google.gerrit.acceptance.PushOneCommit;
+import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.UseClockStep;
+import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.entities.AttentionSetUpdate;
-import com.google.gerrit.extensions.api.changes.AddToAttentionSetInput;
-import com.google.gerrit.extensions.api.changes.RemoveFromAttentionSetInput;
+import com.google.gerrit.extensions.api.changes.AddReviewerInput;
+import com.google.gerrit.extensions.api.changes.AttentionSetInput;
+import com.google.gerrit.extensions.api.changes.HashtagsInput;
+import com.google.gerrit.extensions.api.changes.ReviewInput;
+import com.google.gerrit.extensions.client.ReviewerState;
+import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.server.util.time.TimeUtil;
+import com.google.inject.Inject;
import java.time.Duration;
import java.time.Instant;
+import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.LongSupplier;
+import java.util.stream.Collectors;
+import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
+import org.eclipse.jgit.junit.TestRepository;
import org.junit.Before;
import org.junit.Test;
@NoHttpd
@UseClockStep(clockStepUnit = TimeUnit.MINUTES)
public class AttentionSetIT extends AbstractDaemonTest {
+
+ @Inject private RequestScopeOperations requestScopeOperations;
+
/** Simulates a fake clock. Uses second granularity. */
private static class FakeClock implements LongSupplier {
Instant now = Instant.now();
@@ -69,7 +88,7 @@
public void addUser() throws Exception {
PushOneCommit.Result r = createChange();
int accountId =
- change(r).addToAttentionSet(new AddToAttentionSetInput(user.email(), "first"))._accountId;
+ change(r).addToAttentionSet(new AttentionSetInput(user.email(), "first"))._accountId;
assertThat(accountId).isEqualTo(user.id().get());
AttentionSetUpdate expectedAttentionSetUpdate =
AttentionSetUpdate.createFromRead(
@@ -78,7 +97,7 @@
// Second add is ignored.
accountId =
- change(r).addToAttentionSet(new AddToAttentionSetInput(user.email(), "second"))._accountId;
+ change(r).addToAttentionSet(new AttentionSetInput(user.email(), "second"))._accountId;
assertThat(accountId).isEqualTo(user.id().get());
assertThat(r.getChange().attentionSet()).containsExactly(expectedAttentionSetUpdate);
}
@@ -88,13 +107,13 @@
PushOneCommit.Result r = createChange();
Instant timestamp1 = fakeClock.now();
int accountId1 =
- change(r).addToAttentionSet(new AddToAttentionSetInput(user.email(), "user"))._accountId;
+ change(r).addToAttentionSet(new AttentionSetInput(user.email(), "user"))._accountId;
assertThat(accountId1).isEqualTo(user.id().get());
fakeClock.advance(Duration.ofSeconds(42));
Instant timestamp2 = fakeClock.now();
int accountId2 =
change(r)
- .addToAttentionSet(new AddToAttentionSetInput(admin.id().toString(), "admin"))
+ .addToAttentionSet(new AttentionSetInput(admin.id().toString(), "admin"))
._accountId;
assertThat(accountId2).isEqualTo(admin.id().get());
@@ -111,9 +130,9 @@
@Test
public void removeUser() throws Exception {
PushOneCommit.Result r = createChange();
- change(r).addToAttentionSet(new AddToAttentionSetInput(user.email(), "added"));
+ change(r).addToAttentionSet(new AttentionSetInput(user.email(), "added"));
fakeClock.advance(Duration.ofSeconds(42));
- change(r).attention(user.id().toString()).remove(new RemoveFromAttentionSetInput("removed"));
+ change(r).attention(user.id().toString()).remove(new AttentionSetInput("removed"));
AttentionSetUpdate expectedAttentionSetUpdate =
AttentionSetUpdate.createFromRead(
fakeClock.now(), user.id(), AttentionSetUpdate.Operation.REMOVE, "removed");
@@ -121,16 +140,748 @@
// Second removal is ignored.
fakeClock.advance(Duration.ofSeconds(42));
- change(r)
- .attention(user.id().toString())
- .remove(new RemoveFromAttentionSetInput("removed again"));
+ change(r).attention(user.id().toString()).remove(new AttentionSetInput("removed again"));
assertThat(r.getChange().attentionSet()).containsExactly(expectedAttentionSetUpdate);
}
@Test
+ public void removeUserWithInvalidUserInput() throws Exception {
+ PushOneCommit.Result r = createChange();
+ BadRequestException exception =
+ assertThrows(
+ BadRequestException.class,
+ () ->
+ change(r)
+ .attention(user.id().toString())
+ .remove(new AttentionSetInput("invalid user", "reason")));
+ assertThat(exception.getMessage())
+ .isEqualTo("The user specified in the input body couldn't be found.");
+
+ exception =
+ assertThrows(
+ BadRequestException.class,
+ () ->
+ change(r)
+ .attention(user.id().toString())
+ .remove(new AttentionSetInput(admin.email(), "reason")));
+ assertThat(exception.getMessage())
+ .isEqualTo(
+ "The field \"user\" must be empty, or must match the user specified in the URL.");
+ }
+
+ @Test
public void removeUnrelatedUser() throws Exception {
PushOneCommit.Result r = createChange();
- change(r).attention(user.id().toString()).remove(new RemoveFromAttentionSetInput("foo"));
+ change(r).attention(user.id().toString()).remove(new AttentionSetInput("foo"));
assertThat(r.getChange().attentionSet()).isEmpty();
}
+
+ @Test
+ public void abandonRemovesUsers() throws Exception {
+ PushOneCommit.Result r = createChange();
+ change(r).addToAttentionSet(new AttentionSetInput(user.email(), "user"));
+ change(r).addToAttentionSet(new AttentionSetInput(admin.email(), "admin"));
+
+ change(r).abandon();
+
+ AttentionSetUpdate userUpdate =
+ Iterables.getOnlyElement(getAttentionSetUpdatesForUser(r, user));
+ assertThat(userUpdate.account()).isEqualTo(user.id());
+ assertThat(userUpdate.operation()).isEqualTo(AttentionSetUpdate.Operation.REMOVE);
+ assertThat(userUpdate.reason()).isEqualTo("Change was abandoned");
+
+ AttentionSetUpdate adminUpdate =
+ Iterables.getOnlyElement(getAttentionSetUpdatesForUser(r, admin));
+ assertThat(adminUpdate.account()).isEqualTo(admin.id());
+ assertThat(adminUpdate.operation()).isEqualTo(AttentionSetUpdate.Operation.REMOVE);
+ assertThat(adminUpdate.reason()).isEqualTo("Change was abandoned");
+ }
+
+ @Test
+ public void workInProgressRemovesUsers() throws Exception {
+ PushOneCommit.Result r = createChange();
+ change(r).addToAttentionSet(new AttentionSetInput(user.email(), "reason"));
+
+ change(r).setWorkInProgress();
+
+ AttentionSetUpdate attentionSet = Iterables.getOnlyElement(r.getChange().attentionSet());
+ assertThat(attentionSet.account()).isEqualTo(user.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.REMOVE);
+ assertThat(attentionSet.reason()).isEqualTo("Change was marked work in progress");
+ }
+
+ @Test
+ public void submitRemovesUsersForAllSubmittedChanges() throws Exception {
+ PushOneCommit.Result r1 = createChange("refs/heads/master", "file1", "content");
+
+ change(r1)
+ .current()
+ .review(ReviewInput.approve().addUserToAttentionSet(user.email(), "reason"));
+ PushOneCommit.Result r2 = createChange("refs/heads/master", "file2", "content");
+ change(r2)
+ .current()
+ .review(ReviewInput.approve().addUserToAttentionSet(user.email(), "reason"));
+
+ change(r2).current().submit();
+
+ // Attention set updates that relate to the admin (the person who replied) are filtered out.
+ AttentionSetUpdate attentionSet =
+ Iterables.getOnlyElement(getAttentionSetUpdatesForUser(r1, user));
+
+ assertThat(attentionSet.account()).isEqualTo(user.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.REMOVE);
+ assertThat(attentionSet.reason()).isEqualTo("Change was submitted");
+
+ // Attention set updates that relate to the admin (the person who replied) are filtered out.
+ attentionSet = Iterables.getOnlyElement(getAttentionSetUpdatesForUser(r2, user));
+
+ assertThat(attentionSet.account()).isEqualTo(user.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.REMOVE);
+ assertThat(attentionSet.reason()).isEqualTo("Change was submitted");
+ }
+
+ @Test
+ public void reviewersAddedAndRemovedFromAttentionSet() throws Exception {
+ PushOneCommit.Result r = createChange();
+
+ change(r).addReviewer(user.id().toString());
+
+ AttentionSetUpdate attentionSet = Iterables.getOnlyElement(r.getChange().attentionSet());
+ assertThat(attentionSet.account()).isEqualTo(user.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.ADD);
+ assertThat(attentionSet.reason()).isEqualTo("Reviewer was added");
+
+ change(r).reviewer(user.email()).remove();
+
+ attentionSet = Iterables.getOnlyElement(r.getChange().attentionSet());
+ assertThat(attentionSet.account()).isEqualTo(user.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.REMOVE);
+ assertThat(attentionSet.reason()).isEqualTo("Reviewer was removed");
+ }
+
+ @Test
+ public void reviewersAddedAndRemovedByEmailFromAttentionSet() throws Exception {
+ PushOneCommit.Result r = createChange();
+
+ change(r).addReviewer(user.email());
+
+ AttentionSetUpdate attentionSet = Iterables.getOnlyElement(r.getChange().attentionSet());
+ assertThat(attentionSet.account()).isEqualTo(user.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.ADD);
+ assertThat(attentionSet.reason()).isEqualTo("Reviewer was added");
+
+ change(r).reviewer(user.email()).remove();
+
+ attentionSet = Iterables.getOnlyElement(r.getChange().attentionSet());
+ assertThat(attentionSet.account()).isEqualTo(user.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.REMOVE);
+ assertThat(attentionSet.reason()).isEqualTo("Reviewer was removed");
+ }
+
+ @Test
+ public void reviewersInWorkProgressNotAddedToAttentionSet() throws Exception {
+ PushOneCommit.Result r = createChange();
+ change(r).setWorkInProgress();
+ change(r).addReviewer(user.email());
+
+ assertThat(r.getChange().attentionSet()).isEmpty();
+ }
+
+ @Test
+ public void addingReviewerWhileMarkingWorkInprogressDoesntAddToAttentionSet() throws Exception {
+ PushOneCommit.Result r = createChange();
+ ReviewInput reviewInput = ReviewInput.create().setWorkInProgress(true);
+ AddReviewerInput addReviewerInput = new AddReviewerInput();
+ addReviewerInput.state = ReviewerState.REVIEWER;
+ addReviewerInput.reviewer = user.email();
+ reviewInput.reviewers = ImmutableList.of(addReviewerInput);
+
+ change(r).current().review(reviewInput);
+ assertThat(getAttentionSetUpdatesForUser(r, user)).isEmpty();
+ }
+
+ @Test
+ public void reviewersAddedAsReviewersAgainAreNotAddedToAttentionSet() throws Exception {
+ PushOneCommit.Result r = createChange();
+
+ change(r).addReviewer(user.id().toString());
+ change(r)
+ .attention(user.id().toString())
+ .remove(new AttentionSetInput("removed and not re-added when re-adding as reviewer"));
+
+ change(r).addReviewer(user.id().toString());
+
+ AttentionSetUpdate attentionSet = Iterables.getOnlyElement(r.getChange().attentionSet());
+ assertThat(attentionSet.account()).isEqualTo(user.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.REMOVE);
+ assertThat(attentionSet.reason())
+ .isEqualTo("removed and not re-added when re-adding as reviewer");
+ }
+
+ @Test
+ public void ccsAreIgnored() throws Exception {
+ PushOneCommit.Result r = createChange();
+ AddReviewerInput addReviewerInput = new AddReviewerInput();
+ addReviewerInput.state = ReviewerState.CC;
+ addReviewerInput.reviewer = user.email();
+
+ change(r).addReviewer(addReviewerInput);
+
+ assertThat(r.getChange().attentionSet()).isEmpty();
+ }
+
+ @Test
+ public void ccsConsideredSameAsRemovedForExistingReviewers() throws Exception {
+ PushOneCommit.Result r = createChange();
+ change(r).addReviewer(user.email());
+
+ AddReviewerInput addReviewerInput = new AddReviewerInput();
+ addReviewerInput.state = ReviewerState.CC;
+ addReviewerInput.reviewer = user.email();
+ change(r).addReviewer(addReviewerInput);
+
+ AttentionSetUpdate attentionSet = Iterables.getOnlyElement(r.getChange().attentionSet());
+ assertThat(attentionSet.account()).isEqualTo(user.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.REMOVE);
+ assertThat(attentionSet.reason()).isEqualTo("Reviewer was removed");
+ }
+
+ @Test
+ public void readyForReviewAddsAllReviewersToAttentionSet() throws Exception {
+ PushOneCommit.Result r = createChange();
+ change(r).setWorkInProgress();
+ change(r).addReviewer(user.email());
+
+ change(r).setReadyForReview();
+ AttentionSetUpdate attentionSet = Iterables.getOnlyElement(r.getChange().attentionSet());
+ assertThat(attentionSet.account()).isEqualTo(user.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.ADD);
+ assertThat(attentionSet.reason()).isEqualTo("Change was marked ready for review");
+ }
+
+ @Test
+ public void readyForReviewWhileRemovingReviewerRemovesThemToAttentionSet() throws Exception {
+ PushOneCommit.Result r = createChange();
+ change(r).setWorkInProgress();
+ change(r).addReviewer(user.email());
+
+ ReviewInput reviewInput = ReviewInput.create().setReady(true);
+ AddReviewerInput addReviewerInput = new AddReviewerInput();
+ addReviewerInput.state = ReviewerState.CC;
+ addReviewerInput.reviewer = user.email();
+ reviewInput.reviewers = ImmutableList.of(addReviewerInput);
+ change(r).addToAttentionSet(new AttentionSetInput(user.email(), "reason"));
+ change(r).current().review(reviewInput);
+
+ AttentionSetUpdate attentionSet =
+ Iterables.getOnlyElement(getAttentionSetUpdatesForUser(r, user));
+ assertThat(attentionSet.account()).isEqualTo(user.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.REMOVE);
+ assertThat(attentionSet.reason()).isEqualTo("Reviewer was removed");
+ }
+
+ @Test
+ public void readyForReviewWhileAddingReviewerAddsThemToAttentionSet() throws Exception {
+ PushOneCommit.Result r = createChange();
+ change(r).setWorkInProgress();
+
+ ReviewInput reviewInput = ReviewInput.create().setReady(true).reviewer(user.email());
+ change(r).current().review(reviewInput);
+
+ AttentionSetUpdate attentionSet =
+ Iterables.getOnlyElement(getAttentionSetUpdatesForUser(r, user));
+ assertThat(attentionSet.account()).isEqualTo(user.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.ADD);
+ assertThat(attentionSet.reason()).isEqualTo("Reviewer was added");
+ }
+
+ @Test
+ public void reviewersAreNotAddedForNoReasonBecauseOfAnUpdate() throws Exception {
+ PushOneCommit.Result r = createChange();
+ change(r).addToAttentionSet(new AttentionSetInput(user.email(), "user"));
+ change(r).attention(user.id().toString()).remove(new AttentionSetInput("removed"));
+
+ HashtagsInput hashtagsInput = new HashtagsInput();
+ hashtagsInput.add = ImmutableSet.of("tag");
+ change(r).setHashtags(hashtagsInput);
+
+ AttentionSetUpdate attentionSet = Iterables.getOnlyElement(r.getChange().attentionSet());
+ assertThat(attentionSet.account()).isEqualTo(user.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.REMOVE);
+ assertThat(attentionSet.reason()).isEqualTo("removed");
+ }
+
+ @Test
+ public void reviewAddsManuallyAddedUserToAttentionSet() throws Exception {
+ PushOneCommit.Result r = createChange();
+ ReviewInput reviewInput = ReviewInput.create().addUserToAttentionSet(user.email(), "reason");
+
+ change(r).current().review(reviewInput);
+
+ AttentionSetUpdate attentionSet =
+ Iterables.getOnlyElement(getAttentionSetUpdatesForUser(r, user));
+ assertThat(attentionSet.account()).isEqualTo(user.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.ADD);
+ assertThat(attentionSet.reason()).isEqualTo("reason");
+ }
+
+ @Test
+ public void reviewRemovesManuallyRemovedUserFromAttentionSet() throws Exception {
+ PushOneCommit.Result r = createChange();
+ change(r).addToAttentionSet(new AttentionSetInput(user.email(), "reason"));
+
+ ReviewInput reviewInput =
+ ReviewInput.create().removeUserFromAttentionSet(user.email(), "reason");
+ change(r).current().review(reviewInput);
+
+ AttentionSetUpdate attentionSet =
+ Iterables.getOnlyElement(getAttentionSetUpdatesForUser(r, user));
+ assertThat(attentionSet.account()).isEqualTo(user.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.REMOVE);
+ assertThat(attentionSet.reason()).isEqualTo("reason");
+ }
+
+ @Test
+ public void reviewWithManualAdditionToAttentionSetFailsWithoutReason() throws Exception {
+ PushOneCommit.Result r = createChange();
+ change(r).addToAttentionSet(new AttentionSetInput(user.email(), "reason"));
+
+ ReviewInput reviewInput = ReviewInput.create().addUserToAttentionSet(user.email(), "");
+
+ BadRequestException exception =
+ assertThrows(BadRequestException.class, () -> change(r).current().review(reviewInput));
+
+ assertThat(exception.getMessage()).isEqualTo("missing field: reason");
+ }
+
+ @Test
+ public void reviewWithManualAdditionToAttentionSetFailsWithoutUser() throws Exception {
+ PushOneCommit.Result r = createChange();
+ ReviewInput reviewInput = ReviewInput.create().addUserToAttentionSet("", "reason");
+
+ BadRequestException exception =
+ assertThrows(BadRequestException.class, () -> change(r).current().review(reviewInput));
+
+ assertThat(exception.getMessage()).isEqualTo("missing field: user");
+ }
+
+ @Test
+ public void reviewAddReviewerWhileRemovingFromAttentionSetJustRemovesUser() throws Exception {
+ PushOneCommit.Result r = createChange();
+ change(r).addToAttentionSet(new AttentionSetInput(user.email(), "addition"));
+
+ ReviewInput reviewInput =
+ ReviewInput.create()
+ .reviewer(user.email())
+ .removeUserFromAttentionSet(user.email(), "reason");
+
+ change(r).current().review(reviewInput);
+
+ // Attention set updates that relate to the admin (the person who replied) are filtered out.
+ AttentionSetUpdate attentionSet =
+ Iterables.getOnlyElement(getAttentionSetUpdatesForUser(r, user));
+ assertThat(attentionSet.account()).isEqualTo(user.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.REMOVE);
+ assertThat(attentionSet.reason()).isEqualTo("reason");
+ }
+
+ @Test
+ public void cantAddAndRemoveSameUser() throws Exception {
+ PushOneCommit.Result r = createChange();
+ ReviewInput reviewInput =
+ ReviewInput.create()
+ .removeUserFromAttentionSet(user.email(), "reason")
+ .addUserToAttentionSet(user.username(), "reason");
+
+ BadRequestException exception =
+ assertThrows(BadRequestException.class, () -> change(r).current().review(reviewInput));
+
+ assertThat(exception.getMessage())
+ .isEqualTo(
+ "user can not be added/removed twice, and can not be added and removed at the same time");
+ }
+
+ @Test
+ public void cantRemoveSameUserTwice() throws Exception {
+ PushOneCommit.Result r = createChange();
+ ReviewInput reviewInput =
+ ReviewInput.create()
+ .removeUserFromAttentionSet(user.email(), "reason1")
+ .removeUserFromAttentionSet(user.username(), "reason2");
+
+ BadRequestException exception =
+ assertThrows(BadRequestException.class, () -> change(r).current().review(reviewInput));
+
+ assertThat(exception.getMessage())
+ .isEqualTo(
+ "user can not be added/removed twice, and can not be added and removed at the same time");
+ }
+
+ @Test
+ public void cantAddSameUserTwice() throws Exception {
+ PushOneCommit.Result r = createChange();
+ ReviewInput reviewInput =
+ ReviewInput.create()
+ .addUserToAttentionSet(user.email(), "reason1")
+ .addUserToAttentionSet(user.username(), "reason2");
+
+ BadRequestException exception =
+ assertThrows(BadRequestException.class, () -> change(r).current().review(reviewInput));
+
+ assertThat(exception.getMessage())
+ .isEqualTo(
+ "user can not be added/removed twice, and can not be added and removed at the same time");
+ }
+
+ @Test
+ public void reviewRemoveFromAttentionSetWhileMarkingReadyForReviewJustRemovesUser()
+ throws Exception {
+ PushOneCommit.Result r = createChange();
+ change(r).setWorkInProgress();
+ change(r).addReviewer(user.email());
+ change(r).addToAttentionSet(new AttentionSetInput(user.email(), "reason"));
+
+ ReviewInput reviewInput =
+ ReviewInput.create().setReady(true).removeUserFromAttentionSet(user.email(), "reason");
+
+ change(r).current().review(reviewInput);
+
+ // Attention set updates that relate to the admin (the person who replied) are filtered out.
+ AttentionSetUpdate attentionSet =
+ Iterables.getOnlyElement(getAttentionSetUpdatesForUser(r, user));
+ assertThat(attentionSet.account()).isEqualTo(user.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.REMOVE);
+ assertThat(attentionSet.reason()).isEqualTo("reason");
+ }
+
+ @Test
+ public void reviewAddToAttentionSetWhileMarkingWorkInProgressJustAddsUser() throws Exception {
+ PushOneCommit.Result r = createChange();
+ change(r).addReviewer(user.email());
+
+ ReviewInput reviewInput =
+ ReviewInput.create().setWorkInProgress(true).addUserToAttentionSet(user.email(), "reason");
+
+ change(r).attention(user.email()).remove(new AttentionSetInput("removal"));
+ change(r).current().review(reviewInput);
+
+ // Attention set updates that relate to the admin (the person who replied) are filtered out.
+ AttentionSetUpdate attentionSet =
+ Iterables.getOnlyElement(getAttentionSetUpdatesForUser(r, user));
+ assertThat(attentionSet.account()).isEqualTo(user.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.ADD);
+ assertThat(attentionSet.reason()).isEqualTo("reason");
+ }
+
+ @Test
+ public void reviewRemovesUserFromAttentionSet() throws Exception {
+ PushOneCommit.Result r = createChange();
+ change(r).addToAttentionSet(new AttentionSetInput(admin.email(), "reason"));
+
+ ReviewInput reviewInput = new ReviewInput();
+ change(r).current().review(reviewInput);
+
+ AttentionSetUpdate attentionSet = Iterables.getOnlyElement(r.getChange().attentionSet());
+ assertThat(attentionSet.account()).isEqualTo(admin.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.REMOVE);
+ assertThat(attentionSet.reason()).isEqualTo("removed on reply");
+ }
+
+ @Test
+ public void reviewAddUserToAttentionSetWhileReplyingJustAddsUser() throws Exception {
+ PushOneCommit.Result r = createChange();
+
+ ReviewInput reviewInput = ReviewInput.create().addUserToAttentionSet(admin.email(), "reason");
+ change(r).current().review(reviewInput);
+
+ AttentionSetUpdate attentionSet = Iterables.getOnlyElement(r.getChange().attentionSet());
+ assertThat(attentionSet.account()).isEqualTo(admin.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.ADD);
+ assertThat(attentionSet.reason()).isEqualTo("reason");
+ }
+
+ @Test
+ public void reviewWhileAddingThemselvesAsReviewerStillRemovesThem() throws Exception {
+ PushOneCommit.Result r = createChange();
+
+ requestScopeOperations.setApiUser(user.id());
+
+ change(r).addToAttentionSet(new AttentionSetInput(user.email(), "reason"));
+ ReviewInput reviewInput = ReviewInput.create().reviewer(user.email());
+ change(r).current().review(reviewInput);
+
+ AttentionSetUpdate attentionSet =
+ Iterables.getOnlyElement(getAttentionSetUpdatesForUser(r, user));
+ assertThat(attentionSet.account()).isEqualTo(user.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.REMOVE);
+ assertThat(attentionSet.reason()).isEqualTo("removed on reply");
+ }
+
+ @Test
+ public void reviewWhileAddingThemselvesAsReviewerDoesNotAddThem() throws Exception {
+ PushOneCommit.Result r = createChange();
+
+ requestScopeOperations.setApiUser(user.id());
+
+ ReviewInput reviewInput = ReviewInput.create().reviewer(user.email());
+ change(r).current().review(reviewInput);
+
+ assertThat(getAttentionSetUpdatesForUser(r, user)).isEmpty();
+ }
+
+ @Test
+ public void repliesAddsOwner() throws Exception {
+ PushOneCommit.Result r = createChange();
+
+ requestScopeOperations.setApiUser(user.id());
+
+ ReviewInput reviewInput = new ReviewInput();
+ change(r).current().review(reviewInput);
+
+ AttentionSetUpdate attentionSet =
+ Iterables.getOnlyElement(getAttentionSetUpdatesForUser(r, admin));
+ assertThat(attentionSet.account()).isEqualTo(admin.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.ADD);
+ assertThat(attentionSet.reason()).isEqualTo("reviewer or cc replied");
+ }
+
+ @Test
+ public void repliesDoNotAddOwnerWhenChangeIsWorkInProgress() throws Exception {
+ PushOneCommit.Result r = createChange();
+ change(r).setWorkInProgress();
+ requestScopeOperations.setApiUser(user.id());
+
+ ReviewInput reviewInput = new ReviewInput();
+ change(r).current().review(reviewInput);
+
+ assertThat(getAttentionSetUpdatesForUser(r, admin)).isEmpty();
+ }
+
+ @Test
+ public void repliesDoNotAddOwnerWhenChangeIsBecomingWorkInProgress() throws Exception {
+ PushOneCommit.Result r = createChange();
+ requestScopeOperations.setApiUser(accountCreator.admin2().id());
+
+ ReviewInput reviewInput = ReviewInput.create().setWorkInProgress(true);
+ change(r).current().review(reviewInput);
+
+ assertThat(getAttentionSetUpdatesForUser(r, admin)).isEmpty();
+ }
+
+ @Test
+ public void repliesAddOwnerWhenChangeIsBecomingReadyForReview() throws Exception {
+ PushOneCommit.Result r = createChange();
+ change(r).setWorkInProgress();
+ requestScopeOperations.setApiUser(accountCreator.admin2().id());
+
+ ReviewInput reviewInput = ReviewInput.create().setReady(true);
+ change(r).current().review(reviewInput);
+
+ AttentionSetUpdate attentionSet =
+ Iterables.getOnlyElement(getAttentionSetUpdatesForUser(r, admin));
+ assertThat(attentionSet.account()).isEqualTo(admin.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.ADD);
+ assertThat(attentionSet.reason()).isEqualTo("reviewer or cc replied");
+ }
+
+ @Test
+ public void repliesAddsOwnerAndUploader() throws Exception {
+ // Create change with owner: admin
+ PushOneCommit.Result r = createChange();
+
+ // Clone, fetch, and checkout the change with user, and then create a new patchset.
+ TestRepository<InMemoryRepository> repo = cloneProject(project, user);
+ GitUtil.fetch(repo, "refs/*:refs/*");
+ repo.reset(r.getCommit());
+ r =
+ amendChange(
+ r.getChangeId(),
+ "refs/for/master",
+ user,
+ repo,
+ "new subject",
+ "new file",
+ "new content");
+
+ TestAccount user2 = accountCreator.user2();
+ requestScopeOperations.setApiUser(user2.id());
+
+ change(r).attention(user.email()).remove(new AttentionSetInput("reason"));
+ ReviewInput reviewInput = new ReviewInput();
+ change(r).current().review(reviewInput);
+
+ reviewInput = new ReviewInput();
+ change(r).current().review(reviewInput);
+
+ // Uploader added
+ AttentionSetUpdate attentionSet =
+ Iterables.getOnlyElement(getAttentionSetUpdatesForUser(r, user));
+ assertThat(attentionSet.account()).isEqualTo(user.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.ADD);
+ assertThat(attentionSet.reason()).isEqualTo("reviewer or cc replied");
+
+ // Owner added
+ attentionSet = Iterables.getOnlyElement(getAttentionSetUpdatesForUser(r, admin));
+ assertThat(attentionSet.account()).isEqualTo(admin.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.ADD);
+ assertThat(attentionSet.reason()).isEqualTo("reviewer or cc replied");
+ }
+
+ @Test
+ public void ownerRepliesAddsReviewersOnly() throws Exception {
+ PushOneCommit.Result r = createChange();
+ // add reviewer and cc
+ change(r).addReviewer(user.email());
+ change(r)
+ .attention(user.email())
+ .remove(new AttentionSetInput("Reviewer is not in attention-set"));
+
+ TestAccount cc = accountCreator.admin2();
+ AddReviewerInput input = new AddReviewerInput();
+ input.state = ReviewerState.CC;
+ input.reviewer = cc.email();
+ change(r).addReviewer(input);
+
+ ReviewInput reviewInput = new ReviewInput();
+ change(r).current().review(reviewInput);
+
+ // cc not added
+ assertThat(getAttentionSetUpdatesForUser(r, cc)).isEmpty();
+
+ // reviewer added
+ AttentionSetUpdate attentionSet =
+ Iterables.getOnlyElement(getAttentionSetUpdatesForUser(r, user));
+ assertThat(attentionSet.account()).isEqualTo(user.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.ADD);
+ assertThat(attentionSet.reason()).isEqualTo("owner or uploader replied");
+ }
+
+ @Test
+ public void ownerRepliesWhileRemovingReviewerStillRemovesFromAttentionSet() throws Exception {
+ PushOneCommit.Result r = createChange();
+ change(r).addReviewer(user.email());
+
+ ReviewInput reviewInput = ReviewInput.create().reviewer(user.email(), ReviewerState.CC, false);
+ change(r).current().review(reviewInput);
+
+ // cc removed
+ AttentionSetUpdate attentionSet =
+ Iterables.getOnlyElement(getAttentionSetUpdatesForUser(r, user));
+ assertThat(attentionSet.account()).isEqualTo(user.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.REMOVE);
+ assertThat(attentionSet.reason()).isEqualTo("Reviewer was removed");
+ }
+
+ @Test
+ public void uploaderRepliesAddsOwnerAndReviewersOnly() throws Exception {
+ PushOneCommit.Result r = createChange();
+
+ // Clone, fetch, and checkout the change with user, and then create a new patchset.
+ TestRepository<InMemoryRepository> repo = cloneProject(project, user);
+ GitUtil.fetch(repo, "refs/*:refs/*");
+ repo.reset(r.getCommit());
+ r =
+ amendChange(
+ r.getChangeId(),
+ "refs/for/master",
+ user,
+ repo,
+ "new subject",
+ "new file",
+ "new content");
+
+ // Add reviewer and cc
+ TestAccount reviewer = accountCreator.user2();
+ change(r).addReviewer(reviewer.email());
+ TestAccount cc = accountCreator.admin2();
+ AddReviewerInput input = new AddReviewerInput();
+ input.state = ReviewerState.CC;
+ input.reviewer = cc.email();
+ change(r).addReviewer(input);
+
+ requestScopeOperations.setApiUser(user.id());
+ change(r).attention(reviewer.email()).remove(new AttentionSetInput("reason"));
+
+ ReviewInput reviewInput = new ReviewInput();
+ change(r).current().review(reviewInput);
+
+ // cc not added
+ assertThat(getAttentionSetUpdatesForUser(r, cc)).isEmpty();
+
+ // reviewer added
+ AttentionSetUpdate attentionSet =
+ Iterables.getOnlyElement(getAttentionSetUpdatesForUser(r, reviewer));
+ assertThat(attentionSet.account()).isEqualTo(reviewer.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.ADD);
+ assertThat(attentionSet.reason()).isEqualTo("owner or uploader replied");
+
+ // Owner added
+ attentionSet = Iterables.getOnlyElement(getAttentionSetUpdatesForUser(r, admin));
+ assertThat(attentionSet.account()).isEqualTo(admin.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.ADD);
+ assertThat(attentionSet.reason()).isEqualTo("uploader replied");
+ }
+
+ @Test
+ public void repliesWhileAddingAsReviewerStillRemovesUser() throws Exception {
+ PushOneCommit.Result r = createChange();
+ change(r).addToAttentionSet(new AttentionSetInput(user.email(), "remove"));
+
+ requestScopeOperations.setApiUser(user.id());
+ ReviewInput reviewInput = ReviewInput.create().recommend();
+ change(r).current().review(reviewInput);
+
+ // reviewer removed
+ AttentionSetUpdate attentionSet =
+ Iterables.getOnlyElement(getAttentionSetUpdatesForUser(r, user));
+ assertThat(attentionSet.account()).isEqualTo(user.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.REMOVE);
+ assertThat(attentionSet.reason()).isEqualTo("removed on reply");
+ }
+
+ @Test
+ public void attentionSetUnchangedWithIgnoreDefaultAttentionSetRules() throws Exception {
+ PushOneCommit.Result r = createChange();
+ change(r).addToAttentionSet(new AttentionSetInput(admin.email(), "reason"));
+ change(r)
+ .current()
+ .review(
+ ReviewInput.create()
+ .reviewer(admin.email(), ReviewerState.CC, false)
+ .blockDefaultAttentionSetRules());
+
+ // admin is still in the attention set, although replies remove from attention set, and removing
+ // from reviewer also should remove from attention set.
+ AttentionSetUpdate attentionSet = Iterables.getOnlyElement(r.getChange().attentionSet());
+ assertThat(attentionSet.account()).isEqualTo(admin.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.ADD);
+ assertThat(attentionSet.reason()).isEqualTo("reason");
+ }
+
+ @Test
+ public void attentionSetStillChangesWithIgnoreDefaultAttentionSetRulesWithInputList()
+ throws Exception {
+ PushOneCommit.Result r = createChange();
+ change(r).addToAttentionSet(new AttentionSetInput(admin.email(), "reason"));
+ change(r)
+ .current()
+ .review(
+ ReviewInput.create()
+ .removeUserFromAttentionSet(admin.email(), "removed")
+ .blockDefaultAttentionSetRules());
+
+ // Admin is still removed although we block default attention set rules, since we remove
+ // the admin manually.
+ AttentionSetUpdate attentionSet = Iterables.getOnlyElement(r.getChange().attentionSet());
+ assertThat(attentionSet.account()).isEqualTo(admin.id());
+ assertThat(attentionSet.operation()).isEqualTo(AttentionSetUpdate.Operation.REMOVE);
+ assertThat(attentionSet.reason()).isEqualTo("removed");
+ }
+
+ private List<AttentionSetUpdate> getAttentionSetUpdatesForUser(
+ PushOneCommit.Result r, TestAccount account) {
+ return r.getChange().attentionSet().stream()
+ .filter(a -> a.account().get() == account.id().get())
+ .collect(Collectors.toList());
+ }
}
diff --git a/javatests/com/google/gerrit/acceptance/server/change/CommentsIT.java b/javatests/com/google/gerrit/acceptance/server/change/CommentsIT.java
index e48c9d5..15f1a6a 100644
--- a/javatests/com/google/gerrit/acceptance/server/change/CommentsIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/change/CommentsIT.java
@@ -34,6 +34,7 @@
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.entities.Change;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.Patch;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.api.changes.DeleteCommentInput;
@@ -1425,16 +1426,16 @@
RevCommit commitBefore = beforeDelete.get(i);
RevCommit commitAfter = afterDelete.get(i);
- Map<String, com.google.gerrit.entities.Comment> commentMapBefore =
+ Map<String, HumanComment> commentMapBefore =
DeleteCommentRewriter.getPublishedComments(
noteUtil, reader, NoteMap.read(reader, commitBefore));
- Map<String, com.google.gerrit.entities.Comment> commentMapAfter =
+ Map<String, HumanComment> commentMapAfter =
DeleteCommentRewriter.getPublishedComments(
noteUtil, reader, NoteMap.read(reader, commitAfter));
if (commentMapBefore.containsKey(targetCommentUuid)) {
assertThat(commentMapAfter).containsKey(targetCommentUuid);
- com.google.gerrit.entities.Comment comment = commentMapAfter.get(targetCommentUuid);
+ HumanComment comment = commentMapAfter.get(targetCommentUuid);
assertThat(comment.message).isEqualTo(expectedMessage);
comment.message = commentMapBefore.get(targetCommentUuid).message;
commentMapAfter.put(targetCommentUuid, comment);
diff --git a/javatests/com/google/gerrit/acceptance/server/change/GetRelatedIT.java b/javatests/com/google/gerrit/acceptance/server/change/GetRelatedIT.java
index b544f6e..74dfa04 100644
--- a/javatests/com/google/gerrit/acceptance/server/change/GetRelatedIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/change/GetRelatedIT.java
@@ -58,7 +58,6 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-import java.util.Objects;
import java.util.Optional;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.Config;
@@ -636,10 +635,8 @@
private static Correspondence<RelatedChangeAndCommitInfo, String>
getRelatedChangeToStatusCorrespondence() {
- return Correspondence.from(
- (relatedChangeAndCommitInfo, status) ->
- Objects.equals(relatedChangeAndCommitInfo.status, status),
- "has status");
+ return Correspondence.transforming(
+ relatedChangeAndCommitInfo -> relatedChangeAndCommitInfo.status, "has status");
}
private RevCommit parseBody(RevCommit c) throws Exception {
diff --git a/javatests/com/google/gerrit/acceptance/testsuite/group/GroupOperationsImplTest.java b/javatests/com/google/gerrit/acceptance/testsuite/group/GroupOperationsImplTest.java
index 96864d9..a003f9d 100644
--- a/javatests/com/google/gerrit/acceptance/testsuite/group/GroupOperationsImplTest.java
+++ b/javatests/com/google/gerrit/acceptance/testsuite/group/GroupOperationsImplTest.java
@@ -29,9 +29,9 @@
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.extensions.restapi.RestApiException;
+import com.google.gerrit.truth.NullAwareCorrespondence;
import com.google.inject.Inject;
import java.sql.Timestamp;
-import java.util.Objects;
import java.util.Optional;
import org.junit.Test;
@@ -616,28 +616,11 @@
}
private static Correspondence<AccountInfo, Account.Id> getAccountToIdCorrespondence() {
- return Correspondence.from(
- (actualAccount, expectedId) -> {
- Account.Id accountId =
- Optional.ofNullable(actualAccount)
- .map(account -> account._accountId)
- .map(Account::id)
- .orElse(null);
- return Objects.equals(accountId, expectedId);
- },
- "has ID");
+ return NullAwareCorrespondence.transforming(
+ account -> Account.id(account._accountId), "has ID");
}
private static Correspondence<GroupInfo, AccountGroup.UUID> getGroupToUuidCorrespondence() {
- return Correspondence.from(
- (actualGroup, expectedUuid) -> {
- AccountGroup.UUID groupUuid =
- Optional.ofNullable(actualGroup)
- .map(group -> group.id)
- .map(AccountGroup::uuid)
- .orElse(null);
- return Objects.equals(groupUuid, expectedUuid);
- },
- "has UUID");
+ return NullAwareCorrespondence.transforming(group -> AccountGroup.uuid(group.id), "has UUID");
}
}
diff --git a/javatests/com/google/gerrit/mail/AbstractParserTest.java b/javatests/com/google/gerrit/mail/AbstractParserTest.java
index f3c8671..2306449 100644
--- a/javatests/com/google/gerrit/mail/AbstractParserTest.java
+++ b/javatests/com/google/gerrit/mail/AbstractParserTest.java
@@ -18,6 +18,7 @@
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.ArrayList;
@@ -37,7 +38,7 @@
}
protected static void assertInlineComment(
- String message, MailComment comment, Comment inReplyTo) {
+ String message, MailComment comment, HumanComment inReplyTo) {
assertThat(comment.fileName).isNull();
assertThat(comment.message).isEqualTo(message);
assertThat(comment.inReplyTo.key).isEqualTo(inReplyTo.key);
@@ -51,9 +52,9 @@
assertThat(comment.type).isEqualTo(MailComment.CommentType.FILE_COMMENT);
}
- protected static Comment newComment(String uuid, String file, String message, int line) {
- Comment c =
- new Comment(
+ protected static HumanComment newComment(String uuid, String file, String message, int line) {
+ HumanComment c =
+ new HumanComment(
new Comment.Key(uuid, file, 1),
Account.id(0),
new Timestamp(0L),
@@ -65,9 +66,10 @@
return c;
}
- protected static Comment newRangeComment(String uuid, String file, String message, int line) {
- Comment c =
- new Comment(
+ protected static HumanComment newRangeComment(
+ String uuid, String file, String message, int line) {
+ HumanComment c =
+ new HumanComment(
new Comment.Key(uuid, file, 1),
Account.id(0),
new Timestamp(0L),
@@ -91,8 +93,8 @@
}
/** Returns a List of default comments for testing. */
- protected static List<Comment> defaultComments() {
- List<Comment> comments = new ArrayList<>();
+ protected static List<HumanComment> defaultComments() {
+ List<HumanComment> comments = new ArrayList<>();
comments.add(newComment("c1", "gerrit-server/test.txt", "comment", 0));
comments.add(newComment("c2", "gerrit-server/test.txt", "comment", 2));
comments.add(newComment("c3", "gerrit-server/test.txt", "comment", 3));
diff --git a/javatests/com/google/gerrit/mail/HtmlParserTest.java b/javatests/com/google/gerrit/mail/HtmlParserTest.java
index 345cb05..d661278 100644
--- a/javatests/com/google/gerrit/mail/HtmlParserTest.java
+++ b/javatests/com/google/gerrit/mail/HtmlParserTest.java
@@ -16,7 +16,7 @@
import static com.google.common.truth.Truth.assertThat;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import java.util.List;
import org.junit.Ignore;
import org.junit.Test;
@@ -31,7 +31,7 @@
MailMessage.Builder b = newMailMessageBuilder();
b.htmlContent(newHtmlBody("Looks good to me", null, null, null, null, null, null));
- List<Comment> comments = defaultComments();
+ List<HumanComment> comments = defaultComments();
List<MailComment> parsedComments = HtmlParser.parse(b.build(), comments, "");
assertThat(parsedComments).hasSize(1);
@@ -52,7 +52,7 @@
null,
null));
- List<Comment> comments = defaultComments();
+ List<HumanComment> comments = defaultComments();
List<MailComment> parsedComments = HtmlParser.parse(b.build(), comments, "");
assertThat(parsedComments).hasSize(1);
@@ -73,7 +73,7 @@
null,
null));
- List<Comment> comments = defaultComments();
+ List<HumanComment> comments = defaultComments();
List<MailComment> parsedComments = HtmlParser.parse(b.build(), comments, CHANGE_URL);
assertThat(parsedComments).hasSize(3);
@@ -96,7 +96,7 @@
null,
null));
- List<Comment> comments = defaultComments();
+ List<HumanComment> comments = defaultComments();
List<MailComment> parsedComments = HtmlParser.parse(b.build(), comments, CHANGE_URL);
assertThat(parsedComments).hasSize(3);
@@ -121,7 +121,7 @@
null,
null));
- List<Comment> comments = defaultComments();
+ List<HumanComment> comments = defaultComments();
List<MailComment> parsedComments = HtmlParser.parse(b.build(), comments, CHANGE_URL);
assertThat(parsedComments).hasSize(3);
@@ -135,7 +135,7 @@
MailMessage.Builder b = newMailMessageBuilder();
b.htmlContent(newHtmlBody(null, null, null, null, null, null, null));
- List<Comment> comments = defaultComments();
+ List<HumanComment> comments = defaultComments();
List<MailComment> parsedComments = HtmlParser.parse(b.build(), comments, CHANGE_URL);
assertThat(parsedComments).isEmpty();
@@ -148,7 +148,7 @@
newHtmlBody(
null, null, null, "Also have a comment here.", "This is a nice file", null, null));
- List<Comment> comments = defaultComments();
+ List<HumanComment> comments = defaultComments();
List<MailComment> parsedComments = HtmlParser.parse(b.build(), comments, CHANGE_URL);
assertThat(parsedComments).hasSize(2);
@@ -164,7 +164,7 @@
MailMessage.Builder b = newMailMessageBuilder();
b.htmlContent(newHtmlBody(htmlMessage, null, null, htmlMessage, htmlMessage, null, null));
- List<Comment> comments = defaultComments();
+ List<HumanComment> comments = defaultComments();
List<MailComment> parsedComments = HtmlParser.parse(b.build(), comments, CHANGE_URL);
assertThat(parsedComments).hasSize(3);
diff --git a/javatests/com/google/gerrit/mail/TextParserTest.java b/javatests/com/google/gerrit/mail/TextParserTest.java
index 00d5b41..f1d61792 100644
--- a/javatests/com/google/gerrit/mail/TextParserTest.java
+++ b/javatests/com/google/gerrit/mail/TextParserTest.java
@@ -16,7 +16,7 @@
import static com.google.common.truth.Truth.assertThat;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import java.util.List;
import org.junit.Test;
@@ -39,7 +39,7 @@
MailMessage.Builder b = newMailMessageBuilder();
b.textContent("Looks good to me\n" + quotedFooter);
- List<Comment> comments = defaultComments();
+ List<HumanComment> comments = defaultComments();
List<MailComment> parsedComments = TextParser.parse(b.build(), comments, CHANGE_URL);
assertThat(parsedComments).hasSize(1);
@@ -60,7 +60,7 @@
null)
+ quotedFooter);
- List<Comment> comments = defaultComments();
+ List<HumanComment> comments = defaultComments();
List<MailComment> parsedComments = TextParser.parse(b.build(), comments, CHANGE_URL);
assertThat(parsedComments).hasSize(3);
@@ -83,7 +83,7 @@
null)
+ quotedFooter);
- List<Comment> comments = defaultComments();
+ List<HumanComment> comments = defaultComments();
List<MailComment> parsedComments = TextParser.parse(b.build(), comments, CHANGE_URL);
assertThat(parsedComments).hasSize(3);
@@ -97,7 +97,7 @@
MailMessage.Builder b = newMailMessageBuilder();
b.textContent(newPlaintextBody(null, null, null, null, null, null, null) + quotedFooter);
- List<Comment> comments = defaultComments();
+ List<HumanComment> comments = defaultComments();
List<MailComment> parsedComments = TextParser.parse(b.build(), comments, CHANGE_URL);
assertThat(parsedComments).isEmpty();
@@ -111,7 +111,7 @@
null, null, null, "Also have a comment here.", "This is a nice file", null, null)
+ quotedFooter);
- List<Comment> comments = defaultComments();
+ List<HumanComment> comments = defaultComments();
List<MailComment> parsedComments = TextParser.parse(b.build(), comments, CHANGE_URL);
assertThat(parsedComments).hasSize(2);
@@ -134,7 +134,7 @@
+ quotedFooter)
.replace("> ", ">> "));
- List<Comment> comments = defaultComments();
+ List<HumanComment> comments = defaultComments();
List<MailComment> parsedComments = TextParser.parse(b.build(), comments, CHANGE_URL);
assertThat(parsedComments).hasSize(3);
@@ -157,7 +157,7 @@
"Comment in reply to file comment")
+ quotedFooter);
- List<Comment> comments = defaultComments();
+ List<HumanComment> comments = defaultComments();
List<MailComment> parsedComments = TextParser.parse(b.build(), comments, CHANGE_URL);
assertThat(parsedComments).hasSize(2);
diff --git a/javatests/com/google/gerrit/server/BUILD b/javatests/com/google/gerrit/server/BUILD
index 60d9d69..248c7d1 100644
--- a/javatests/com/google/gerrit/server/BUILD
+++ b/javatests/com/google/gerrit/server/BUILD
@@ -63,6 +63,7 @@
"//java/com/google/gerrit/server/schema",
"//java/com/google/gerrit/server/schema/testing",
"//java/com/google/gerrit/server/util/time",
+ "//java/com/google/gerrit/sshd",
"//java/com/google/gerrit/testing:assertable-executor",
"//java/com/google/gerrit/testing:gerrit-test-util",
"//java/com/google/gerrit/truth",
diff --git a/javatests/com/google/gerrit/server/cache/h2/H2CacheTest.java b/javatests/com/google/gerrit/server/cache/h2/H2CacheTest.java
index ddcfe0c..3ade4d0 100644
--- a/javatests/com/google/gerrit/server/cache/h2/H2CacheTest.java
+++ b/javatests/com/google/gerrit/server/cache/h2/H2CacheTest.java
@@ -188,6 +188,7 @@
assertThat(h2Cache.getIfPresent("foo")).isEqualTo("reload:foo");
}
+ @SuppressWarnings("unchecked")
private static void resetLoaderAndAnswerLoadAndRefreshCalls(CacheLoader<String, String> loader)
throws Exception {
reset(loader);
diff --git a/javatests/com/google/gerrit/server/mail/send/CommentFormatterTest.java b/javatests/com/google/gerrit/server/mail/send/HumanCommentFormatterTest.java
similarity index 99%
rename from javatests/com/google/gerrit/server/mail/send/CommentFormatterTest.java
rename to javatests/com/google/gerrit/server/mail/send/HumanCommentFormatterTest.java
index f4fbc78..46ea8b2 100644
--- a/javatests/com/google/gerrit/server/mail/send/CommentFormatterTest.java
+++ b/javatests/com/google/gerrit/server/mail/send/HumanCommentFormatterTest.java
@@ -23,7 +23,7 @@
import java.util.List;
import org.junit.Test;
-public class CommentFormatterTest {
+public class HumanCommentFormatterTest {
private void assertBlock(
List<CommentFormatter.Block> list, int index, CommentFormatter.BlockType type, String text) {
CommentFormatter.Block block = list.get(index);
diff --git a/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java b/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java
index 7192c55..bf9b187 100644
--- a/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java
+++ b/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java
@@ -23,6 +23,7 @@
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Comment;
import com.google.gerrit.entities.CommentRange;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.config.FactoryModule;
@@ -244,7 +245,7 @@
return label;
}
- protected Comment newComment(
+ protected HumanComment newComment(
PatchSet.Id psId,
String filename,
String UUID,
@@ -257,8 +258,8 @@
short side,
ObjectId commitId,
boolean unresolved) {
- Comment c =
- new Comment(
+ HumanComment c =
+ new HumanComment(
new Comment.Key(UUID, filename, psId.get()),
commenter.getAccountId(),
t,
diff --git a/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java b/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java
index efbaed6..a5e7dce 100644
--- a/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java
+++ b/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java
@@ -32,6 +32,7 @@
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.ChangeMessage;
import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.LabelId;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.PatchSetApproval;
@@ -714,8 +715,8 @@
@Test
public void serializePublishedComments() throws Exception {
- Comment c1 =
- new Comment(
+ HumanComment c1 =
+ new HumanComment(
new Comment.Key("uuid1", "file1", 1),
Account.id(1001),
new Timestamp(1212L),
@@ -726,8 +727,8 @@
c1.setCommitId(ObjectId.fromString("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
String c1Json = Serializer.GSON.toJson(c1);
- Comment c2 =
- new Comment(
+ HumanComment c2 =
+ new HumanComment(
new Comment.Key("uuid2", "file2", 2),
Account.id(1002),
new Timestamp(3434L),
@@ -798,7 +799,7 @@
.put("changeMessages", new TypeLiteral<ImmutableList<ChangeMessage>>() {}.getType())
.put(
"publishedComments",
- new TypeLiteral<ImmutableListMultimap<ObjectId, Comment>>() {}.getType())
+ new TypeLiteral<ImmutableListMultimap<ObjectId, HumanComment>>() {}.getType())
.put("updateCount", int.class)
.build());
}
@@ -970,7 +971,7 @@
"startChar", int.class,
"endLine", int.class,
"endChar", int.class));
- assertThatSerializedClass(Comment.class)
+ assertThatSerializedClass(HumanComment.class)
.hasFields(
ImmutableMap.<String, Type>builder()
.put("key", Comment.Key.class)
diff --git a/javatests/com/google/gerrit/server/notedb/ChangeNotesTest.java b/javatests/com/google/gerrit/server/notedb/ChangeNotesTest.java
index 964187c..df5903f 100644
--- a/javatests/com/google/gerrit/server/notedb/ChangeNotesTest.java
+++ b/javatests/com/google/gerrit/server/notedb/ChangeNotesTest.java
@@ -43,8 +43,8 @@
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.ChangeMessage;
-import com.google.gerrit.entities.Comment;
import com.google.gerrit.entities.CommentRange;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.PatchSetApproval;
import com.google.gerrit.entities.SubmissionId;
@@ -123,7 +123,7 @@
RevCommit commit = tr.commit().message("PS2").create();
ChangeUpdate update = newUpdate(c, changeOwner);
update.putComment(
- Comment.Status.PUBLISHED,
+ HumanComment.Status.PUBLISHED,
newComment(
c.currentPatchSetId(),
"a.txt",
@@ -142,7 +142,7 @@
ChangeNotes notes = newNotes(c);
- ImmutableListMultimap<ObjectId, Comment> comments = notes.getComments();
+ ImmutableListMultimap<ObjectId, HumanComment> comments = notes.getHumanComments();
assertThat(comments).hasSize(1);
assertThat(comments.entries().asList().get(0).getValue().tag).isEqualTo(tag);
}
@@ -185,7 +185,7 @@
RevCommit commit = tr.commit().message("PS2").create();
update = newUpdate(c, changeOwner);
update.putComment(
- Comment.Status.PUBLISHED,
+ HumanComment.Status.PUBLISHED,
newComment(
c.currentPatchSetId(),
"a.txt",
@@ -216,7 +216,7 @@
assertThat(approval.tag()).hasValue(integrationTag);
assertThat(approval.value()).isEqualTo(-1);
- ImmutableListMultimap<ObjectId, Comment> comments = notes.getComments();
+ ImmutableListMultimap<ObjectId, HumanComment> comments = notes.getHumanComments();
assertThat(comments).hasSize(1);
assertThat(comments.entries().asList().get(0).getValue().tag).isEqualTo(coverageTag);
@@ -704,7 +704,7 @@
ChangeUpdate update = newUpdate(c, changeOwner);
AttentionSetUpdate attentionSetUpdate =
AttentionSetUpdate.createForWrite(changeOwner.getAccountId(), Operation.ADD, "test");
- update.setAttentionSetUpdates(ImmutableSet.of(attentionSetUpdate));
+ update.addToPlannedAttentionSetUpdates(ImmutableSet.of(attentionSetUpdate));
update.commit();
ChangeNotes notes = newNotes(c);
@@ -717,12 +717,12 @@
ChangeUpdate update = newUpdate(c, changeOwner);
AttentionSetUpdate attentionSetUpdate =
AttentionSetUpdate.createForWrite(changeOwner.getAccountId(), Operation.ADD, "test");
- update.setAttentionSetUpdates(ImmutableSet.of(attentionSetUpdate));
+ update.addToPlannedAttentionSetUpdates(ImmutableSet.of(attentionSetUpdate));
update.commit();
update = newUpdate(c, changeOwner);
attentionSetUpdate =
AttentionSetUpdate.createForWrite(changeOwner.getAccountId(), Operation.REMOVE, "test");
- update.setAttentionSetUpdates(ImmutableSet.of(attentionSetUpdate));
+ update.addToPlannedAttentionSetUpdates(ImmutableSet.of(attentionSetUpdate));
update.commit();
ChangeNotes notes = newNotes(c);
@@ -739,23 +739,24 @@
IllegalArgumentException thrown =
assertThrows(
IllegalArgumentException.class,
- () -> update.setAttentionSetUpdates(ImmutableSet.of(attentionSetUpdate)));
+ () -> update.addToPlannedAttentionSetUpdates(ImmutableSet.of(attentionSetUpdate)));
assertThat(thrown).hasMessageThat().contains("must not specify timestamp for write");
}
@Test
- public void addAttentionStatus_rejectMultiplePerUser() throws Exception {
+ public void addAttentionStatus_rejectIfSameUserTwice() throws Exception {
Change c = newChange();
ChangeUpdate update = newUpdate(c, changeOwner);
AttentionSetUpdate attentionSetUpdate0 =
AttentionSetUpdate.createForWrite(changeOwner.getAccountId(), Operation.ADD, "test 0");
AttentionSetUpdate attentionSetUpdate1 =
AttentionSetUpdate.createForWrite(changeOwner.getAccountId(), Operation.ADD, "test 1");
+
IllegalArgumentException thrown =
assertThrows(
IllegalArgumentException.class,
() ->
- update.setAttentionSetUpdates(
+ update.addToPlannedAttentionSetUpdates(
ImmutableSet.of(attentionSetUpdate0, attentionSetUpdate1)));
assertThat(thrown)
.hasMessageThat()
@@ -771,7 +772,8 @@
AttentionSetUpdate attentionSetUpdate1 =
AttentionSetUpdate.createForWrite(otherUser.getAccountId(), Operation.ADD, "test");
- update.setAttentionSetUpdates(ImmutableSet.of(attentionSetUpdate0, attentionSetUpdate1));
+ update.addToPlannedAttentionSetUpdates(
+ ImmutableSet.of(attentionSetUpdate0, attentionSetUpdate1));
update.commit();
ChangeNotes notes = newNotes(c);
@@ -1186,7 +1188,7 @@
update.putApproval("Code-Review", (short) 1);
update.setChangeMessage("This is a message");
update.putComment(
- Comment.Status.PUBLISHED,
+ HumanComment.Status.PUBLISHED,
newComment(
c.currentPatchSetId(),
"a.txt",
@@ -1206,7 +1208,7 @@
assertThat(notes.getPatchSets().keySet()).containsExactly(psId1, psId2);
assertThat(notes.getApprovals()).isNotEmpty();
assertThat(notes.getChangeMessages()).isNotEmpty();
- assertThat(notes.getComments()).isNotEmpty();
+ assertThat(notes.getHumanComments()).isNotEmpty();
// publish ps2
update = newUpdate(c, changeOwner);
@@ -1222,7 +1224,7 @@
assertThat(notes.getPatchSets().keySet()).containsExactly(psId1);
assertThat(notes.getApprovals()).isEmpty();
assertThat(notes.getChangeMessages()).isEmpty();
- assertThat(notes.getComments()).isEmpty();
+ assertThat(notes.getHumanComments()).isEmpty();
}
@Test
@@ -1279,14 +1281,14 @@
Map<PatchSet.Id, PatchSet> patchSets = notes.getPatchSets();
assertThat(patchSets.get(psId1).pushCertificate()).isEmpty();
assertThat(patchSets.get(psId2).pushCertificate()).hasValue(pushCert);
- assertThat(notes.getComments()).isEmpty();
+ assertThat(notes.getHumanComments()).isEmpty();
// comment on ps2
update = newUpdate(c, changeOwner);
update.setPatchSetId(psId2);
Timestamp ts = TimeUtil.nowTs();
update.putComment(
- Comment.Status.PUBLISHED,
+ HumanComment.Status.PUBLISHED,
newComment(
psId2,
"a.txt",
@@ -1307,7 +1309,7 @@
patchSets = notes.getPatchSets();
assertThat(patchSets.get(psId1).pushCertificate()).isEmpty();
assertThat(patchSets.get(psId2).pushCertificate()).hasValue(pushCert);
- assertThat(notes.getComments()).isNotEmpty();
+ assertThat(notes.getHumanComments()).isNotEmpty();
}
@Test
@@ -1356,7 +1358,7 @@
PatchSet.Id psId = c.currentPatchSetId();
RevCommit tipCommit;
try (NoteDbUpdateManager updateManager = updateManagerFactory.create(project)) {
- Comment comment1 =
+ HumanComment comment1 =
newComment(
psId,
"file1",
@@ -1371,7 +1373,7 @@
ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234"),
false);
update1.setPatchSetId(psId);
- update1.putComment(Comment.Status.PUBLISHED, comment1);
+ update1.putComment(HumanComment.Status.PUBLISHED, comment1);
updateManager.add(update1);
ChangeUpdate update2 = newUpdate(c, otherUser);
@@ -1570,7 +1572,7 @@
PatchSet.Id psId = c.currentPatchSetId();
ObjectId commitId = ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
- Comment comment =
+ HumanComment comment =
newComment(
psId,
"file1",
@@ -1585,11 +1587,11 @@
commitId,
false);
update.setPatchSetId(psId);
- update.putComment(Comment.Status.PUBLISHED, comment);
+ update.putComment(HumanComment.Status.PUBLISHED, comment);
update.commit();
ChangeNotes notes = newNotes(c);
- assertThat(notes.getComments()).isEqualTo(ImmutableListMultimap.of(commitId, comment));
+ assertThat(notes.getHumanComments()).isEqualTo(ImmutableListMultimap.of(commitId, comment));
}
@Test
@@ -1600,7 +1602,7 @@
ObjectId commitId = ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
CommentRange range = new CommentRange(1, 0, 2, 0);
- Comment comment =
+ HumanComment comment =
newComment(
psId,
"file1",
@@ -1615,11 +1617,11 @@
commitId,
false);
update.setPatchSetId(psId);
- update.putComment(Comment.Status.PUBLISHED, comment);
+ update.putComment(HumanComment.Status.PUBLISHED, comment);
update.commit();
ChangeNotes notes = newNotes(c);
- assertThat(notes.getComments()).isEqualTo(ImmutableListMultimap.of(commitId, comment));
+ assertThat(notes.getHumanComments()).isEqualTo(ImmutableListMultimap.of(commitId, comment));
}
@Test
@@ -1630,7 +1632,7 @@
ObjectId commitId = ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
CommentRange range = new CommentRange(0, 0, 0, 0);
- Comment comment =
+ HumanComment comment =
newComment(
psId,
"file",
@@ -1645,11 +1647,11 @@
commitId,
false);
update.setPatchSetId(psId);
- update.putComment(Comment.Status.PUBLISHED, comment);
+ update.putComment(HumanComment.Status.PUBLISHED, comment);
update.commit();
ChangeNotes notes = newNotes(c);
- assertThat(notes.getComments()).isEqualTo(ImmutableListMultimap.of(commitId, comment));
+ assertThat(notes.getHumanComments()).isEqualTo(ImmutableListMultimap.of(commitId, comment));
}
@Test
@@ -1660,7 +1662,7 @@
ObjectId commitId = ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
CommentRange range = new CommentRange(1, 2, 3, 4);
- Comment comment =
+ HumanComment comment =
newComment(
psId,
"",
@@ -1675,11 +1677,11 @@
commitId,
false);
update.setPatchSetId(psId);
- update.putComment(Comment.Status.PUBLISHED, comment);
+ update.putComment(HumanComment.Status.PUBLISHED, comment);
update.commit();
ChangeNotes notes = newNotes(c);
- assertThat(notes.getComments()).isEqualTo(ImmutableListMultimap.of(commitId, comment));
+ assertThat(notes.getHumanComments()).isEqualTo(ImmutableListMultimap.of(commitId, comment));
}
@Test
@@ -1699,7 +1701,7 @@
Timestamp time = TimeUtil.nowTs();
ObjectId commitId = ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
- Comment comment1 =
+ HumanComment comment1 =
newComment(
psId1,
"file1",
@@ -1713,7 +1715,7 @@
(short) 0,
commitId,
false);
- Comment comment2 =
+ HumanComment comment2 =
newComment(
psId1,
"file1",
@@ -1727,7 +1729,7 @@
(short) 0,
commitId,
false);
- Comment comment3 =
+ HumanComment comment3 =
newComment(
psId2,
"file1",
@@ -1744,13 +1746,13 @@
ChangeUpdate update = newUpdate(c, otherUser);
update.setPatchSetId(psId2);
- update.putComment(Comment.Status.PUBLISHED, comment3);
- update.putComment(Comment.Status.PUBLISHED, comment2);
- update.putComment(Comment.Status.PUBLISHED, comment1);
+ update.putComment(HumanComment.Status.PUBLISHED, comment3);
+ update.putComment(HumanComment.Status.PUBLISHED, comment2);
+ update.putComment(HumanComment.Status.PUBLISHED, comment1);
update.commit();
ChangeNotes notes = newNotes(c);
- assertThat(notes.getComments())
+ assertThat(notes.getHumanComments())
.isEqualTo(
ImmutableListMultimap.of(
commitId, comment1,
@@ -1770,7 +1772,7 @@
PatchSet.Id psId = c.currentPatchSetId();
ObjectId commitId = ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
- Comment comment =
+ HumanComment comment =
newComment(
psId,
"file",
@@ -1786,12 +1788,12 @@
false);
comment.setRealAuthor(changeOwner.getAccountId());
update.setPatchSetId(psId);
- update.putComment(Comment.Status.PUBLISHED, comment);
+ update.putComment(HumanComment.Status.PUBLISHED, comment);
update.commit();
ChangeNotes notes = newNotes(c);
- assertThat(notes.getComments()).isEqualTo(ImmutableListMultimap.of(commitId, comment));
+ assertThat(notes.getHumanComments()).isEqualTo(ImmutableListMultimap.of(commitId, comment));
}
@Test
@@ -1809,7 +1811,7 @@
Timestamp time = TimeUtil.nowTs();
PatchSet.Id psId = c.currentPatchSetId();
- Comment comment =
+ HumanComment comment =
newComment(
psId,
"file1",
@@ -1824,12 +1826,12 @@
ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234"),
false);
update.setPatchSetId(psId);
- update.putComment(Comment.Status.PUBLISHED, comment);
+ update.putComment(HumanComment.Status.PUBLISHED, comment);
update.commit();
ChangeNotes notes = newNotes(c);
- assertThat(notes.getComments())
+ assertThat(notes.getHumanComments())
.isEqualTo(ImmutableListMultimap.of(comment.getCommitId(), comment));
}
@@ -1847,7 +1849,7 @@
Timestamp now = TimeUtil.nowTs();
PatchSet.Id psId = c.currentPatchSetId();
- Comment commentForBase =
+ HumanComment commentForBase =
newComment(
psId,
"filename",
@@ -1862,11 +1864,11 @@
commitId1,
false);
update.setPatchSetId(psId);
- update.putComment(Comment.Status.PUBLISHED, commentForBase);
+ update.putComment(HumanComment.Status.PUBLISHED, commentForBase);
update.commit();
update = newUpdate(c, otherUser);
- Comment commentForPS =
+ HumanComment commentForPS =
newComment(
psId,
"filename",
@@ -1881,10 +1883,10 @@
commitId2,
false);
update.setPatchSetId(psId);
- update.putComment(Comment.Status.PUBLISHED, commentForPS);
+ update.putComment(HumanComment.Status.PUBLISHED, commentForPS);
update.commit();
- assertThat(newNotes(c).getComments())
+ assertThat(newNotes(c).getHumanComments())
.containsExactlyEntriesIn(
ImmutableListMultimap.of(
commitId1, commentForBase,
@@ -1905,7 +1907,7 @@
ChangeUpdate update = newUpdate(c, otherUser);
Timestamp timeForComment1 = TimeUtil.nowTs();
Timestamp timeForComment2 = TimeUtil.nowTs();
- Comment comment1 =
+ HumanComment comment1 =
newComment(
psId,
filename,
@@ -1920,11 +1922,11 @@
commitId,
false);
update.setPatchSetId(psId);
- update.putComment(Comment.Status.PUBLISHED, comment1);
+ update.putComment(HumanComment.Status.PUBLISHED, comment1);
update.commit();
update = newUpdate(c, otherUser);
- Comment comment2 =
+ HumanComment comment2 =
newComment(
psId,
filename,
@@ -1939,10 +1941,10 @@
commitId,
false);
update.setPatchSetId(psId);
- update.putComment(Comment.Status.PUBLISHED, comment2);
+ update.putComment(HumanComment.Status.PUBLISHED, comment2);
update.commit();
- assertThat(newNotes(c).getComments())
+ assertThat(newNotes(c).getHumanComments())
.containsExactlyEntriesIn(
ImmutableListMultimap.of(
commitId, comment1,
@@ -1963,7 +1965,7 @@
ChangeUpdate update = newUpdate(c, otherUser);
Timestamp now = TimeUtil.nowTs();
- Comment comment1 =
+ HumanComment comment1 =
newComment(
psId,
filename1,
@@ -1978,11 +1980,11 @@
commitId,
false);
update.setPatchSetId(psId);
- update.putComment(Comment.Status.PUBLISHED, comment1);
+ update.putComment(HumanComment.Status.PUBLISHED, comment1);
update.commit();
update = newUpdate(c, otherUser);
- Comment comment2 =
+ HumanComment comment2 =
newComment(
psId,
filename2,
@@ -1997,10 +1999,10 @@
commitId,
false);
update.setPatchSetId(psId);
- update.putComment(Comment.Status.PUBLISHED, comment2);
+ update.putComment(HumanComment.Status.PUBLISHED, comment2);
update.commit();
- assertThat(newNotes(c).getComments())
+ assertThat(newNotes(c).getHumanComments())
.containsExactlyEntriesIn(
ImmutableListMultimap.of(
commitId, comment1,
@@ -2021,7 +2023,7 @@
ChangeUpdate update = newUpdate(c, otherUser);
Timestamp now = TimeUtil.nowTs();
- Comment comment1 =
+ HumanComment comment1 =
newComment(
ps1,
filename,
@@ -2036,7 +2038,7 @@
commitId1,
false);
update.setPatchSetId(ps1);
- update.putComment(Comment.Status.PUBLISHED, comment1);
+ update.putComment(HumanComment.Status.PUBLISHED, comment1);
update.commit();
incrementPatchSet(c);
@@ -2044,7 +2046,7 @@
update = newUpdate(c, otherUser);
now = TimeUtil.nowTs();
- Comment comment2 =
+ HumanComment comment2 =
newComment(
ps2,
filename,
@@ -2059,10 +2061,10 @@
commitId2,
false);
update.setPatchSetId(ps2);
- update.putComment(Comment.Status.PUBLISHED, comment2);
+ update.putComment(HumanComment.Status.PUBLISHED, comment2);
update.commit();
- assertThat(newNotes(c).getComments())
+ assertThat(newNotes(c).getHumanComments())
.containsExactlyEntriesIn(
ImmutableListMultimap.of(
commitId1, comment1,
@@ -2081,7 +2083,7 @@
ChangeUpdate update = newUpdate(c, otherUser);
Timestamp now = TimeUtil.nowTs();
- Comment comment1 =
+ HumanComment comment1 =
newComment(
ps1,
filename,
@@ -2096,22 +2098,22 @@
commitId,
false);
update.setPatchSetId(ps1);
- update.putComment(Comment.Status.DRAFT, comment1);
+ update.putComment(HumanComment.Status.DRAFT, comment1);
update.commit();
ChangeNotes notes = newNotes(c);
assertThat(notes.getDraftComments(otherUserId))
.containsExactlyEntriesIn(ImmutableListMultimap.of(commitId, comment1));
- assertThat(notes.getComments()).isEmpty();
+ assertThat(notes.getHumanComments()).isEmpty();
update = newUpdate(c, otherUser);
update.setPatchSetId(ps1);
- update.putComment(Comment.Status.PUBLISHED, comment1);
+ update.putComment(HumanComment.Status.PUBLISHED, comment1);
update.commit();
notes = newNotes(c);
assertThat(notes.getDraftComments(otherUserId)).isEmpty();
- assertThat(notes.getComments())
+ assertThat(notes.getHumanComments())
.containsExactlyEntriesIn(ImmutableListMultimap.of(commitId, comment1));
}
@@ -2131,7 +2133,7 @@
// Write two drafts on the same side of one patch set.
ChangeUpdate update = newUpdate(c, otherUser);
update.setPatchSetId(psId);
- Comment comment1 =
+ HumanComment comment1 =
newComment(
psId,
filename,
@@ -2145,7 +2147,7 @@
side,
commitId,
false);
- Comment comment2 =
+ HumanComment comment2 =
newComment(
psId,
filename,
@@ -2159,8 +2161,8 @@
side,
commitId,
false);
- update.putComment(Comment.Status.DRAFT, comment1);
- update.putComment(Comment.Status.DRAFT, comment2);
+ update.putComment(HumanComment.Status.DRAFT, comment1);
+ update.putComment(HumanComment.Status.DRAFT, comment2);
update.commit();
ChangeNotes notes = newNotes(c);
@@ -2170,18 +2172,18 @@
commitId, comment1,
commitId, comment2))
.inOrder();
- assertThat(notes.getComments()).isEmpty();
+ assertThat(notes.getHumanComments()).isEmpty();
// Publish first draft.
update = newUpdate(c, otherUser);
update.setPatchSetId(psId);
- update.putComment(Comment.Status.PUBLISHED, comment1);
+ update.putComment(HumanComment.Status.PUBLISHED, comment1);
update.commit();
notes = newNotes(c);
assertThat(notes.getDraftComments(otherUserId))
.containsExactlyEntriesIn(ImmutableListMultimap.of(commitId, comment2));
- assertThat(notes.getComments())
+ assertThat(notes.getHumanComments())
.containsExactlyEntriesIn(ImmutableListMultimap.of(commitId, comment1));
}
@@ -2201,7 +2203,7 @@
// Write two drafts, one on each side of the patchset.
ChangeUpdate update = newUpdate(c, otherUser);
update.setPatchSetId(psId);
- Comment baseComment =
+ HumanComment baseComment =
newComment(
psId,
filename,
@@ -2215,7 +2217,7 @@
(short) 0,
commitId1,
false);
- Comment psComment =
+ HumanComment psComment =
newComment(
psId,
filename,
@@ -2230,8 +2232,8 @@
commitId2,
false);
- update.putComment(Comment.Status.DRAFT, baseComment);
- update.putComment(Comment.Status.DRAFT, psComment);
+ update.putComment(HumanComment.Status.DRAFT, baseComment);
+ update.putComment(HumanComment.Status.DRAFT, psComment);
update.commit();
ChangeNotes notes = newNotes(c);
@@ -2240,19 +2242,19 @@
ImmutableListMultimap.of(
commitId1, baseComment,
commitId2, psComment));
- assertThat(notes.getComments()).isEmpty();
+ assertThat(notes.getHumanComments()).isEmpty();
// Publish both comments.
update = newUpdate(c, otherUser);
update.setPatchSetId(psId);
- update.putComment(Comment.Status.PUBLISHED, baseComment);
- update.putComment(Comment.Status.PUBLISHED, psComment);
+ update.putComment(HumanComment.Status.PUBLISHED, baseComment);
+ update.putComment(HumanComment.Status.PUBLISHED, psComment);
update.commit();
notes = newNotes(c);
assertThat(notes.getDraftComments(otherUserId)).isEmpty();
- assertThat(notes.getComments())
+ assertThat(notes.getHumanComments())
.containsExactlyEntriesIn(
ImmutableListMultimap.of(
commitId1, baseComment,
@@ -2271,7 +2273,7 @@
ChangeUpdate update = newUpdate(c, otherUser);
Timestamp now = TimeUtil.nowTs();
- Comment comment =
+ HumanComment comment =
newComment(
psId,
filename,
@@ -2286,7 +2288,7 @@
commitId,
false);
update.setPatchSetId(psId);
- update.putComment(Comment.Status.DRAFT, comment);
+ update.putComment(HumanComment.Status.DRAFT, comment);
update.commit();
ChangeNotes notes = newNotes(c);
@@ -2316,7 +2318,7 @@
ChangeUpdate update = newUpdate(c, otherUser);
Timestamp now = TimeUtil.nowTs();
- Comment comment1 =
+ HumanComment comment1 =
newComment(
ps1,
filename,
@@ -2331,7 +2333,7 @@
commitId1,
false);
update.setPatchSetId(ps1);
- update.putComment(Comment.Status.DRAFT, comment1);
+ update.putComment(HumanComment.Status.DRAFT, comment1);
update.commit();
incrementPatchSet(c);
@@ -2339,7 +2341,7 @@
update = newUpdate(c, otherUser);
now = TimeUtil.nowTs();
- Comment comment2 =
+ HumanComment comment2 =
newComment(
ps2,
filename,
@@ -2354,7 +2356,7 @@
commitId2,
false);
update.setPatchSetId(ps2);
- update.putComment(Comment.Status.DRAFT, comment2);
+ update.putComment(HumanComment.Status.DRAFT, comment2);
update.commit();
ChangeNotes notes = newNotes(c);
@@ -2384,7 +2386,7 @@
ChangeUpdate update = newUpdate(c, otherUser);
Timestamp now = TimeUtil.nowTs();
- Comment comment =
+ HumanComment comment =
newComment(
ps1,
filename,
@@ -2398,7 +2400,7 @@
side,
commitId,
false);
- update.putComment(Comment.Status.PUBLISHED, comment);
+ update.putComment(HumanComment.Status.PUBLISHED, comment);
update.commit();
assertThat(repo.exactRef(changeMetaRef(c.getId()))).isNotNull();
@@ -2417,7 +2419,7 @@
ChangeUpdate update = newUpdate(c, otherUser);
Timestamp now = TimeUtil.nowTs();
- Comment draft =
+ HumanComment draft =
newComment(
ps1,
filename,
@@ -2431,7 +2433,7 @@
side,
commitId,
false);
- update.putComment(Comment.Status.DRAFT, draft);
+ update.putComment(HumanComment.Status.DRAFT, draft);
update.commit();
String draftRef = refsDraftComments(c.getId(), otherUser.getAccountId());
@@ -2439,7 +2441,7 @@
assertThat(old).isNotNull();
update = newUpdate(c, otherUser);
- Comment pub =
+ HumanComment pub =
newComment(
ps1,
filename,
@@ -2453,7 +2455,7 @@
side,
commitId,
false);
- update.putComment(Comment.Status.PUBLISHED, pub);
+ update.putComment(HumanComment.Status.PUBLISHED, pub);
update.commit();
assertThat(exactRefAllUsers(draftRef)).isEqualTo(old);
@@ -2469,7 +2471,7 @@
Timestamp now = TimeUtil.nowTs();
PatchSet.Id psId = c.currentPatchSetId();
- Comment comment =
+ HumanComment comment =
newComment(
psId,
"filename",
@@ -2484,10 +2486,10 @@
commitId,
false);
update.setPatchSetId(psId);
- update.putComment(Comment.Status.PUBLISHED, comment);
+ update.putComment(HumanComment.Status.PUBLISHED, comment);
update.commit();
- assertThat(newNotes(c).getComments())
+ assertThat(newNotes(c).getHumanComments())
.containsExactlyEntriesIn(ImmutableListMultimap.of(commitId, comment));
}
@@ -2501,7 +2503,7 @@
Timestamp now = TimeUtil.nowTs();
PatchSet.Id psId = c.currentPatchSetId();
- Comment comment =
+ HumanComment comment =
newComment(
psId,
"filename",
@@ -2516,10 +2518,10 @@
commitId,
false);
update.setPatchSetId(psId);
- update.putComment(Comment.Status.PUBLISHED, comment);
+ update.putComment(HumanComment.Status.PUBLISHED, comment);
update.commit();
- assertThat(newNotes(c).getComments())
+ assertThat(newNotes(c).getHumanComments())
.containsExactlyEntriesIn(ImmutableListMultimap.of(commitId, comment));
}
@@ -2540,7 +2542,7 @@
ChangeUpdate update = newUpdate(c, otherUser);
update.setPatchSetId(ps2);
Timestamp now = TimeUtil.nowTs();
- Comment comment1 =
+ HumanComment comment1 =
newComment(
ps1,
filename,
@@ -2554,7 +2556,7 @@
side,
commitId1,
false);
- Comment comment2 =
+ HumanComment comment2 =
newComment(
ps2,
filename,
@@ -2568,23 +2570,23 @@
side,
commitId2,
false);
- update.putComment(Comment.Status.DRAFT, comment1);
- update.putComment(Comment.Status.DRAFT, comment2);
+ update.putComment(HumanComment.Status.DRAFT, comment1);
+ update.putComment(HumanComment.Status.DRAFT, comment2);
update.commit();
ChangeNotes notes = newNotes(c);
assertThat(notes.getDraftComments(otherUserId)).hasSize(2);
- assertThat(notes.getComments()).isEmpty();
+ assertThat(notes.getHumanComments()).isEmpty();
update = newUpdate(c, otherUser);
update.setPatchSetId(ps2);
- update.putComment(Comment.Status.PUBLISHED, comment1);
- update.putComment(Comment.Status.PUBLISHED, comment2);
+ update.putComment(HumanComment.Status.PUBLISHED, comment1);
+ update.putComment(HumanComment.Status.PUBLISHED, comment2);
update.commit();
notes = newNotes(c);
assertThat(notes.getDraftComments(otherUserId)).isEmpty();
- assertThat(notes.getComments()).hasSize(2);
+ assertThat(notes.getHumanComments()).hasSize(2);
}
@Test
@@ -2598,7 +2600,7 @@
ChangeUpdate update = newUpdate(c, otherUser);
update.setPatchSetId(ps1);
Timestamp now = TimeUtil.nowTs();
- Comment comment1 =
+ HumanComment comment1 =
newComment(
ps1,
"file1",
@@ -2612,7 +2614,7 @@
side,
commitId1,
false);
- Comment comment2 =
+ HumanComment comment2 =
newComment(
ps1,
"file2",
@@ -2626,23 +2628,23 @@
side,
commitId1,
false);
- update.putComment(Comment.Status.DRAFT, comment1);
- update.putComment(Comment.Status.DRAFT, comment2);
+ update.putComment(HumanComment.Status.DRAFT, comment1);
+ update.putComment(HumanComment.Status.DRAFT, comment2);
update.commit();
ChangeNotes notes = newNotes(c);
assertThat(notes.getDraftComments(otherUserId).get(commitId1))
.containsExactly(comment1, comment2);
- assertThat(notes.getComments()).isEmpty();
+ assertThat(notes.getHumanComments()).isEmpty();
update = newUpdate(c, otherUser);
update.setPatchSetId(ps1);
- update.putComment(Comment.Status.PUBLISHED, comment2);
+ update.putComment(HumanComment.Status.PUBLISHED, comment2);
update.commit();
notes = newNotes(c);
assertThat(notes.getDraftComments(otherUserId).get(commitId1)).containsExactly(comment1);
- assertThat(notes.getComments().get(commitId1)).containsExactly(comment2);
+ assertThat(notes.getHumanComments().get(commitId1)).containsExactly(comment2);
}
@Test
@@ -2671,7 +2673,7 @@
ChangeUpdate update = newUpdate(c, otherUser);
Timestamp now = TimeUtil.nowTs();
- Comment comment1 =
+ HumanComment comment1 =
newComment(
ps1,
"file1",
@@ -2685,7 +2687,7 @@
side,
commitId1,
false);
- Comment comment2 =
+ HumanComment comment2 =
newComment(
ps1,
"file2",
@@ -2699,8 +2701,8 @@
side,
commitId1,
false);
- update.putComment(Comment.Status.DRAFT, comment1);
- update.putComment(Comment.Status.DRAFT, comment2);
+ update.putComment(HumanComment.Status.DRAFT, comment1);
+ update.putComment(HumanComment.Status.DRAFT, comment2);
update.commit();
String refName = refsDraftComments(c.getId(), otherUserId);
@@ -2708,7 +2710,7 @@
update = newUpdate(c, otherUser);
update.setPatchSetId(ps1);
- update.putComment(Comment.Status.PUBLISHED, comment2);
+ update.putComment(HumanComment.Status.PUBLISHED, comment2);
update.commit();
assertThat(exactRefAllUsers(refName)).isNotNull();
assertThat(exactRefAllUsers(refName)).isNotEqualTo(oldDraftId);
@@ -2730,11 +2732,11 @@
// Zombie comment is filtered out of drafts via ChangeNotes.
ChangeNotes notes = newNotes(c);
assertThat(notes.getDraftComments(otherUserId).get(commitId1)).containsExactly(comment1);
- assertThat(notes.getComments().get(commitId1)).containsExactly(comment2);
+ assertThat(notes.getHumanComments().get(commitId1)).containsExactly(comment2);
update = newUpdate(c, otherUser);
update.setPatchSetId(ps1);
- update.putComment(Comment.Status.PUBLISHED, comment1);
+ update.putComment(HumanComment.Status.PUBLISHED, comment1);
update.commit();
// Updating an unrelated comment causes the zombie comment to get fixed up.
@@ -2748,7 +2750,7 @@
ObjectId commitId = ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
ChangeUpdate update1 = newUpdate(c, otherUser);
- Comment comment1 =
+ HumanComment comment1 =
newComment(
c.currentPatchSetId(),
"filename",
@@ -2762,10 +2764,10 @@
(short) 1,
commitId,
false);
- update1.putComment(Comment.Status.PUBLISHED, comment1);
+ update1.putComment(HumanComment.Status.PUBLISHED, comment1);
ChangeUpdate update2 = newUpdate(c, otherUser);
- Comment comment2 =
+ HumanComment comment2 =
newComment(
c.currentPatchSetId(),
"filename",
@@ -2779,7 +2781,7 @@
(short) 1,
commitId,
false);
- update2.putComment(Comment.Status.PUBLISHED, comment2);
+ update2.putComment(HumanComment.Status.PUBLISHED, comment2);
try (NoteDbUpdateManager manager = updateManagerFactory.create(project)) {
manager.add(update1);
@@ -2788,7 +2790,7 @@
}
ChangeNotes notes = newNotes(c);
- List<Comment> comments = notes.getComments().get(commitId);
+ List<HumanComment> comments = notes.getHumanComments().get(commitId);
assertThat(comments).hasSize(2);
assertThat(comments.get(0).message).isEqualTo("comment 1");
assertThat(comments.get(1).message).isEqualTo("comment 2");
@@ -2815,14 +2817,14 @@
int numMessages = notes.getChangeMessages().size();
int numPatchSets = notes.getPatchSets().size();
int numApprovals = notes.getApprovals().size();
- int numComments = notes.getComments().size();
+ int numComments = notes.getHumanComments().size();
ChangeUpdate update = newUpdate(c, changeOwner);
update.setPatchSetId(PatchSet.id(c.getId(), c.currentPatchSetId().get() + 1));
update.setChangeMessage("Should be ignored");
update.putApproval("Code-Review", (short) 2);
CommentRange range = new CommentRange(1, 1, 2, 1);
- Comment comment =
+ HumanComment comment =
newComment(
update.getPatchSetId(),
"filename",
@@ -2836,14 +2838,14 @@
(short) 1,
ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234"),
false);
- update.putComment(Comment.Status.PUBLISHED, comment);
+ update.putComment(HumanComment.Status.PUBLISHED, comment);
update.commit();
notes = newNotes(c);
assertThat(notes.getChangeMessages()).hasSize(numMessages);
assertThat(notes.getPatchSets()).hasSize(numPatchSets);
assertThat(notes.getApprovals()).hasSize(numApprovals);
- assertThat(notes.getComments()).hasSize(numComments);
+ assertThat(notes.getHumanComments()).hasSize(numComments);
}
@Test
diff --git a/javatests/com/google/gerrit/server/notedb/CommentTimestampAdapterTest.java b/javatests/com/google/gerrit/server/notedb/CommentTimestampAdapterTest.java
index c2620dc..2c1348c 100644
--- a/javatests/com/google/gerrit/server/notedb/CommentTimestampAdapterTest.java
+++ b/javatests/com/google/gerrit/server/notedb/CommentTimestampAdapterTest.java
@@ -18,6 +18,7 @@
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.sql.Timestamp;
@@ -151,7 +152,7 @@
@Test
public void newAdapterRoundTripOfWholeComment() {
Comment c =
- new Comment(
+ new HumanComment(
new Comment.Key("uuid", "filename", 1),
Account.id(100),
NON_DST_TS,
@@ -165,7 +166,7 @@
String json = gson.toJson(c);
assertThat(json).contains("\"writtenOn\": \"" + NON_DST_STR_TRUNC + "\",");
- Comment result = gson.fromJson(json, Comment.class);
+ Comment result = gson.fromJson(json, HumanComment.class);
// Round-trip lossily truncates ms, but that's ok.
assertThat(result.writtenOn).isEqualTo(NON_DST_TS_TRUNC);
result.writtenOn = NON_DST_TS;
diff --git a/javatests/com/google/gerrit/server/notedb/CommitMessageOutputTest.java b/javatests/com/google/gerrit/server/notedb/CommitMessageOutputTest.java
index 6a090c1..8818d81 100644
--- a/javatests/com/google/gerrit/server/notedb/CommitMessageOutputTest.java
+++ b/javatests/com/google/gerrit/server/notedb/CommitMessageOutputTest.java
@@ -45,7 +45,6 @@
update.putReviewer(otherUser.getAccount().id(), CC);
update.commit();
assertThat(update.getRefName()).isEqualTo("refs/changes/01/1/meta");
-
RevCommit commit = parseCommit(update.getResult());
assertBodyEquals(
"Update patch set 1\n"
@@ -62,7 +61,8 @@
+ "Reviewer: Gerrit User 1 <1@gerrit>\n"
+ "CC: Gerrit User 2 <2@gerrit>\n"
+ "Label: Code-Review=-1\n"
- + "Label: Verified=+1\n",
+ + "Label: Verified=+1\n"
+ + "Attention: {\"person_ident\":\"Gerrit User 1 \\u003c1@gerrit\\u003e\",\"operation\":\"ADD\",\"reason\":\"Reviewer was added\"}\n",
commit);
PersonIdent author = commit.getAuthorIdent();
@@ -245,7 +245,8 @@
update.commit();
assertBodyEquals(
- "Update patch set 1\n\nPatch-set: 1\nReviewer: Gerrit User 1 <1@gerrit>\n",
+ "Update patch set 1\n\nPatch-set: 1\nReviewer: Gerrit User 1 <1@gerrit>\n"
+ + "Attention: {\"person_ident\":\"Gerrit User 1 \\u003c1@gerrit\\u003e\",\"operation\":\"ADD\",\"reason\":\"Reviewer was added\"}\n",
update.getResult());
}
diff --git a/javatests/com/google/gerrit/server/notedb/DraftCommentNotesTest.java b/javatests/com/google/gerrit/server/notedb/DraftCommentNotesTest.java
index bf49884..041366c 100644
--- a/javatests/com/google/gerrit/server/notedb/DraftCommentNotesTest.java
+++ b/javatests/com/google/gerrit/server/notedb/DraftCommentNotesTest.java
@@ -17,7 +17,7 @@
import static com.google.common.truth.Truth.assertThat;
import com.google.gerrit.entities.Change;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.server.util.time.TimeUtil;
import org.eclipse.jgit.lib.ObjectId;
@@ -31,7 +31,7 @@
Change c = newChange();
ChangeUpdate update = newUpdate(c, otherUser);
update.setPatchSetId(c.currentPatchSetId());
- update.putComment(Comment.Status.PUBLISHED, comment(c.currentPatchSetId()));
+ update.putComment(HumanComment.Status.PUBLISHED, comment(c.currentPatchSetId()));
update.commit();
assertThat(newNotes(c).getDraftComments(otherUserId)).isEmpty();
@@ -44,13 +44,13 @@
ChangeUpdate update = newUpdate(c, otherUser);
update.setPatchSetId(c.currentPatchSetId());
- update.putComment(Comment.Status.DRAFT, comment(c.currentPatchSetId()));
+ update.putComment(HumanComment.Status.DRAFT, comment(c.currentPatchSetId()));
update.commit();
assertThat(newNotes(c).getDraftComments(otherUserId)).hasSize(1);
assertableFanOutExecutor.assertInteractions(0);
update = newUpdate(c, otherUser);
- update.putComment(Comment.Status.PUBLISHED, comment(c.currentPatchSetId()));
+ update.putComment(HumanComment.Status.PUBLISHED, comment(c.currentPatchSetId()));
update.commit();
assertThat(newNotes(c).getDraftComments(otherUserId)).isEmpty();
@@ -63,7 +63,7 @@
ChangeUpdate update = newUpdate(c, otherUser);
update.setPatchSetId(c.currentPatchSetId());
- update.putComment(Comment.Status.DRAFT, comment(c.currentPatchSetId()));
+ update.putComment(HumanComment.Status.DRAFT, comment(c.currentPatchSetId()));
update.commit();
ChangeNotes notes = newNotes(c);
@@ -80,7 +80,7 @@
assertableFanOutExecutor.assertInteractions(0);
}
- private Comment comment(PatchSet.Id psId) {
+ private HumanComment comment(PatchSet.Id psId) {
return newComment(
psId,
"filename",
diff --git a/javatests/com/google/gerrit/server/plugins/AutoRegisterModulesTest.java b/javatests/com/google/gerrit/server/plugins/AutoRegisterModulesTest.java
new file mode 100644
index 0000000..55c9bc3
--- /dev/null
+++ b/javatests/com/google/gerrit/server/plugins/AutoRegisterModulesTest.java
@@ -0,0 +1,101 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.plugins;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.collect.Lists;
+import com.google.gerrit.extensions.annotations.Export;
+import com.google.gerrit.extensions.annotations.Listen;
+import com.google.gerrit.sshd.SshCommand;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.jar.Manifest;
+import org.junit.Test;
+
+public class AutoRegisterModulesTest {
+
+ @Test
+ public void shouldRegisterSshCommand() throws InvalidPluginException {
+ ModuleGenerator sshModule = mock(ModuleGenerator.class);
+ PluginGuiceEnvironment env = mock(PluginGuiceEnvironment.class);
+
+ when(env.hasSshModule()).thenReturn(true);
+ when(env.newSshModuleGenerator()).thenReturn(sshModule);
+
+ PluginContentScanner scanner = new TestPluginContextScanner();
+ ClassLoader classLoader = this.getClass().getClassLoader();
+
+ AutoRegisterModules objectUnderTest =
+ new AutoRegisterModules("test_plugin_name", env, scanner, classLoader);
+ objectUnderTest.discover();
+
+ verify(sshModule).setPluginName("test_plugin_name");
+ verify(sshModule).export(any(Export.class), eq(TestSshCommand.class));
+ }
+
+ @Export(value = "test")
+ public static class TestSshCommand extends SshCommand {
+ @Override
+ protected void run() throws UnloggedFailure, Failure, Exception {}
+ }
+
+ private static class TestPluginContextScanner implements PluginContentScanner {
+
+ @Override
+ public Manifest getManifest() throws IOException {
+ return null;
+ }
+
+ @Override
+ public Map<Class<? extends Annotation>, Iterable<ExtensionMetaData>> scan(
+ String pluginName, Iterable<Class<? extends Annotation>> annotations)
+ throws InvalidPluginException {
+ Map<Class<? extends Annotation>, Iterable<ExtensionMetaData>> extensions = new HashMap<>();
+ extensions.put(
+ Export.class,
+ Lists.newArrayList(
+ new ExtensionMetaData(
+ "com.google.gerrit.server.plugins.AutoRegisterModulesTest$TestSshCommand",
+ "com.google.gerrit.extensions.annotations.Export")));
+ extensions.put(Listen.class, Lists.newArrayList());
+ return extensions;
+ }
+
+ @Override
+ public Optional<PluginEntry> getEntry(String resourcePath) throws IOException {
+ return null;
+ }
+
+ @Override
+ public InputStream getInputStream(PluginEntry entry) throws IOException {
+ return null;
+ }
+
+ @Override
+ public Enumeration<PluginEntry> entries() {
+ return null;
+ }
+ }
+}
diff --git a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
index 75fce8e..331bb4c 100644
--- a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
+++ b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
@@ -59,8 +59,8 @@
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.api.GerritApi;
import com.google.gerrit.extensions.api.changes.AddReviewerInput;
-import com.google.gerrit.extensions.api.changes.AddToAttentionSetInput;
import com.google.gerrit.extensions.api.changes.AssigneeInput;
+import com.google.gerrit.extensions.api.changes.AttentionSetInput;
import com.google.gerrit.extensions.api.changes.ChangeApi;
import com.google.gerrit.extensions.api.changes.Changes.QueryRequest;
import com.google.gerrit.extensions.api.changes.DraftInput;
@@ -3016,7 +3016,7 @@
Change change1 = insert(repo, newChange(repo));
Change change2 = insert(repo, newChange(repo));
- AddToAttentionSetInput input = new AddToAttentionSetInput(userId.toString(), "some reason");
+ AttentionSetInput input = new AttentionSetInput(userId.toString(), "some reason");
gApi.changes().id(change1.getChangeId()).addToAttentionSet(input);
assertQuery("attention:" + user.getUserName().get(), change1);
@@ -3029,11 +3029,11 @@
TestRepository<Repo> repo = createProject("repo");
Change change = insert(repo, newChange(repo));
- AddToAttentionSetInput input = new AddToAttentionSetInput(userId.toString(), "reason 1");
+ AttentionSetInput input = new AttentionSetInput(userId.toString(), "reason 1");
gApi.changes().id(change.getChangeId()).addToAttentionSet(input);
Account.Id user2Id =
accountManager.authenticate(AuthRequest.forUser("anotheruser")).getAccountId();
- input = new AddToAttentionSetInput(user2Id.toString(), "reason 2");
+ input = new AttentionSetInput(user2Id.toString(), "reason 2");
gApi.changes().id(change.getChangeId()).addToAttentionSet(input);
List<ChangeInfo> result = newQuery("attention:" + user2Id.toString()).get();
diff --git a/package.json b/package.json
index 0f10b62..30dbb99 100644
--- a/package.json
+++ b/package.json
@@ -15,21 +15,19 @@
"fried-twinkie": "^0.2.2",
"polymer-cli": "^1.9.11",
"prettier": "2.0.5",
- "typescript": "3.8.2",
- "web-component-tester": "^6.5.1"
+ "typescript": "3.8.2"
},
"scripts": {
"clean": "git clean -fdx && bazel clean --expunge",
"start": "polygerrit-ui/run-server.sh",
- "test": "WCT_HEADLESS_MODE=1 WCT_ARGS='--verbose -l chrome' ./polygerrit-ui/app/run_test.sh",
+ "test": "./polygerrit-ui/app/run_test.sh",
"safe_bazelisk": "if which bazelisk >/dev/null; then bazel_bin=bazelisk; else bazel_bin=bazel; fi && $bazel_bin",
"eslint": "npm run safe_bazelisk test polygerrit-ui/app:lint_test",
"eslintfix": "npm run safe_bazelisk run polygerrit-ui/app:lint_bin -- -- --fix $(pwd)/polygerrit-ui/app",
"test-template": "./polygerrit-ui/app/run_template_test.sh",
"polylint": "npm run safe_bazelisk test polygerrit-ui/app:polylint_test",
- "test:karma:debug": "npm run safe_bazelisk run //polygerrit-ui:karma_bin -- -- start $(pwd)/polygerrit-ui/karma.conf.js --browsers ChromeDev --no-single-run --testFiles",
- "test:karma": "npm run safe_bazelisk run //polygerrit-ui:karma_bin -- -- start $(pwd)/polygerrit-ui/karma.conf.js --testFiles",
- "test:wct": "npm run test -- --test_tag_filters=wct"
+ "test:debug": "npm run safe_bazelisk run //polygerrit-ui:karma_bin -- -- start $(pwd)/polygerrit-ui/karma.conf.js --browsers ChromeDev --no-single-run --testFiles",
+ "test:single": "npm run safe_bazelisk run //polygerrit-ui:karma_bin -- -- start $(pwd)/polygerrit-ui/karma.conf.js --testFiles"
},
"repository": {
"type": "git",
diff --git a/plugins/download-commands b/plugins/download-commands
index e26ed31..47b783e 160000
--- a/plugins/download-commands
+++ b/plugins/download-commands
@@ -1 +1 @@
-Subproject commit e26ed31aaf070ff884e96b9a09d39c20437de6cb
+Subproject commit 47b783ea75036664dd591d2d3f1bcd06b68cdd5e
diff --git a/plugins/package.json b/plugins/package.json
new file mode 100644
index 0000000..e0227d1
--- /dev/null
+++ b/plugins/package.json
@@ -0,0 +1,8 @@
+{
+ "name": "polygerrit-plugin-dependencies-placeholder",
+ "description": "Gerrit Code Review - Polygerrit plugin dependencies placeholder, expected to be overriden by plugins",
+ "browser": true,
+ "dependencies": {},
+ "license": "Apache-2.0",
+ "private": true
+}
\ No newline at end of file
diff --git a/plugins/replication b/plugins/replication
index dc6762f..b0ecbd3 160000
--- a/plugins/replication
+++ b/plugins/replication
@@ -1 +1 @@
-Subproject commit dc6762f60e561868cabe4824c4c13291eeaa068d
+Subproject commit b0ecbd3c88fd0d8b19112e33049564e25ac5fc39
diff --git a/plugins/singleusergroup b/plugins/singleusergroup
index d04c4c3..9eb6334 160000
--- a/plugins/singleusergroup
+++ b/plugins/singleusergroup
@@ -1 +1 @@
-Subproject commit d04c4c33ad36e2e11ccc8b798357dd1e4e979a1a
+Subproject commit 9eb63345a129533aa88235af3ba9308c53cee1d2
diff --git a/plugins/yarn.lock b/plugins/yarn.lock
new file mode 100644
index 0000000..a63f96e
--- /dev/null
+++ b/plugins/yarn.lock
@@ -0,0 +1,3 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+# This is an empty placeholder
\ No newline at end of file
diff --git a/polygerrit-ui/Polymer3.md b/polygerrit-ui/Polymer3.md
index 94750d8..186f0f4 100644
--- a/polygerrit-ui/Polymer3.md
+++ b/polygerrit-ui/Polymer3.md
@@ -14,6 +14,11 @@
To get inspirations, check out our [samples here](https://gerrit.googlesource.com/gerrit/+/master/polygerrit-ui/app/samples).
+### Plugin dependencies
+
+Since most of Gerrit plugins are treated as sub modules and part of the Gerrit workspace when develop, dependencies of plugins are also defined and installed from Gerrit WORKSPACE, currently most of them are `bower_archives`. When moving to npm, if your plugin requires dependencies, you can have them added to your plugin's `package.json` and then link that file to `plugins/package.json` in gerrit.
+Then use `@plugins_npm//:node_modules` to make sure `rollup_bundle` knows the right place to look for. More examples from `image-diff` plugin, [change 271672](https://gerrit-review.googlesource.com/c/plugins/image-diff/+/271672).
+
### Related resources
- [Polymer 3.0 upgrade guide](https://polymer-library.polymer-project.org/3.0/docs/upgrade)
diff --git a/polygerrit-ui/README.md b/polygerrit-ui/README.md
index 29ba857..545c238 100644
--- a/polygerrit-ui/README.md
+++ b/polygerrit-ui/README.md
@@ -148,160 +148,30 @@
## Running Tests
For daily development you typically only want to run and debug individual tests.
-There are 2 types of fronted tests in gerrit:
-- Karma tests - all tests matches `*_test.js` pattern
-- web-component-tester(WCT) tests - all tests matches the `*_test.html` pattern.
+There are several ways to run tests.
-**Note:** WCT tests are deprecated. We are migrating to Karma tests now. If you are going to change
-something in a WCT test file, we strongly recommend to convert it to Karma tests before making
-any change. See [Converting WCT tests to Karma](#wct-to-karma).
-
-Our CI integration ensures that all tests are run when you upload a change to
-Gerrit, but you can also run all tests locally in headless mode:
-
+* Run all tests in headless mode:
```sh
-npm test
+npm run test
```
-### Running Karma tests
-There are several ways to run Karma tests:
-
-* Run all Karma tests in headless mode:
-```sh
-npm run test:karma
-```
-
-* Run all Karma tests in debug mode (the command opens Chrome browser with
+* Run all tests in debug mode (the command opens Chrome browser with
the default Karma page; you should click the "Debug" button to start testing):
```sh
-npm run test:karma:debug
+npm run test:debug
```
* Run a single test file:
```
# Headless mode
-npm run test:karma async-foreach-behavior_test.js
+npm run test:single async-foreach-behavior_test.js
# Debug mode
-npm run test:karma:debug async-foreach-behavior_test.js
+npm run test:debug async-foreach-behavior_test.js
```
* You can run tests in IDE:
- [IntelliJ: running unit tests on Karma](https://www.jetbrains.com/help/idea/running-unit-tests-on-karma.html#ws_karma_running)
-### Running WCT tests
-
-Run the local [Go proxy server](#go-server) and navigate for example to
-<http://localhost:8081/elements/shared/gr-account-entry/gr-account-entry_test.html>.
-Check "Disable cache" in the "Network" tab of Chrome's dev tools, so code
-changes are picked up on "reload".
-
-You can also run all WCT tests locally in headless mode:
-
-```sh
-npm test:wct
-```
-
-To allow the tests to run in Safari:
-
-* In the Advanced preferences tab, check "Show Develop menu in menu bar".
-* In the Develop menu, enable the "Allow Remote Automation" option.
-
-To run Chrome tests in headless mode:
-
-```sh
-WCT_HEADLESS_MODE=1 WCT_ARGS='--verbose -l chrome' ./polygerrit-ui/app/run_test.sh
-```
-
-### <a name="wct-to-karma"></a>Converting WCT tests to Karma
-
-If you are want to change a WCT test file (any `..._test.html` file), please convert the file to a
-Karma test file before making any changes. It is better to make a conversion in a separate change,
-so any conversion-related problems can be catch at this step.
-
-Usually, our WCT tests files have the following structure:
-```Html
-<!-- Test header: meta, title, wct scripts -->
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-account-link</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<!-- Templates for test fixtures (optional) -->
-<test-fixture id="basic">
- <template>
- <gr-account-link></gr-account-link>
- </template>
- </test-fixture>
-
-<test-fixture id="other">
- <template>
- <gr-dialog>
- <span>Hello!</span>
- </gr-dialog>
- </template>
- </test-fixture>
-
-<!-- Tests -->
-<script type="module">
-// One or more imports:
-import '../../../test/common-test-setup.js';
-import ...;
-
-// Tests - one or more suites
-suite(..., () => {
- ...
- // instantiate 'basic' template:
- element = fixture('basic');
-
- ...
- // instantiate 'other' template:
- otherElements = fixture('other');
-
-);
-</script>
-```
-
-A conversion requires the following changes:
-* Rename the `..._test.html` file to the `..._test.js` file.
-* Remove test header (see a WCT test example above)
-* Remove all `<script...>` and `</script>` tags, but preserve javascript code
-* Change imports - use `test/common-test-setup-karma.js` instead of `test/common-test-setup.js`.
-Ensure, that the `common-test-setup-karma.js` import is placed above any other imports.
-* If there are test fixtures in the html file, move them inside a `<script>` tag and use
-the `fixtureFromTemplate` or `fixtureFromElement` (if there is only one element in a template)
-to define a test fixture template.
-* Use `instantiate` method instead of `fixture` method.
-
-After conversion, the Karma test file for the example above can look like:
-```Javascript
-import '../../../test/common-test-setup-karma.js';
-// Other imports:
-import ...
-
-// Define test fixtures templates:
-const fixture =
- fixtureFromElement('gr-account-link');
-const otherFixture = fixtureFromTemplate(html`<gr-dialog>
- <span>Hello!</span>
-</gr-dialog>
-`);
-
-// Tests - one or more suites
-suite(..., () => {
- ...
- // instantiate 'basic' template:
- element = fixture.instantiate();
-
- ...
- // instantiate 'other' template:
- otherElements = otherFixture.instantiate();
-
-);
-```
-
## Style guide
We follow the [Google JavaScript Style Guide](https://google.github.io/styleguide/javascriptguide.xml)
diff --git a/polygerrit-ui/app/.eslintrc.js b/polygerrit-ui/app/.eslintrc.js
index e7506e0..8aa6e5f 100644
--- a/polygerrit-ui/app/.eslintrc.js
+++ b/polygerrit-ui/app/.eslintrc.js
@@ -206,6 +206,7 @@
"stub": "readonly",
"suite": "readonly",
"suiteSetup": "readonly",
+ "suiteTeardown": "readonly",
"teardown": "readonly",
"test": "readonly",
"fixtureFromElement": "readonly",
@@ -219,7 +220,7 @@
}
},
{
- "files": ["samples/**/*.js", "**/test/plugin.html"],
+ "files": ["samples/**/*.js"],
"globals": {
// Settings for samples. You can add globals here if you want to use it
"Gerrit": "readonly",
@@ -227,7 +228,7 @@
}
},
{
- "files": ["test/functional/**/*.js", "wct.conf.js", "template_test.js"],
+ "files": ["test/functional/**/*.js", "template_test.js"],
// Settings for functional tests. These scripts are node scripts.
// Turn off "no-undef" to allow any global variable
"env": {
@@ -240,12 +241,6 @@
}
},
{
- "files": "test/index.html",
- "globals": {
- "WCT": "readonly",
- }
- },
- {
"files": ["*_html.js", "gr-icons.js", "*-theme.js", "*-styles.js"],
"rules": {
"max-len": "off"
diff --git a/polygerrit-ui/app/BUILD b/polygerrit-ui/app/BUILD
index 096c665..88e0834 100644
--- a/polygerrit-ui/app/BUILD
+++ b/polygerrit-ui/app/BUILD
@@ -1,4 +1,4 @@
-load(":rules.bzl", "polygerrit_bundle", "wct_suite")
+load(":rules.bzl", "polygerrit_bundle")
load("//tools/js:eslint.bzl", "eslint")
package(default_visibility = ["//visibility:public"])
@@ -18,7 +18,7 @@
],
),
outs = ["polygerrit_ui.zip"],
- entry_point = "elements/gr-app.html",
+ entry_point = "elements/gr-app.js",
)
filegroup(
@@ -45,7 +45,6 @@
exclude = [
"node_modules/**",
"node_modules_licenses/**",
- "**/*_test.html",
"test/**",
"samples/**",
"**/*_test.js",
@@ -59,19 +58,12 @@
srcs = [
"test/common-test-setup.js",
"test/common-test-setup-karma.js",
- "test/index.html",
":pg_code",
"@ui_dev_npm//:node_modules",
"@ui_npm//:node_modules",
],
)
-wct_suite(
- name = "wct",
- srcs = [":test-srcs-fg"],
- split_count = 4,
-)
-
# Define the eslinter for polygerrit-ui app
# The eslint macro creates 2 rules: lint_test and lint_bin
eslint(
diff --git a/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior_test.html b/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior_test.html
deleted file mode 100644
index 61d7bac..0000000
--- a/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior_test.html
+++ /dev/null
@@ -1,74 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>base-url-behavior</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<script type="module">
-import '../../test/common-test-setup.js';
-/** @type {string} */
-window.CANONICAL_PATH = '/r';
-</script>
-<test-fixture id="basic">
- <template>
- <test-element></test-element>
- </template>
-</test-fixture>
-
-<test-fixture id="within-overlay">
- <template>
- <gr-overlay>
- <test-element></test-element>
- </gr-overlay>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../test/common-test-setup.js';
-import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
-import {BaseUrlBehavior} from './base-url-behavior.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: [
- BaseUrlBehavior,
- ],
- });
- });
-
- setup(() => {
- element = fixture('basic');
- overlay = fixture('within-overlay');
- });
-
- test('getBaseUrl', () => {
- assert.deepEqual(element.getBaseUrl(), '/r');
- });
-});
-</script>
diff --git a/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior_test.js b/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior_test.js
new file mode 100644
index 0000000..3b8a9cb
--- /dev/null
+++ b/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior_test.js
@@ -0,0 +1,51 @@
+/**
+ * @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 '../../test/common-test-setup-karma.js';
+import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
+import {BaseUrlBehavior} from './base-url-behavior.js';
+
+const basicFixture = fixtureFromElement('base-url-behavior-test-element');
+
+suite('base-url-behavior tests', () => {
+ let element;
+ let originialCanonicalPath;
+
+ suiteSetup(() => {
+ originialCanonicalPath = window.CANONICAL_PATH;
+ window.CANONICAL_PATH = '/r';
+ // Define a Polymer element that uses this behavior.
+ Polymer({
+ is: 'base-url-behavior-test-element',
+ behaviors: [
+ BaseUrlBehavior,
+ ],
+ });
+ });
+
+ suiteTeardown(() => {
+ window.CANONICAL_PATH = originialCanonicalPath;
+ });
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ test('getBaseUrl', () => {
+ assert.deepEqual(element.getBaseUrl(), '/r');
+ });
+});
diff --git a/polygerrit-ui/app/behaviors/docs-url-behavior/docs-url-behavior_test.html b/polygerrit-ui/app/behaviors/docs-url-behavior/docs-url-behavior_test.js
similarity index 62%
rename from polygerrit-ui/app/behaviors/docs-url-behavior/docs-url-behavior_test.html
rename to polygerrit-ui/app/behaviors/docs-url-behavior/docs-url-behavior_test.js
index 0efd80f..93beb52 100644
--- a/polygerrit-ui/app/behaviors/docs-url-behavior/docs-url-behavior_test.html
+++ b/polygerrit-ui/app/behaviors/docs-url-behavior/docs-url-behavior_test.js
@@ -1,36 +1,26 @@
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<!-- Polymer included for the html import polyfill. -->
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<title>docs-url-behavior</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<test-fixture id="basic">
- <template>
- <docs-url-behavior-element></docs-url-behavior-element>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../test/common-test-setup.js';
+import '../../test/common-test-setup-karma.js';
import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
import {DocsUrlBehavior} from './docs-url-behavior.js';
+
+const basicFixture = fixtureFromElement('docs-url-behavior-element');
+
suite('docs-url-behavior tests', () => {
let element;
@@ -43,7 +33,7 @@
});
setup(() => {
- element = fixture('basic');
+ element = basicFixture.instantiate();
element._clearDocsBaseUrlCache();
});
@@ -96,4 +86,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/behaviors/dom-util-behavior/dom-util-behavior_test.html b/polygerrit-ui/app/behaviors/dom-util-behavior/dom-util-behavior_test.html
deleted file mode 100644
index 1e842c1..0000000
--- a/polygerrit-ui/app/behaviors/dom-util-behavior/dom-util-behavior_test.html
+++ /dev/null
@@ -1,72 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>dom-util-behavior</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<test-fixture id="nested-structure">
- <template>
- <test-element></test-element>
- <div>
- <div class="a">
- <div class="b">
- <div class="c"></div>
- </div>
- </div>
- </div>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../test/common-test-setup.js';
-import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
-import {DomUtilBehavior} from './dom-util-behavior.js';
-suite('dom-util-behavior tests', () => {
- let element;
- let divs;
-
- suiteSetup(() => {
- // Define a Polymer element that uses this behavior.
- Polymer({
- is: 'test-element',
- behaviors: [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>
diff --git a/polygerrit-ui/app/behaviors/dom-util-behavior/dom-util-behavior_test.js b/polygerrit-ui/app/behaviors/dom-util-behavior/dom-util-behavior_test.js
new file mode 100644
index 0000000..c110b34
--- /dev/null
+++ b/polygerrit-ui/app/behaviors/dom-util-behavior/dom-util-behavior_test.js
@@ -0,0 +1,62 @@
+/**
+ * @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.
+ */
+
+import '../../test/common-test-setup-karma.js';
+import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
+import {DomUtilBehavior} from './dom-util-behavior.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const nestedStructureFixture = fixtureFromTemplate(html`
+ <dom-util-behavior-test-element></dom-util-behavior-test-element>
+ <div>
+ <div class="a">
+ <div class="b">
+ <div class="c"></div>
+ </div>
+ </div>
+ </div>
+`);
+
+suite('dom-util-behavior tests', () => {
+ let element;
+ let divs;
+
+ suiteSetup(() => {
+ // Define a Polymer element that uses this behavior.
+ Polymer({
+ is: 'dom-util-behavior-test-element',
+ behaviors: [DomUtilBehavior],
+ });
+ });
+
+ setup(() => {
+ const testDom = nestedStructureFixture.instantiate();
+ 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')));
+ });
+});
+
diff --git a/polygerrit-ui/app/behaviors/gr-access-behavior/gr-access-behavior_test.html b/polygerrit-ui/app/behaviors/gr-access-behavior/gr-access-behavior_test.html
deleted file mode 100644
index c5f3f94..0000000
--- a/polygerrit-ui/app/behaviors/gr-access-behavior/gr-access-behavior_test.html
+++ /dev/null
@@ -1,72 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>keyboard-shortcut-behavior</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<test-fixture id="basic">
- <template>
- <test-element></test-element>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../test/common-test-setup.js';
-import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
-import {AccessBehavior} from './gr-access-behavior.js';
-suite('gr-access-behavior tests', () => {
- let element;
-
- suiteSetup(() => {
- // Define a Polymer element that uses this behavior.
- Polymer({
- is: 'test-element',
- behaviors: [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>
diff --git a/polygerrit-ui/app/behaviors/gr-access-behavior/gr-access-behavior_test.js b/polygerrit-ui/app/behaviors/gr-access-behavior/gr-access-behavior_test.js
new file mode 100644
index 0000000..b29505f
--- /dev/null
+++ b/polygerrit-ui/app/behaviors/gr-access-behavior/gr-access-behavior_test.js
@@ -0,0 +1,59 @@
+/**
+ * @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 '../../test/common-test-setup-karma.js';
+import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
+import {AccessBehavior} from './gr-access-behavior.js';
+
+const basicFixture = fixtureFromElement('gr-access-behavior-test-element');
+
+suite('gr-access-behavior tests', () => {
+ let element;
+
+ suiteSetup(() => {
+ // Define a Polymer element that uses this behavior.
+ Polymer({
+ is: 'gr-access-behavior-test-element',
+ behaviors: [AccessBehavior],
+ });
+ });
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ 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);
+ });
+});
+
diff --git a/polygerrit-ui/app/behaviors/gr-admin-nav-behavior/gr-admin-nav-behavior_test.html b/polygerrit-ui/app/behaviors/gr-admin-nav-behavior/gr-admin-nav-behavior_test.js
similarity index 86%
rename from polygerrit-ui/app/behaviors/gr-admin-nav-behavior/gr-admin-nav-behavior_test.html
rename to polygerrit-ui/app/behaviors/gr-admin-nav-behavior/gr-admin-nav-behavior_test.js
index 3f58499..72109f2 100644
--- a/polygerrit-ui/app/behaviors/gr-admin-nav-behavior/gr-admin-nav-behavior_test.html
+++ b/polygerrit-ui/app/behaviors/gr-admin-nav-behavior/gr-admin-nav-behavior_test.js
@@ -1,49 +1,35 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2018 The Android Open Source Project
+/**
+ * @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.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>keyboard-shortcut-behavior</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<test-fixture id="basic">
- <template>
- <test-element></test-element>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../test/common-test-setup.js';
+import '../../test/common-test-setup-karma.js';
import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
import {AdminNavBehavior} from './gr-admin-nav-behavior.js';
+
+const basicFixture = fixtureFromElement('gr-admin-nav-behavior-test-element');
+
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',
+ is: 'gr-admin-nav-behavior-test-element',
behaviors: [
AdminNavBehavior,
],
@@ -51,16 +37,11 @@
});
setup(() => {
- element = fixture('basic');
- sandbox = sinon.sandbox.create();
+ element = basicFixture.instantiate();
capabilityStub = sinon.stub();
menuLinkStub = sinon.stub().returns([]);
});
- teardown(() => {
- sandbox.restore();
- });
-
const testAdminLinks = (account, options, expected, done) => {
element.getAdminLinks(account,
capabilityStub,
@@ -366,4 +347,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/behaviors/gr-change-table-behavior/gr-change-table-behavior.js b/polygerrit-ui/app/behaviors/gr-change-table-behavior/gr-change-table-behavior.js
index 6c469a5..7feaf79 100644
--- a/polygerrit-ui/app/behaviors/gr-change-table-behavior/gr-change-table-behavior.js
+++ b/polygerrit-ui/app/behaviors/gr-change-table-behavior/gr-change-table-behavior.js
@@ -52,7 +52,7 @@
* @return {boolean}
*/
isColumnHidden(columnToCheck, columnsToDisplay) {
- if ([columnsToDisplay, columnToCheck].some(arg => arg === undefined)) {
+ if ([columnsToDisplay, columnToCheck].includes(undefined)) {
return false;
}
return !columnsToDisplay.includes(columnToCheck);
diff --git a/polygerrit-ui/app/behaviors/gr-change-table-behavior/gr-change-table-behavior_test.html b/polygerrit-ui/app/behaviors/gr-change-table-behavior/gr-change-table-behavior_test.html
deleted file mode 100644
index 3c5aedd..0000000
--- a/polygerrit-ui/app/behaviors/gr-change-table-behavior/gr-change-table-behavior_test.html
+++ /dev/null
@@ -1,130 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>keyboard-shortcut-behavior</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<test-fixture id="basic">
- <template>
- <test-element></test-element>
- </template>
-</test-fixture>
-
-<test-fixture id="within-overlay">
- <template>
- <gr-overlay>
- <test-element></test-element>
- </gr-overlay>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../test/common-test-setup.js';
-import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
-import {ChangeTableBehavior} from './gr-change-table-behavior.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: [ChangeTableBehavior],
- });
- });
-
- setup(() => {
- element = fixture('basic');
- overlay = fixture('within-overlay');
- });
-
- test('getComplementColumns', () => {
- let columns = [
- 'Subject',
- 'Status',
- 'Owner',
- 'Assignee',
- 'Reviewers',
- 'Comments',
- 'Repo',
- 'Branch',
- 'Updated',
- 'Size',
- ];
- assert.deepEqual(element.getComplementColumns(columns), []);
-
- columns = [
- 'Subject',
- 'Status',
- 'Assignee',
- 'Reviewers',
- 'Comments',
- '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>
diff --git a/polygerrit-ui/app/behaviors/gr-change-table-behavior/gr-change-table-behavior_test.js b/polygerrit-ui/app/behaviors/gr-change-table-behavior/gr-change-table-behavior_test.js
new file mode 100644
index 0000000..dfca358
--- /dev/null
+++ b/polygerrit-ui/app/behaviors/gr-change-table-behavior/gr-change-table-behavior_test.js
@@ -0,0 +1,118 @@
+/**
+ * @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 '../../test/common-test-setup-karma.js';
+import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
+import {ChangeTableBehavior} from './gr-change-table-behavior.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const basicFixture = fixtureFromElement(
+ 'gr-change-table-behavior-test-element');
+
+const withinOverlayFixture = fixtureFromTemplate(html`
+ <gr-overlay>
+ <gr-change-table-behavior-test-element>
+ </gr-change-table-behavior-test-element>
+ </gr-overlay>
+`);
+
+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: 'gr-change-table-behavior-test-element',
+ behaviors: [ChangeTableBehavior],
+ });
+ });
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ overlay = withinOverlayFixture.instantiate();
+ });
+
+ test('getComplementColumns', () => {
+ let columns = [
+ 'Subject',
+ 'Status',
+ 'Owner',
+ 'Assignee',
+ 'Reviewers',
+ 'Comments',
+ 'Repo',
+ 'Branch',
+ 'Updated',
+ 'Size',
+ ];
+ assert.deepEqual(element.getComplementColumns(columns), []);
+
+ columns = [
+ 'Subject',
+ 'Status',
+ 'Assignee',
+ 'Reviewers',
+ 'Comments',
+ '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']));
+ });
+});
+
diff --git a/polygerrit-ui/app/behaviors/gr-display-name-behavior/gr-display-name-behavior_test.html b/polygerrit-ui/app/behaviors/gr-display-name-behavior/gr-display-name-behavior_test.html
deleted file mode 100644
index fa72c40..0000000
--- a/polygerrit-ui/app/behaviors/gr-display-name-behavior/gr-display-name-behavior_test.html
+++ /dev/null
@@ -1,100 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-display-name-behavior</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<test-fixture id="basic">
- <template>
- <test-element-anon></test-element-anon>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../test/common-test-setup.js';
-import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
-import {DisplayNameBehavior} from './gr-display-name-behavior.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: [
- DisplayNameBehavior,
- ],
- });
- });
-
- setup(() => {
- element = fixture('basic');
- });
-
- test('getUserName name only', () => {
- const account = {
- name: 'test-name',
- };
- assert.equal(element.getUserName(config, account), 'test-name');
- });
-
- test('getUserName username only', () => {
- const account = {
- username: 'test-user',
- };
- assert.equal(element.getUserName(config, account), 'test-user');
- });
-
- test('getUserName email only', () => {
- const account = {
- email: 'test-user@test-url.com',
- };
- assert.equal(element.getUserName(config, account),
- 'test-user@test-url.com');
- });
-
- test('getUserName returns not Anonymous Coward as the anon name', () => {
- assert.equal(element.getUserName(config, null), 'Anonymous');
- });
-
- test('getUserName for the config returning the anon name', () => {
- const config = {
- user: {
- anonymous_coward_name: 'Test Anon',
- },
- };
- assert.equal(element.getUserName(config, null), 'Test Anon');
- });
-
- test('getGroupDisplayName', () => {
- assert.equal(element.getGroupDisplayName({name: 'Some user name'}),
- 'Some user name (group)');
- });
-});
-</script>
diff --git a/polygerrit-ui/app/behaviors/gr-display-name-behavior/gr-display-name-behavior_test.js b/polygerrit-ui/app/behaviors/gr-display-name-behavior/gr-display-name-behavior_test.js
new file mode 100644
index 0000000..82108429
--- /dev/null
+++ b/polygerrit-ui/app/behaviors/gr-display-name-behavior/gr-display-name-behavior_test.js
@@ -0,0 +1,87 @@
+/**
+ * @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 '../../test/common-test-setup-karma.js';
+import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
+import {DisplayNameBehavior} from './gr-display-name-behavior.js';
+
+const basicFixture = fixtureFromElement('test-element-anon');
+
+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: [
+ DisplayNameBehavior,
+ ],
+ });
+ });
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ test('getUserName name only', () => {
+ const account = {
+ name: 'test-name',
+ };
+ assert.equal(element.getUserName(config, account), 'test-name');
+ });
+
+ test('getUserName username only', () => {
+ const account = {
+ username: 'test-user',
+ };
+ assert.equal(element.getUserName(config, account), 'test-user');
+ });
+
+ test('getUserName email only', () => {
+ const account = {
+ email: 'test-user@test-url.com',
+ };
+ assert.equal(element.getUserName(config, account),
+ 'test-user@test-url.com');
+ });
+
+ test('getUserName returns not Anonymous Coward as the anon name', () => {
+ assert.equal(element.getUserName(config, null), 'Anonymous');
+ });
+
+ test('getUserName for the config returning the anon name', () => {
+ const config = {
+ user: {
+ anonymous_coward_name: 'Test Anon',
+ },
+ };
+ assert.equal(element.getUserName(config, null), 'Test Anon');
+ });
+
+ test('getGroupDisplayName', () => {
+ assert.equal(element.getGroupDisplayName({name: 'Some user name'}),
+ 'Some user name (group)');
+ });
+});
+
diff --git a/polygerrit-ui/app/behaviors/gr-list-view-behavior/gr-list-view-behavior_test.html b/polygerrit-ui/app/behaviors/gr-list-view-behavior/gr-list-view-behavior_test.html
deleted file mode 100644
index 80013bf..0000000
--- a/polygerrit-ui/app/behaviors/gr-list-view-behavior/gr-list-view-behavior_test.html
+++ /dev/null
@@ -1,93 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>keyboard-shortcut-behavior</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<test-fixture id="basic">
- <template>
- <test-element></test-element>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../test/common-test-setup.js';
-import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
-import {ListViewBehavior} from './gr-list-view-behavior.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: [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>
diff --git a/polygerrit-ui/app/behaviors/gr-list-view-behavior/gr-list-view-behavior_test.js b/polygerrit-ui/app/behaviors/gr-list-view-behavior/gr-list-view-behavior_test.js
new file mode 100644
index 0000000..bb54672
--- /dev/null
+++ b/polygerrit-ui/app/behaviors/gr-list-view-behavior/gr-list-view-behavior_test.js
@@ -0,0 +1,81 @@
+/**
+ * @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 '../../test/common-test-setup-karma.js';
+import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
+import {ListViewBehavior} from './gr-list-view-behavior.js';
+
+const basicFixture = fixtureFromElement(
+ 'gr-list-view-behavior-test-element');
+
+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: 'gr-list-view-behavior-test-element',
+ behaviors: [ListViewBehavior],
+ });
+ });
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ 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);
+ });
+});
+
diff --git a/polygerrit-ui/app/behaviors/gr-patch-set-behavior/gr-patch-set-behavior_test.html b/polygerrit-ui/app/behaviors/gr-patch-set-behavior/gr-patch-set-behavior_test.js
similarity index 89%
rename from polygerrit-ui/app/behaviors/gr-patch-set-behavior/gr-patch-set-behavior_test.html
rename to polygerrit-ui/app/behaviors/gr-patch-set-behavior/gr-patch-set-behavior_test.js
index f03e3ac..b14c0bd 100644
--- a/polygerrit-ui/app/behaviors/gr-patch-set-behavior/gr-patch-set-behavior_test.html
+++ b/polygerrit-ui/app/behaviors/gr-patch-set-behavior/gr-patch-set-behavior_test.js
@@ -1,28 +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.
+ */
-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.
--->
-<!-- Polymer included for the html import polyfill. -->
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<title>gr-patch-set-behavior</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script type="module">
-import '../../test/common-test-setup.js';
+import '../../test/common-test-setup-karma.js';
import {PatchSetBehavior} from './gr-patch-set-behavior.js';
suite('gr-patch-set-behavior tests', () => {
test('getRevisionByPatchNum', () => {
@@ -321,4 +314,4 @@
assert.equal(PatchSetBehavior.getParentIndex(-4), 4);
});
});
-</script>
+
diff --git a/polygerrit-ui/app/behaviors/gr-path-list-behavior/gr-path-list-behavior_test.html b/polygerrit-ui/app/behaviors/gr-path-list-behavior/gr-path-list-behavior_test.js
similarity index 74%
rename from polygerrit-ui/app/behaviors/gr-path-list-behavior/gr-path-list-behavior_test.html
rename to polygerrit-ui/app/behaviors/gr-path-list-behavior/gr-path-list-behavior_test.js
index cf5105e..94e82e2 100644
--- a/polygerrit-ui/app/behaviors/gr-path-list-behavior/gr-path-list-behavior_test.html
+++ b/polygerrit-ui/app/behaviors/gr-path-list-behavior/gr-path-list-behavior_test.js
@@ -1,28 +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.
+ */
-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.
--->
-<!-- Polymer included for the html import polyfill. -->
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<title>gr-path-list-behavior</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script type="module">
-import '../../test/common-test-setup.js';
+import '../../test/common-test-setup-karma.js';
import {PathListBehavior} from './gr-path-list-behavior.js';
import {SpecialFilePath} from '../../constants/constants.js';
@@ -113,4 +106,4 @@
assert.equal(shortenedPath, expectedPath);
});
});
-</script>
+
diff --git a/polygerrit-ui/app/behaviors/gr-tooltip-behavior/gr-tooltip-behavior_test.html b/polygerrit-ui/app/behaviors/gr-tooltip-behavior/gr-tooltip-behavior_test.js
similarity index 66%
rename from polygerrit-ui/app/behaviors/gr-tooltip-behavior/gr-tooltip-behavior_test.html
rename to polygerrit-ui/app/behaviors/gr-tooltip-behavior/gr-tooltip-behavior_test.js
index 79c515e..1f144a0 100644
--- a/polygerrit-ui/app/behaviors/gr-tooltip-behavior/gr-tooltip-behavior_test.html
+++ b/polygerrit-ui/app/behaviors/gr-tooltip-behavior/gr-tooltip-behavior_test.js
@@ -1,41 +1,28 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<title>tooltip-behavior</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <tooltip-behavior-element></tooltip-behavior-element>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../test/common-test-setup.js';
+import '../../test/common-test-setup-karma.js';
import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
import {TooltipBehavior} from './gr-tooltip-behavior.js';
+
+const basicFixture = fixtureFromElement('tooltip-behavior-element');
+
suite('gr-tooltip-behavior tests', () => {
let element;
- let sandbox;
function makeTooltip(tooltipRect, parentRect) {
return {
@@ -57,16 +44,11 @@
});
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- });
-
- teardown(() => {
- sandbox.restore();
+ element = basicFixture.instantiate();
});
test('normal position', () => {
- sandbox.stub(element, 'getBoundingClientRect', () => {
+ sinon.stub(element, 'getBoundingClientRect').callsFake(() => {
return {top: 100, left: 100, width: 200};
});
const tooltip = makeTooltip(
@@ -80,7 +62,7 @@
});
test('left side position', () => {
- sandbox.stub(element, 'getBoundingClientRect', () => {
+ sinon.stub(element, 'getBoundingClientRect').callsFake(() => {
return {top: 100, left: 10, width: 50};
});
const tooltip = makeTooltip(
@@ -97,7 +79,7 @@
});
test('right side position', () => {
- sandbox.stub(element, 'getBoundingClientRect', () => {
+ sinon.stub(element, 'getBoundingClientRect').callsFake(() => {
return {top: 100, left: 950, width: 50};
});
const tooltip = makeTooltip(
@@ -114,7 +96,7 @@
});
test('position to bottom', () => {
- sandbox.stub(element, 'getBoundingClientRect', () => {
+ sinon.stub(element, 'getBoundingClientRect').callsFake(() => {
return {top: 100, left: 950, width: 50, height: 50};
});
const tooltip = makeTooltip(
@@ -132,23 +114,23 @@
});
test('hides tooltip when detached', () => {
- sandbox.stub(element, '_handleHideTooltip');
+ sinon.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');
+ const addListenerStub = sinon.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');
+ const removeListenerStub = sinon.stub(element, 'removeEventListener');
element.hasTooltip = true;
element.hasTooltip = false;
assert.isTrue(removeListenerStub.called);
});
});
-</script>
+
diff --git a/polygerrit-ui/app/behaviors/gr-url-encoding-behavior/gr-url-encoding-behavior_test.html b/polygerrit-ui/app/behaviors/gr-url-encoding-behavior/gr-url-encoding-behavior_test.html
deleted file mode 100644
index d0a2cde..0000000
--- a/polygerrit-ui/app/behaviors/gr-url-encoding-behavior/gr-url-encoding-behavior_test.html
+++ /dev/null
@@ -1,92 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<title>gr-url-encoding-behavior</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <test-element></test-element>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../test/common-test-setup.js';
-import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
-import {URLEncodingBehavior} from './gr-url-encoding-behavior.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: [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>
diff --git a/polygerrit-ui/app/behaviors/gr-url-encoding-behavior/gr-url-encoding-behavior_test.js b/polygerrit-ui/app/behaviors/gr-url-encoding-behavior/gr-url-encoding-behavior_test.js
new file mode 100644
index 0000000..1fe2874
--- /dev/null
+++ b/polygerrit-ui/app/behaviors/gr-url-encoding-behavior/gr-url-encoding-behavior_test.js
@@ -0,0 +1,75 @@
+/**
+ * @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.
+ */
+
+import '../../test/common-test-setup-karma.js';
+import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
+import {URLEncodingBehavior} from './gr-url-encoding-behavior.js';
+
+const basicFixture =
+ fixtureFromElement('gr-url-encoding-behavior-test-element');
+
+suite('gr-url-encoding-behavior tests', () => {
+ let element;
+
+ suiteSetup(() => {
+ // Define a Polymer element that uses this behavior.
+ Polymer({
+ is: 'gr-url-encoding-behavior-test-element',
+ behaviors: [URLEncodingBehavior],
+ });
+ });
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ 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');
+ });
+ });
+});
+
diff --git a/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.js b/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.js
index ca31ee8..2db1c09 100644
--- a/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.js
+++ b/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.js
@@ -101,11 +101,14 @@
const DOC_ONLY = 'DOC_ONLY';
const GO_KEY = 'GO_KEY';
+const V_KEY = 'V_KEY';
// The maximum age of a keydown event to be used in a jump navigation. This
// is only for cases when the keyup event is lost.
const GO_KEY_TIMEOUT_MS = 1000;
+const V_KEY_TIMEOUT_MS = 1000;
+
const ShortcutSection = {
ACTIONS: 'Actions',
DIFFS: 'Diffs',
@@ -141,6 +144,11 @@
TOGGLE_DIFF_MODE: 'TOGGLE_DIFF_MODE',
REFRESH_CHANGE: 'REFRESH_CHANGE',
EDIT_TOPIC: 'EDIT_TOPIC',
+ DIFF_AGAINST_BASE: 'DIFF_AGAINST_BASE',
+ DIFF_AGAINST_LATEST: 'DIFF_AGAINST_LATEST',
+ DIFF_BASE_AGAINST_LEFT: 'DIFF_BASE_AGAINST_LEFT',
+ DIFF_RIGHT_AGAINST_LATEST: 'DIFF_RIGHT_AGAINST_LATEST',
+ DIFF_BASE_AGAINST_LATEST: 'DIFF_BASE_AGAINST_LATEST',
NEXT_LINE: 'NEXT_LINE',
PREV_LINE: 'PREV_LINE',
@@ -233,9 +241,29 @@
'Star/unstar change');
_describe(Shortcut.EDIT_TOPIC, ShortcutSection.ACTIONS,
'Add a change topic');
+_describe(Shortcut.DIFF_AGAINST_BASE, ShortcutSection.ACTIONS,
+ 'Diff against base');
+_describe(Shortcut.DIFF_AGAINST_LATEST, ShortcutSection.ACTIONS,
+ 'Diff against latest patchset');
+_describe(Shortcut.DIFF_BASE_AGAINST_LEFT, ShortcutSection.ACTIONS,
+ 'Diff base against left');
+_describe(Shortcut.DIFF_RIGHT_AGAINST_LATEST, ShortcutSection.ACTIONS,
+ 'Diff right against latest');
+_describe(Shortcut.DIFF_BASE_AGAINST_LATEST, ShortcutSection.ACTIONS,
+ 'Diff base against latest');
_describe(Shortcut.NEXT_LINE, ShortcutSection.DIFFS, 'Go to next line');
_describe(Shortcut.PREV_LINE, ShortcutSection.DIFFS, 'Go to previous line');
+_describe(Shortcut.DIFF_AGAINST_BASE, ShortcutSection.DIFFS,
+ 'Diff against base');
+_describe(Shortcut.DIFF_AGAINST_LATEST, ShortcutSection.DIFFS,
+ 'Diff against latest patchset');
+_describe(Shortcut.DIFF_BASE_AGAINST_LEFT, ShortcutSection.DIFFS,
+ 'Diff base against left');
+_describe(Shortcut.DIFF_RIGHT_AGAINST_LATEST, ShortcutSection.DIFFS,
+ 'Diff right against latest');
+_describe(Shortcut.DIFF_BASE_AGAINST_LATEST, ShortcutSection.DIFFS,
+ 'Diff base against latest');
_describe(Shortcut.VISIBLE_LINE, ShortcutSection.DIFFS,
'Move cursor to currently visible code');
_describe(Shortcut.NEXT_CHUNK, ShortcutSection.DIFFS,
@@ -435,39 +463,52 @@
const bindings = this.bindings.get(shortcut);
if (!bindings) { return null; }
if (bindings[0] === GO_KEY) {
- return [['g'].concat(bindings.slice(1))];
+ return bindings.slice(1).map(
+ binding => this._describeKey(binding)
+ )
+ .map(binding => ['g'].concat(binding));
+ }
+ if (bindings[0] === V_KEY) {
+ return bindings.slice(1).map(
+ binding => this._describeKey(binding)
+ )
+ .map(binding => ['v'].concat(binding));
}
return bindings
.filter(binding => binding !== DOC_ONLY)
.map(binding => this.describeBinding(binding));
}
+ _describeKey(key) {
+ switch (key) {
+ case 'shift':
+ return 'Shift';
+ case 'meta':
+ return 'Meta';
+ case 'ctrl':
+ return 'Ctrl';
+ case 'enter':
+ return 'Enter';
+ case 'up':
+ return '↑';
+ case 'down':
+ return '↓';
+ case 'left':
+ return '←';
+ case 'right':
+ return '→';
+ default:
+ return key;
+ }
+ }
+
describeBinding(binding) {
if (binding.length === 1) {
return [binding];
}
- return binding.split(':')[0].split('+').map(part => {
- switch (part) {
- case 'shift':
- return 'Shift';
- case 'meta':
- return 'Meta';
- case 'ctrl':
- return 'Ctrl';
- case 'enter':
- return 'Enter';
- case 'up':
- return '↑';
- case 'down':
- return '↓';
- case 'left':
- return '←';
- case 'right':
- return '→';
- default:
- return part;
- }
- });
+ return binding.split(':')[0].split('+').map(part =>
+ this._describeKey(part)
+ );
}
notifyListeners() {
@@ -489,6 +530,8 @@
// eslint-disable-next-line object-shorthand
GO_KEY: GO_KEY,
// eslint-disable-next-line object-shorthand
+ V_KEY: V_KEY,
+ // eslint-disable-next-line object-shorthand
Shortcut: Shortcut,
// eslint-disable-next-line object-shorthand
ShortcutSection: ShortcutSection,
@@ -498,16 +541,20 @@
type: Number,
value: null,
},
-
_shortcut_go_table: {
type: Array,
value() { return new Map(); },
},
+ _shortcut_v_table: {
+ type: Array,
+ value() { return new Map(); },
+ },
},
modifierPressed(e) {
e = getKeyboardEvent(e);
- return e.altKey || e.ctrlKey || e.metaKey || e.shiftKey;
+ return e.altKey || e.ctrlKey || e.metaKey || e.shiftKey ||
+ !!this._inGoKeyMode() || !!this._inVKeyMode();
},
isModifierPressed(e, modifier) {
@@ -565,7 +612,14 @@
return;
}
if (bindings[0] === GO_KEY) {
- this._shortcut_go_table.set(bindings[1], handler);
+ bindings.slice(1).forEach(binding =>
+ this._shortcut_go_table.set(binding, handler));
+ } else if (bindings[0] === V_KEY) {
+ // for each binding added with the go/v key, we set the handler to be
+ // handleVKeyAction. handleVKeyAction then looks up in th
+ // shortcut_table to see what the relevant handler should be
+ bindings.slice(1).forEach(binding =>
+ this._shortcut_v_table.set(binding, handler));
} else {
this.addOwnKeyBinding(bindings.join(' '), handler);
}
@@ -580,15 +634,26 @@
this._addOwnKeyBindings(key, shortcuts[key]);
}
+ // each component that uses this behaviour must be aware if go key is
+ // pressed or not, since it needs to check it as a modifier
+ this.addOwnKeyBinding('g:keydown', '_handleGoKeyDown');
+ this.addOwnKeyBinding('g:keyup', '_handleGoKeyUp');
+
// If any of the shortcuts utilized GO_KEY, then they are handled
// directly by this behavior.
if (this._shortcut_go_table.size > 0) {
- this.addOwnKeyBinding('g:keydown', '_handleGoKeyDown');
- this.addOwnKeyBinding('g:keyup', '_handleGoKeyUp');
this._shortcut_go_table.forEach((handler, key) => {
this.addOwnKeyBinding(key, '_handleGoAction');
});
}
+
+ this.addOwnKeyBinding('v:keydown', '_handleVKeyDown');
+ this.addOwnKeyBinding('v:keyup', '_handleVKeyUp');
+ if (this._shortcut_v_table.size > 0) {
+ this._shortcut_v_table.forEach((handler, key) => {
+ this.addOwnKeyBinding(key, '_handleVAction');
+ });
+ }
},
/** @override */
@@ -610,13 +675,43 @@
shortcutManager.removeListener(listener);
},
+ _handleVKeyDown(e) {
+ this._shortcut_v_key_last_pressed = Date.now();
+ },
+
+ _handleVKeyUp(e) {
+ setTimeout(() => {
+ this._shortcut_v_key_last_pressed = null;
+ }, V_KEY_TIMEOUT_MS);
+ },
+
+ _inVKeyMode() {
+ return this._shortcut_v_key_last_pressed &&
+ (Date.now() - this._shortcut_v_key_last_pressed <=
+ V_KEY_TIMEOUT_MS);
+ },
+
+ _handleVAction(e) {
+ if (!this._inVKeyMode() ||
+ !this._shortcut_v_table.has(e.detail.key) ||
+ this.shouldSuppressKeyboardShortcut(e)) {
+ return;
+ }
+ e.preventDefault();
+ const handler = this._shortcut_v_table.get(e.detail.key);
+ this[handler](e);
+ },
+
_handleGoKeyDown(e) {
- if (this.modifierPressed(e)) { return; }
this._shortcut_go_key_last_pressed = Date.now();
},
_handleGoKeyUp(e) {
- this._shortcut_go_key_last_pressed = null;
+ // Set go_key_last_pressed to null `GO_KEY_TIMEOUT_MS` after keyup event
+ // so that users can trigger `g + i` by pressing g and i quickly.
+ setTimeout(() => {
+ this._shortcut_go_key_last_pressed = null;
+ }, GO_KEY_TIMEOUT_MS);
},
_inGoKeyMode() {
@@ -641,6 +736,7 @@
export const KeyboardShortcutBinder = {
DOC_ONLY,
GO_KEY,
+ V_KEY,
Shortcut,
ShortcutManager,
ShortcutSection,
@@ -650,6 +746,10 @@
},
};
+export function _testOnly_getShortcutManagerInstance() {
+ return shortcutManager;
+}
+
// TODO(dmfilippov) Remove the following lines with assignments
// Plugins can use the behavior because it was accessible with
// the global Gerrit... variable. To avoid breaking changes in plugins
diff --git a/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior_test.html b/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior_test.js
similarity index 84%
rename from polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior_test.html
rename to polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior_test.js
index fcb7b4f..34cdf86 100644
--- a/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior_test.html
+++ b/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior_test.js
@@ -1,58 +1,45 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>keyboard-shortcut-behavior</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<test-fixture id="basic">
- <template>
- <test-element></test-element>
- </template>
-</test-fixture>
-
-<test-fixture id="within-overlay">
- <template>
- <gr-overlay>
- <test-element></test-element>
- </gr-overlay>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../test/common-test-setup.js';
+import '../../test/common-test-setup-karma.js';
import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
import {KeyboardShortcutBehavior, KeyboardShortcutBinder} from './keyboard-shortcut-behavior.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const basicFixture =
+ fixtureFromElement('keyboard-shortcut-behavior-test-element');
+
+const withinOverlayFixture = fixtureFromTemplate(html`
+<gr-overlay>
+ <keyboard-shortcut-behavior-test-element>
+ </keyboard-shortcut-behavior-test-element>
+</gr-overlay>
+`);
+
suite('keyboard-shortcut-behavior tests', () => {
const kb = KeyboardShortcutBinder;
let element;
let overlay;
- let sandbox;
suiteSetup(() => {
// Define a Polymer element that uses this behavior.
Polymer({
- is: 'test-element',
+ is: 'keyboard-shortcut-behavior-test-element',
behaviors: [KeyboardShortcutBehavior],
keyBindings: {
k: '_handleKey',
@@ -63,13 +50,8 @@
});
setup(() => {
- element = fixture('basic');
- overlay = fixture('within-overlay');
- sandbox = sinon.sandbox.create();
- });
-
- teardown(() => {
- sandbox.restore();
+ element = basicFixture.instantiate();
+ overlay = withinOverlayFixture.instantiate();
});
suite('ShortcutManager', () => {
@@ -294,7 +276,7 @@
});
});
- test('doesn’t block kb shortcuts for non-whitelisted els', done => {
+ test('doesn’t block kb shortcuts for non-allowed els', done => {
const divEl = document.createElement('div');
element.appendChild(divEl);
element._handleKey = e => {
@@ -326,7 +308,8 @@
test('blocks kb shortcuts for anything in a gr-overlay', done => {
const divEl = document.createElement('div');
- const element = overlay.querySelector('test-element');
+ const element =
+ overlay.querySelector('keyboard-shortcut-behavior-test-element');
element.appendChild(divEl);
element._handleKey = e => {
assert.isTrue(element.shouldSuppressKeyboardShortcut(e));
@@ -337,7 +320,8 @@
test('blocks enter shortcut on an anchor', done => {
const anchorEl = document.createElement('a');
- const element = overlay.querySelector('test-element');
+ const element =
+ overlay.querySelector('keyboard-shortcut-behavior-test-element');
element.appendChild(anchorEl);
element._handleKey = e => {
assert.isTrue(element.shouldSuppressKeyboardShortcut(e));
@@ -347,7 +331,7 @@
});
test('modifierPressed returns accurate values', () => {
- const spy = sandbox.spy(element, 'modifierPressed');
+ const spy = sinon.spy(element, 'modifierPressed');
element._handleKey = e => {
element.modifierPressed(e);
};
@@ -368,7 +352,7 @@
});
test('isModifierPressed returns accurate value', () => {
- const spy = sandbox.spy(element, 'isModifierPressed');
+ const spy = sinon.spy(element, 'isModifierPressed');
element._handleKey = e => {
element.isModifierPressed(e, 'shiftKey');
};
@@ -394,12 +378,12 @@
setup(() => {
element._shortcut_go_table.set('a', '_handleA');
handlerStub = element._handleA = sinon.stub();
- sandbox.stub(Date, 'now').returns(10000);
+ sinon.stub(Date, 'now').returns(10000);
});
test('success', () => {
const e = {detail: {key: 'a'}, preventDefault: () => {}};
- sandbox.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
+ sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
element._shortcut_go_key_last_pressed = 9000;
element._handleGoAction(e);
assert.isTrue(handlerStub.calledOnce);
@@ -408,7 +392,7 @@
test('go key not pressed', () => {
const e = {detail: {key: 'a'}, preventDefault: () => {}};
- sandbox.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
+ sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
element._shortcut_go_key_last_pressed = null;
element._handleGoAction(e);
assert.isFalse(handlerStub.called);
@@ -416,7 +400,7 @@
test('go key pressed too long ago', () => {
const e = {detail: {key: 'a'}, preventDefault: () => {}};
- sandbox.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
+ sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
element._shortcut_go_key_last_pressed = 3000;
element._handleGoAction(e);
assert.isFalse(handlerStub.called);
@@ -424,7 +408,7 @@
test('should suppress', () => {
const e = {detail: {key: 'a'}, preventDefault: () => {}};
- sandbox.stub(element, 'shouldSuppressKeyboardShortcut').returns(true);
+ sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(true);
element._shortcut_go_key_last_pressed = 9000;
element._handleGoAction(e);
assert.isFalse(handlerStub.called);
@@ -432,11 +416,11 @@
test('unrecognized key', () => {
const e = {detail: {key: 'f'}, preventDefault: () => {}};
- sandbox.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
+ sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
element._shortcut_go_key_last_pressed = 9000;
element._handleGoAction(e);
assert.isFalse(handlerStub.called);
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/behaviors/rest-client-behavior/rest-client-behavior_test.html b/polygerrit-ui/app/behaviors/rest-client-behavior/rest-client-behavior_test.js
similarity index 77%
rename from polygerrit-ui/app/behaviors/rest-client-behavior/rest-client-behavior_test.html
rename to polygerrit-ui/app/behaviors/rest-client-behavior/rest-client-behavior_test.js
index 980bc8f..8f63a25 100644
--- a/polygerrit-ui/app/behaviors/rest-client-behavior/rest-client-behavior_test.html
+++ b/polygerrit-ui/app/behaviors/rest-client-behavior/rest-client-behavior_test.js
@@ -1,63 +1,46 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>keyboard-shortcut-behavior</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<script type="module">
-import '../../test/common-test-setup.js';
-/** @type {string} */
-window.CANONICAL_PATH = '/r';
-</script>
-
-<test-fixture id="basic">
- <template>
- <test-element></test-element>
- </template>
-</test-fixture>
-
-<test-fixture id="within-overlay">
- <template>
- <gr-overlay>
- <test-element></test-element>
- </gr-overlay>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../test/common-test-setup.js';
+import '../../test/common-test-setup-karma.js';
import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
import {BaseUrlBehavior} from '../base-url-behavior/base-url-behavior.js';
import {RESTClientBehavior} from './rest-client-behavior.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const basicFixture = fixtureFromElement('rest-client-behavior-test-element');
+
+const withinOverlayFixture = fixtureFromTemplate(html`
+<gr-overlay>
+ <rest-client-behavior-test-element></rest-client-behavior-test-element>
+</gr-overlay>
+`);
+
suite('rest-client-behavior tests', () => {
let element;
// eslint-disable-next-line no-unused-vars
let overlay;
+ let originalCanonicalPath;
suiteSetup(() => {
+ originalCanonicalPath = window.CANONICAL_PATH;
+ window.CANONICAL_PATH = '/r';
// Define a Polymer element that uses this behavior.
Polymer({
- is: 'test-element',
+ is: 'rest-client-behavior-test-element',
behaviors: [
BaseUrlBehavior,
RESTClientBehavior,
@@ -65,9 +48,13 @@
});
});
+ suiteTeardown(() => {
+ window.CANONICAL_PATH = originalCanonicalPath;
+ });
+
setup(() => {
- element = fixture('basic');
- overlay = fixture('within-overlay');
+ element = basicFixture.instantiate();
+ overlay = withinOverlayFixture.instantiate();
});
test('changeBaseURL', () => {
@@ -234,4 +221,4 @@
assert.equal(statusString, 'Merge Conflict, WIP, Private');
});
});
-</script>
+
diff --git a/polygerrit-ui/app/behaviors/safe-types-behavior/safe-types-behavior_test.html b/polygerrit-ui/app/behaviors/safe-types-behavior/safe-types-behavior_test.js
similarity index 64%
rename from polygerrit-ui/app/behaviors/safe-types-behavior/safe-types-behavior_test.html
rename to polygerrit-ui/app/behaviors/safe-types-behavior/safe-types-behavior_test.js
index 6fe4460..0e0ff2e 100644
--- a/polygerrit-ui/app/behaviors/safe-types-behavior/safe-types-behavior_test.html
+++ b/polygerrit-ui/app/behaviors/safe-types-behavior/safe-types-behavior_test.js
@@ -1,41 +1,28 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2018 The Android Open Source Project
+/**
+ * @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.
+ */
-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.
--->
-
-<title>safe-types-behavior</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <safe-types-element></safe-types-element>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../test/common-test-setup.js';
+import '../../test/common-test-setup-karma.js';
import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
import {SafeTypes} from './safe-types-behavior.js';
+
+const basicFixture = fixtureFromElement('safe-types-element');
+
suite('gr-tooltip-behavior tests', () => {
let element;
- let sandbox;
suiteSetup(() => {
Polymer({
@@ -45,12 +32,7 @@
});
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- });
-
- teardown(() => {
- sandbox.restore();
+ element = basicFixture.instantiate();
});
test('SafeUrl accepts valid urls', () => {
@@ -119,4 +101,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section_test.js b/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section_test.js
index 2128e29..2d7096f 100644
--- a/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section_test.js
+++ b/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section_test.js
@@ -22,17 +22,11 @@
suite('gr-access-section tests', () => {
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
element = fixture.instantiate();
});
- teardown(() => {
- sandbox.restore();
- });
-
suite('unit tests', () => {
setup(() => {
element.section = {
@@ -123,7 +117,7 @@
});
test('_computePermissions', () => {
- sandbox.stub(element, 'toSortedArray').returns(
+ sinon.stub(element, 'toSortedArray').returns(
[{
id: 'push',
value: {
@@ -463,7 +457,7 @@
test('_handleValueChange', () => {
// For an existing section.
- const modifiedHandler = sandbox.stub();
+ const modifiedHandler = sinon.stub();
element.section = {id: 'refs/for/bar', value: {permissions: {}}};
assert.notOk(element.section.value.updatedId);
element.section.id = 'refs/for/baz';
@@ -528,7 +522,7 @@
});
test('remove an added section', () => {
- const removeStub = sandbox.stub();
+ const removeStub = sinon.stub();
element.addEventListener('added-section-removed', removeStub);
element.editing = true;
element.section.value.added = true;
diff --git a/polygerrit-ui/app/elements/admin/gr-admin-group-list/gr-admin-group-list_test.html b/polygerrit-ui/app/elements/admin/gr-admin-group-list/gr-admin-group-list_test.js
similarity index 70%
rename from polygerrit-ui/app/elements/admin/gr-admin-group-list/gr-admin-group-list_test.html
rename to polygerrit-ui/app/elements/admin/gr-admin-group-list/gr-admin-group-list_test.js
index c8c7f0c..546b8a8 100644
--- a/polygerrit-ui/app/elements/admin/gr-admin-group-list/gr-admin-group-list_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-admin-group-list/gr-admin-group-list_test.js
@@ -1,41 +1,26 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-admin-group-list</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/page/page.js"></script>
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-admin-group-list></gr-admin-group-list>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-admin-group-list.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
+
+const basicFixture = fixtureFromElement('gr-admin-group-list');
+
let counter = 0;
const groupGenerator = () => {
return {
@@ -55,20 +40,15 @@
suite('gr-admin-group-list tests', () => {
let element;
let groups;
- let sandbox;
+
let value;
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- });
-
- teardown(() => {
- sandbox.restore();
+ element = basicFixture.instantiate();
});
test('_computeGroupUrl', () => {
- let urlStub = sandbox.stub(GerritNav, 'getUrlForGroup',
+ let urlStub = sinon.stub(GerritNav, 'getUrlForGroup').callsFake(
() => '/admin/groups/e2cd66f88a2db4d391ac068a92d987effbe872f5');
let group = {
@@ -79,7 +59,7 @@
urlStub.restore();
- urlStub = sandbox.stub(GerritNav, 'getUrlForGroup',
+ urlStub = sinon.stub(GerritNav, 'getUrlForGroup').callsFake(
() => '/admin/groups/user/test');
group = {
@@ -117,7 +97,7 @@
});
test('_maybeOpenCreateOverlay', () => {
- const overlayOpen = sandbox.stub(element.$.createOverlay, 'open');
+ const overlayOpen = sinon.stub(element.$.createOverlay, 'open');
element._maybeOpenCreateOverlay();
assert.isFalse(overlayOpen.called);
const params = {};
@@ -149,10 +129,10 @@
suite('filter', () => {
test('_paramsChanged', done => {
- sandbox.stub(
+ sinon.stub(
element.$.restAPI,
- 'getGroups',
- () => Promise.resolve(groups));
+ 'getGroups')
+ .callsFake(() => Promise.resolve(groups));
const value = {
filter: 'test',
offset: 25,
@@ -182,7 +162,7 @@
suite('create new', () => {
test('_handleCreateClicked called when create-click fired', () => {
- sandbox.stub(element, '_handleCreateClicked');
+ sinon.stub(element, '_handleCreateClicked');
element.shadowRoot
.querySelector('gr-list-view').dispatchEvent(
new CustomEvent('create-clicked', {
@@ -192,13 +172,13 @@
});
test('_handleCreateClicked opens modal', () => {
- const openStub = sandbox.stub(element.$.createOverlay, 'open');
+ const openStub = sinon.stub(element.$.createOverlay, 'open');
element._handleCreateClicked();
assert.isTrue(openStub.called);
});
test('_handleCreateGroup called when confirm fired', () => {
- sandbox.stub(element, '_handleCreateGroup');
+ sinon.stub(element, '_handleCreateGroup');
element.$.createDialog.dispatchEvent(
new CustomEvent('confirm', {
composed: true, bubbles: true,
@@ -207,7 +187,7 @@
});
test('_handleCloseCreate called when cancel fired', () => {
- sandbox.stub(element, '_handleCloseCreate');
+ sinon.stub(element, '_handleCloseCreate');
element.$.createDialog.dispatchEvent(
new CustomEvent('cancel', {
composed: true, bubbles: true,
@@ -216,4 +196,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view_test.html b/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view_test.js
similarity index 82%
rename from polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view_test.html
rename to polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view_test.js
index ec72bfd..25b14e2 100644
--- a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view_test.js
@@ -1,64 +1,43 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-admin-view</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-admin-view></gr-admin-view>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-admin-view.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
import {pluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
+const basicFixture = fixtureFromElement('gr-admin-view');
+
suite('gr-admin-view tests', () => {
let element;
- let sandbox;
setup(done => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
+ element = basicFixture.instantiate();
stub('gr-rest-api-interface', {
getProjectConfig() {
return Promise.resolve({});
},
});
const pluginsLoaded = Promise.resolve();
- sandbox.stub(pluginLoader, 'awaitPluginsLoaded').returns(pluginsLoaded);
+ sinon.stub(pluginLoader, 'awaitPluginsLoaded').returns(pluginsLoaded);
pluginsLoaded.then(() => flush(done));
});
- teardown(() => {
- sandbox.restore();
- });
-
test('_computeURLHelper', () => {
const path = '/test';
const host = 'http://www.testsite.com';
@@ -71,7 +50,7 @@
element._computeLinkURL({url: '/test', noBaseUrl: true}),
'//' + window.location.host + '/test');
- sandbox.stub(element, 'getBaseUrl').returns('/foo');
+ sinon.stub(element, 'getBaseUrl').returns('/foo');
assert.equal(
element._computeLinkURL({url: '/test', noBaseUrl: true}),
'//' + window.location.host + '/foo/test');
@@ -103,18 +82,18 @@
});
test('_filteredLinks admin', done => {
- sandbox.stub(element.$.restAPI, 'getAccount').returns(Promise.resolve({
+ sinon.stub(element.$.restAPI, 'getAccount').returns(Promise.resolve({
name: 'test-user',
}));
- sandbox.stub(
+ sinon.stub(
element.$.restAPI,
- 'getAccountCapabilities',
- () => Promise.resolve({
+ 'getAccountCapabilities')
+ .callsFake(() => Promise.resolve({
createGroup: true,
createProject: true,
viewPlugins: true,
})
- );
+ );
element.reload().then(() => {
assert.equal(element._filteredLinks.length, 3);
@@ -131,14 +110,14 @@
});
test('_filteredLinks non admin authenticated', done => {
- sandbox.stub(element.$.restAPI, 'getAccount').returns(Promise.resolve({
+ sinon.stub(element.$.restAPI, 'getAccount').returns(Promise.resolve({
name: 'test-user',
}));
- sandbox.stub(
+ sinon.stub(
element.$.restAPI,
- 'getAccountCapabilities',
- () => Promise.resolve({})
- );
+ 'getAccountCapabilities')
+ .callsFake(() => Promise.resolve({})
+ );
element.reload().then(() => {
assert.equal(element._filteredLinks.length, 2);
@@ -162,7 +141,7 @@
});
test('_filteredLinks from plugin', () => {
- sandbox.stub(element.$.jsAPI, 'getAdminMenuLinks').returns([
+ sinon.stub(element.$.jsAPI, 'getAdminMenuLinks').returns([
{text: 'internal link text', url: '/internal/link/url'},
{text: 'external link text', url: 'http://external/link/url'},
]);
@@ -191,13 +170,13 @@
test('Repo shows up in nav', done => {
element._repoName = 'Test Repo';
- sandbox.stub(element.$.restAPI, 'getAccount').returns(Promise.resolve({
+ sinon.stub(element.$.restAPI, 'getAccount').returns(Promise.resolve({
name: 'test-user',
}));
- sandbox.stub(
+ sinon.stub(
element.$.restAPI,
- 'getAccountCapabilities',
- () => Promise.resolve({
+ 'getAccountCapabilities')
+ .callsFake(() => Promise.resolve({
createGroup: true,
createProject: true,
viewPlugins: true,
@@ -222,13 +201,13 @@
element._groupIsInternal = true;
element._isAdmin = true;
element._groupOwner = false;
- sandbox.stub(element.$.restAPI, 'getAccount').returns(Promise.resolve({
+ sinon.stub(element.$.restAPI, 'getAccount').returns(Promise.resolve({
name: 'test-user',
}));
- sandbox.stub(
+ sinon.stub(
element.$.restAPI,
- 'getAccountCapabilities',
- () => Promise.resolve({
+ 'getAccountCapabilities')
+ .callsFake(() => Promise.resolve({
createGroup: true,
createProject: true,
viewPlugins: true,
@@ -251,19 +230,19 @@
});
test('Nav is reloaded when repo changes', () => {
- sandbox.stub(
+ sinon.stub(
element.$.restAPI,
- 'getAccountCapabilities',
- () => Promise.resolve({
+ 'getAccountCapabilities')
+ .callsFake(() => Promise.resolve({
createGroup: true,
createProject: true,
viewPlugins: true,
}));
- sandbox.stub(
+ sinon.stub(
element.$.restAPI,
- 'getAccount',
- () => Promise.resolve({_id: 1}));
- sandbox.stub(element, 'reload');
+ 'getAccount')
+ .callsFake(() => Promise.resolve({_id: 1}));
+ sinon.stub(element, 'reload');
element.params = {repo: 'Test Repo', adminView: 'gr-repo'};
assert.equal(element.reload.callCount, 1);
element.params = {repo: 'Test Repo 2',
@@ -272,28 +251,28 @@
});
test('Nav is reloaded when group changes', () => {
- sandbox.stub(element, '_computeGroupName');
- sandbox.stub(
+ sinon.stub(element, '_computeGroupName');
+ sinon.stub(
element.$.restAPI,
- 'getAccountCapabilities',
- () => Promise.resolve({
+ 'getAccountCapabilities')
+ .callsFake(() => Promise.resolve({
createGroup: true,
createProject: true,
viewPlugins: true,
}));
- sandbox.stub(
+ sinon.stub(
element.$.restAPI,
- 'getAccount',
- () => Promise.resolve({_id: 1}));
- sandbox.stub(element, 'reload');
+ 'getAccount')
+ .callsFake(() => Promise.resolve({_id: 1}));
+ sinon.stub(element, 'reload');
element.params = {groupId: '1', adminView: 'gr-group'};
assert.equal(element.reload.callCount, 1);
});
test('Nav is reloaded when group name changes', done => {
const newName = 'newName';
- sandbox.stub(element, '_computeGroupName');
- sandbox.stub(element, 'reload', () => {
+ sinon.stub(element, '_computeGroupName');
+ sinon.stub(element, 'reload').callsFake(() => {
assert.equal(element._groupName, newName);
assert.isTrue(element.reload.called);
done();
@@ -340,18 +319,18 @@
view: GerritNav.View.REPO,
detail: GerritNav.RepoDetailView.ACCESS,
};
- sandbox.stub(
+ sinon.stub(
element.$.restAPI,
- 'getAccountCapabilities',
- () => Promise.resolve({
+ 'getAccountCapabilities')
+ .callsFake(() => Promise.resolve({
createGroup: true,
createProject: true,
viewPlugins: true,
}));
- sandbox.stub(
+ sinon.stub(
element.$.restAPI,
- 'getAccount',
- () => Promise.resolve({_id: 1}));
+ 'getAccount')
+ .callsFake(() => Promise.resolve({_id: 1}));
flushAsynchronousOperations();
const expectedFilteredLinks = [
{
@@ -464,9 +443,9 @@
parent: 'my-repo',
},
];
- sandbox.stub(GerritNav, 'navigateToRelativeUrl');
- sandbox.spy(element, '_selectedIsCurrentPage');
- sandbox.spy(element, '_handleSubsectionChange');
+ sinon.stub(GerritNav, 'navigateToRelativeUrl');
+ sinon.spy(element, '_selectedIsCurrentPage');
+ sinon.spy(element, '_handleSubsectionChange');
element.reload().then(() => {
assert.deepEqual(element._filteredLinks, expectedFilteredLinks);
assert.deepEqual(element._subsectionLinks, expectedSubsectionLinks);
@@ -503,18 +482,18 @@
suite('_computeSelectedClass', () => {
setup(() => {
- sandbox.stub(
+ sinon.stub(
element.$.restAPI,
- 'getAccountCapabilities',
- () => Promise.resolve({
+ 'getAccountCapabilities')
+ .callsFake(() => Promise.resolve({
createGroup: true,
createProject: true,
viewPlugins: true,
}));
- sandbox.stub(
+ sinon.stub(
element.$.restAPI,
- 'getAccount',
- () => Promise.resolve({_id: 1}));
+ 'getAccount')
+ .callsFake(() => Promise.resolve({_id: 1}));
return element.reload();
});
@@ -596,12 +575,12 @@
_loadGroupDetails: () => {},
});
- sandbox.stub(element.$.restAPI, 'getGroupConfig')
+ sinon.stub(element.$.restAPI, 'getGroupConfig')
.returns(Promise.resolve({
name: 'foo',
id: 'c0f83e941ce90caea30e6ad88f0d4ea0e841a7a9',
}));
- sandbox.stub(element.$.restAPI, 'getIsGroupOwner')
+ sinon.stub(element.$.restAPI, 'getIsGroupOwner')
.returns(Promise.resolve(true));
return element.reload();
});
@@ -640,7 +619,7 @@
test('external group', () => {
element.$.restAPI.getGroupConfig.restore();
- sandbox.stub(element.$.restAPI, 'getGroupConfig')
+ sinon.stub(element.$.restAPI, 'getGroupConfig')
.returns(Promise.resolve({
name: 'foo',
id: 'external-id',
@@ -681,4 +660,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/admin/gr-confirm-delete-item-dialog/gr-confirm-delete-item-dialog_test.html b/polygerrit-ui/app/elements/admin/gr-confirm-delete-item-dialog/gr-confirm-delete-item-dialog_test.html
deleted file mode 100644
index 003edfb..0000000
--- a/polygerrit-ui/app/elements/admin/gr-confirm-delete-item-dialog/gr-confirm-delete-item-dialog_test.html
+++ /dev/null
@@ -1,90 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-confirm-delete-item-dialog</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-confirm-delete-item-dialog></gr-confirm-delete-item-dialog>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-confirm-delete-item-dialog.js';
-suite('gr-confirm-delete-item-dialog tests', () => {
- let element;
- let sandbox;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('_handleConfirmTap', () => {
- const confirmHandler = sandbox.stub();
- element.addEventListener('confirm', confirmHandler);
- sandbox.spy(element, '_handleConfirmTap');
- element.shadowRoot
- .querySelector('gr-dialog').dispatchEvent(
- new CustomEvent('confirm', {
- composed: true, bubbles: true,
- }));
- assert.isTrue(confirmHandler.called);
- assert.isTrue(confirmHandler.calledOnce);
- assert.isTrue(element._handleConfirmTap.called);
- assert.isTrue(element._handleConfirmTap.calledOnce);
- });
-
- test('_handleCancelTap', () => {
- const cancelHandler = sandbox.stub();
- element.addEventListener('cancel', cancelHandler);
- sandbox.spy(element, '_handleCancelTap');
- element.shadowRoot
- .querySelector('gr-dialog').dispatchEvent(
- new CustomEvent('cancel', {
- composed: true, bubbles: true,
- }));
- assert.isTrue(cancelHandler.called);
- assert.isTrue(cancelHandler.calledOnce);
- assert.isTrue(element._handleCancelTap.called);
- assert.isTrue(element._handleCancelTap.calledOnce);
- });
-
- test('_computeItemName function for branches', () => {
- assert.deepEqual(element._computeItemName('branches'), 'Branch');
- assert.notEqual(element._computeItemName('branches'), 'Tag');
- });
-
- test('_computeItemName function for tags', () => {
- assert.deepEqual(element._computeItemName('tags'), 'Tag');
- assert.notEqual(element._computeItemName('tags'), 'Branch');
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/admin/gr-confirm-delete-item-dialog/gr-confirm-delete-item-dialog_test.js b/polygerrit-ui/app/elements/admin/gr-confirm-delete-item-dialog/gr-confirm-delete-item-dialog_test.js
new file mode 100644
index 0000000..485a48b
--- /dev/null
+++ b/polygerrit-ui/app/elements/admin/gr-confirm-delete-item-dialog/gr-confirm-delete-item-dialog_test.js
@@ -0,0 +1,70 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-confirm-delete-item-dialog.js';
+
+const basicFixture = fixtureFromElement('gr-confirm-delete-item-dialog');
+
+suite('gr-confirm-delete-item-dialog tests', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ test('_handleConfirmTap', () => {
+ const confirmHandler = sinon.stub();
+ element.addEventListener('confirm', confirmHandler);
+ sinon.spy(element, '_handleConfirmTap');
+ element.shadowRoot
+ .querySelector('gr-dialog').dispatchEvent(
+ new CustomEvent('confirm', {
+ composed: true, bubbles: true,
+ }));
+ assert.isTrue(confirmHandler.called);
+ assert.isTrue(confirmHandler.calledOnce);
+ assert.isTrue(element._handleConfirmTap.called);
+ assert.isTrue(element._handleConfirmTap.calledOnce);
+ });
+
+ test('_handleCancelTap', () => {
+ const cancelHandler = sinon.stub();
+ element.addEventListener('cancel', cancelHandler);
+ sinon.spy(element, '_handleCancelTap');
+ element.shadowRoot
+ .querySelector('gr-dialog').dispatchEvent(
+ new CustomEvent('cancel', {
+ composed: true, bubbles: true,
+ }));
+ assert.isTrue(cancelHandler.called);
+ assert.isTrue(cancelHandler.calledOnce);
+ assert.isTrue(element._handleCancelTap.called);
+ assert.isTrue(element._handleCancelTap.calledOnce);
+ });
+
+ test('_computeItemName function for branches', () => {
+ assert.deepEqual(element._computeItemName('branches'), 'Branch');
+ assert.notEqual(element._computeItemName('branches'), 'Tag');
+ });
+
+ test('_computeItemName function for tags', () => {
+ assert.deepEqual(element._computeItemName('tags'), 'Tag');
+ assert.notEqual(element._computeItemName('tags'), 'Branch');
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog_test.html b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog_test.js
similarity index 67%
rename from polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog_test.html
rename to polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog_test.js
index eaee4a4..07eee42 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog_test.js
@@ -1,45 +1,29 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-create-change-dialog</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-create-change-dialog></gr-create-change-dialog>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-create-change-dialog.js';
+
+const basicFixture = fixtureFromElement('gr-create-change-dialog');
+
suite('gr-create-change-dialog tests', () => {
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
stub('gr-rest-api-interface', {
getLoggedIn() { return Promise.resolve(true); },
getRepoBranches(input) {
@@ -56,7 +40,7 @@
}
},
});
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.repoName = 'test-repo';
element._repoConfig = {
private_by_default: {
@@ -66,10 +50,6 @@
};
});
- teardown(() => {
- sandbox.restore();
- });
-
test('new change created with default', done => {
const configInputObj = {
branch: 'test-branch',
@@ -79,8 +59,8 @@
work_in_progress: true,
};
- const saveStub = sandbox.stub(element.$.restAPI,
- 'createChange', () => Promise.resolve({}));
+ const saveStub = sinon.stub(element.$.restAPI,
+ 'createChange').callsFake(() => Promise.resolve({}));
element.branch = 'test-branch';
element.topic = 'test-topic';
@@ -106,7 +86,8 @@
configured_value: 'TRUE',
inherited_value: false,
};
- sandbox.stub(element, '_formatBooleanString', () => Promise.resolve(true));
+ sinon.stub(element, '_formatBooleanString')
+ .callsFake(() => Promise.resolve(true));
flushAsynchronousOperations();
const configInputObj = {
@@ -117,8 +98,8 @@
work_in_progress: true,
};
- const saveStub = sandbox.stub(element.$.restAPI,
- 'createChange', () => Promise.resolve({}));
+ const saveStub = sinon.stub(element.$.restAPI,
+ 'createChange').callsFake(() => Promise.resolve({}));
element.branch = 'test-branch';
element.topic = 'test-topic';
@@ -164,4 +145,4 @@
assert.equal(element._computePrivateSectionClass(false), '');
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/admin/gr-create-group-dialog/gr-create-group-dialog_test.html b/polygerrit-ui/app/elements/admin/gr-create-group-dialog/gr-create-group-dialog_test.html
deleted file mode 100644
index 164db53..0000000
--- a/polygerrit-ui/app/elements/admin/gr-create-group-dialog/gr-create-group-dialog_test.html
+++ /dev/null
@@ -1,100 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-create-group-dialog</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/page/page.js"></script>
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-create-group-dialog></gr-create-group-dialog>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-create-group-dialog.js';
-import page from 'page/page.mjs';
-
-suite('gr-create-group-dialog tests', () => {
- let element;
- let sandbox;
- const GROUP_NAME = 'test-group';
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- stub('gr-rest-api-interface', {
- getLoggedIn() { return Promise.resolve(true); },
- });
- element = fixture('basic');
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('name is updated correctly', done => {
- assert.isFalse(element.hasNewGroupName);
-
- const inputEl = element.root.querySelector('iron-input');
- inputEl.bindValue = GROUP_NAME;
-
- setTimeout(() => {
- assert.isTrue(element.hasNewGroupName);
- assert.deepEqual(element._name, GROUP_NAME);
- done();
- });
- });
-
- test('test for redirecting to group on successful creation', done => {
- sandbox.stub(element.$.restAPI, 'createGroup')
- .returns(Promise.resolve({status: 201}));
-
- sandbox.stub(element.$.restAPI, 'getGroupConfig')
- .returns(Promise.resolve({group_id: 551}));
-
- const showStub = sandbox.stub(page, 'show');
- element.handleCreateGroup()
- .then(() => {
- assert.isTrue(showStub.calledWith('/admin/groups/551'));
- done();
- });
- });
-
- test('test for unsuccessful group creation', done => {
- sandbox.stub(element.$.restAPI, 'createGroup')
- .returns(Promise.resolve({status: 409}));
-
- sandbox.stub(element.$.restAPI, 'getGroupConfig')
- .returns(Promise.resolve({group_id: 551}));
-
- const showStub = sandbox.stub(page, 'show');
- element.handleCreateGroup()
- .then(() => {
- assert.isFalse(showStub.called);
- done();
- });
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/admin/gr-create-group-dialog/gr-create-group-dialog_test.js b/polygerrit-ui/app/elements/admin/gr-create-group-dialog/gr-create-group-dialog_test.js
new file mode 100644
index 0000000..d9bc500
--- /dev/null
+++ b/polygerrit-ui/app/elements/admin/gr-create-group-dialog/gr-create-group-dialog_test.js
@@ -0,0 +1,79 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-create-group-dialog.js';
+import page from 'page/page.mjs';
+
+const basicFixture = fixtureFromElement('gr-create-group-dialog');
+
+suite('gr-create-group-dialog tests', () => {
+ let element;
+
+ const GROUP_NAME = 'test-group';
+
+ setup(() => {
+ stub('gr-rest-api-interface', {
+ getLoggedIn() { return Promise.resolve(true); },
+ });
+ element = basicFixture.instantiate();
+ });
+
+ test('name is updated correctly', done => {
+ assert.isFalse(element.hasNewGroupName);
+
+ const inputEl = element.root.querySelector('iron-input');
+ inputEl.bindValue = GROUP_NAME;
+
+ setTimeout(() => {
+ assert.isTrue(element.hasNewGroupName);
+ assert.deepEqual(element._name, GROUP_NAME);
+ done();
+ });
+ });
+
+ test('test for redirecting to group on successful creation', done => {
+ sinon.stub(element.$.restAPI, 'createGroup')
+ .returns(Promise.resolve({status: 201}));
+
+ sinon.stub(element.$.restAPI, 'getGroupConfig')
+ .returns(Promise.resolve({group_id: 551}));
+
+ const showStub = sinon.stub(page, 'show');
+ element.handleCreateGroup()
+ .then(() => {
+ assert.isTrue(showStub.calledWith('/admin/groups/551'));
+ done();
+ });
+ });
+
+ test('test for unsuccessful group creation', done => {
+ sinon.stub(element.$.restAPI, 'createGroup')
+ .returns(Promise.resolve({status: 409}));
+
+ sinon.stub(element.$.restAPI, 'getGroupConfig')
+ .returns(Promise.resolve({group_id: 551}));
+
+ const showStub = sinon.stub(page, 'show');
+ element.handleCreateGroup()
+ .then(() => {
+ assert.isFalse(showStub.called);
+ done();
+ });
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/admin/gr-create-pointer-dialog/gr-create-pointer-dialog_test.html b/polygerrit-ui/app/elements/admin/gr-create-pointer-dialog/gr-create-pointer-dialog_test.html
deleted file mode 100644
index 2778d40..0000000
--- a/polygerrit-ui/app/elements/admin/gr-create-pointer-dialog/gr-create-pointer-dialog_test.html
+++ /dev/null
@@ -1,135 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-create-pointer-dialog</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-create-pointer-dialog></gr-create-pointer-dialog>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-create-pointer-dialog.js';
-import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
-suite('gr-create-pointer-dialog tests', () => {
- let element;
- let sandbox;
-
- const ironInput = function(element) {
- return dom(element).querySelector('iron-input');
- };
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- stub('gr-rest-api-interface', {
- getLoggedIn() { return Promise.resolve(true); },
- });
- element = fixture('basic');
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('branch created', done => {
- sandbox.stub(
- element.$.restAPI,
- 'createRepoBranch',
- () => Promise.resolve({}));
-
- assert.isFalse(element.hasNewItemName);
-
- element._itemName = 'test-branch';
- element.itemDetail = 'branches';
-
- ironInput(element.$.itemNameSection).bindValue = 'test-branch2';
- ironInput(element.$.itemRevisionSection).bindValue = 'HEAD';
-
- setTimeout(() => {
- assert.isTrue(element.hasNewItemName);
- assert.equal(element._itemName, 'test-branch2');
- assert.equal(element._itemRevision, 'HEAD');
- done();
- });
- });
-
- test('tag created', done => {
- sandbox.stub(
- element.$.restAPI,
- 'createRepoTag',
- () => Promise.resolve({}));
-
- assert.isFalse(element.hasNewItemName);
-
- element._itemName = 'test-tag';
- element.itemDetail = 'tags';
-
- ironInput(element.$.itemNameSection).bindValue = 'test-tag2';
- ironInput(element.$.itemRevisionSection).bindValue = 'HEAD';
-
- setTimeout(() => {
- assert.isTrue(element.hasNewItemName);
- assert.equal(element._itemName, 'test-tag2');
- assert.equal(element._itemRevision, 'HEAD');
- done();
- });
- });
-
- test('tag created with annotations', done => {
- sandbox.stub(
- element.$.restAPI,
- 'createRepoTag',
- () => Promise.resolve({}));
-
- assert.isFalse(element.hasNewItemName);
-
- element._itemName = 'test-tag';
- element._itemAnnotation = 'test-message';
- element.itemDetail = 'tags';
-
- ironInput(element.$.itemNameSection).bindValue = 'test-tag2';
- ironInput(element.$.itemAnnotationSection).bindValue = 'test-message2';
- ironInput(element.$.itemRevisionSection).bindValue = 'HEAD';
-
- setTimeout(() => {
- assert.isTrue(element.hasNewItemName);
- assert.equal(element._itemName, 'test-tag2');
- assert.equal(element._itemAnnotation, 'test-message2');
- assert.equal(element._itemRevision, 'HEAD');
- done();
- });
- });
-
- test('_computeHideItemClass returns hideItem if type is branches', () => {
- assert.equal(element._computeHideItemClass('branches'), 'hideItem');
- });
-
- test('_computeHideItemClass returns strings if not branches', () => {
- assert.equal(element._computeHideItemClass('tags'), '');
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/admin/gr-create-pointer-dialog/gr-create-pointer-dialog_test.js b/polygerrit-ui/app/elements/admin/gr-create-pointer-dialog/gr-create-pointer-dialog_test.js
new file mode 100644
index 0000000..22f19a6
--- /dev/null
+++ b/polygerrit-ui/app/elements/admin/gr-create-pointer-dialog/gr-create-pointer-dialog_test.js
@@ -0,0 +1,115 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-create-pointer-dialog.js';
+import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+
+const basicFixture = fixtureFromElement('gr-create-pointer-dialog');
+
+suite('gr-create-pointer-dialog tests', () => {
+ let element;
+
+ const ironInput = function(element) {
+ return dom(element).querySelector('iron-input');
+ };
+
+ setup(() => {
+ stub('gr-rest-api-interface', {
+ getLoggedIn() { return Promise.resolve(true); },
+ });
+ element = basicFixture.instantiate();
+ });
+
+ test('branch created', done => {
+ sinon.stub(
+ element.$.restAPI,
+ 'createRepoBranch')
+ .callsFake(() => Promise.resolve({}));
+
+ assert.isFalse(element.hasNewItemName);
+
+ element._itemName = 'test-branch';
+ element.itemDetail = 'branches';
+
+ ironInput(element.$.itemNameSection).bindValue = 'test-branch2';
+ ironInput(element.$.itemRevisionSection).bindValue = 'HEAD';
+
+ setTimeout(() => {
+ assert.isTrue(element.hasNewItemName);
+ assert.equal(element._itemName, 'test-branch2');
+ assert.equal(element._itemRevision, 'HEAD');
+ done();
+ });
+ });
+
+ test('tag created', done => {
+ sinon.stub(
+ element.$.restAPI,
+ 'createRepoTag')
+ .callsFake(() => Promise.resolve({}));
+
+ assert.isFalse(element.hasNewItemName);
+
+ element._itemName = 'test-tag';
+ element.itemDetail = 'tags';
+
+ ironInput(element.$.itemNameSection).bindValue = 'test-tag2';
+ ironInput(element.$.itemRevisionSection).bindValue = 'HEAD';
+
+ setTimeout(() => {
+ assert.isTrue(element.hasNewItemName);
+ assert.equal(element._itemName, 'test-tag2');
+ assert.equal(element._itemRevision, 'HEAD');
+ done();
+ });
+ });
+
+ test('tag created with annotations', done => {
+ sinon.stub(
+ element.$.restAPI,
+ 'createRepoTag')
+ .callsFake(() => Promise.resolve({}));
+
+ assert.isFalse(element.hasNewItemName);
+
+ element._itemName = 'test-tag';
+ element._itemAnnotation = 'test-message';
+ element.itemDetail = 'tags';
+
+ ironInput(element.$.itemNameSection).bindValue = 'test-tag2';
+ ironInput(element.$.itemAnnotationSection).bindValue = 'test-message2';
+ ironInput(element.$.itemRevisionSection).bindValue = 'HEAD';
+
+ setTimeout(() => {
+ assert.isTrue(element.hasNewItemName);
+ assert.equal(element._itemName, 'test-tag2');
+ assert.equal(element._itemAnnotation, 'test-message2');
+ assert.equal(element._itemRevision, 'HEAD');
+ done();
+ });
+ });
+
+ test('_computeHideItemClass returns hideItem if type is branches', () => {
+ assert.equal(element._computeHideItemClass('branches'), 'hideItem');
+ });
+
+ test('_computeHideItemClass returns strings if not branches', () => {
+ assert.equal(element._computeHideItemClass('tags'), '');
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog_test.html b/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog_test.html
deleted file mode 100644
index dfab4ac..0000000
--- a/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog_test.html
+++ /dev/null
@@ -1,105 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-create-repo-dialog</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-create-repo-dialog></gr-create-repo-dialog>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-create-repo-dialog.js';
-suite('gr-create-repo-dialog tests', () => {
- let element;
- let sandbox;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- stub('gr-rest-api-interface', {
- getLoggedIn() { return Promise.resolve(true); },
- });
- element = fixture('basic');
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('default values are populated', () => {
- assert.isTrue(element.$.initialCommit.bindValue);
- assert.isFalse(element.$.parentRepo.bindValue);
- });
-
- test('repo created', done => {
- const configInputObj = {
- name: 'test-repo',
- create_empty_commit: true,
- parent: 'All-Project',
- permissions_only: false,
- owners: ['testId'],
- };
-
- const saveStub = sandbox.stub(element.$.restAPI,
- 'createRepo', () => Promise.resolve({}));
-
- assert.isFalse(element.hasNewRepoName);
-
- element._repoConfig = {
- name: 'test-repo',
- create_empty_commit: true,
- parent: 'All-Project',
- permissions_only: false,
- };
-
- element._repoOwner = 'test';
- element._repoOwnerId = 'testId';
-
- element.$.repoNameInput.bindValue = configInputObj.name;
- element.$.rightsInheritFromInput.bindValue = configInputObj.parent;
- element.$.ownerInput.text = configInputObj.owners[0];
- element.$.initialCommit.bindValue =
- configInputObj.create_empty_commit;
- element.$.parentRepo.bindValue =
- configInputObj.permissions_only;
-
- assert.isTrue(element.hasNewRepoName);
-
- assert.deepEqual(element._repoConfig, configInputObj);
-
- element.handleCreateRepo().then(() => {
- assert.isTrue(saveStub.lastCall.calledWithExactly(configInputObj));
- done();
- });
- });
-
- test('testing observer of _repoOwner', () => {
- element._repoOwnerId = 'test-5';
- assert.deepEqual(element._repoConfig.owners, ['test-5']);
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog_test.js b/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog_test.js
new file mode 100644
index 0000000..1e1fb0e
--- /dev/null
+++ b/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog_test.js
@@ -0,0 +1,85 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-create-repo-dialog.js';
+
+const basicFixture = fixtureFromElement('gr-create-repo-dialog');
+
+suite('gr-create-repo-dialog tests', () => {
+ let element;
+
+ setup(() => {
+ stub('gr-rest-api-interface', {
+ getLoggedIn() { return Promise.resolve(true); },
+ });
+ element = basicFixture.instantiate();
+ });
+
+ test('default values are populated', () => {
+ assert.isTrue(element.$.initialCommit.bindValue);
+ assert.isFalse(element.$.parentRepo.bindValue);
+ });
+
+ test('repo created', done => {
+ const configInputObj = {
+ name: 'test-repo',
+ create_empty_commit: true,
+ parent: 'All-Project',
+ permissions_only: false,
+ owners: ['testId'],
+ };
+
+ const saveStub = sinon.stub(element.$.restAPI,
+ 'createRepo').callsFake(() => Promise.resolve({}));
+
+ assert.isFalse(element.hasNewRepoName);
+
+ element._repoConfig = {
+ name: 'test-repo',
+ create_empty_commit: true,
+ parent: 'All-Project',
+ permissions_only: false,
+ };
+
+ element._repoOwner = 'test';
+ element._repoOwnerId = 'testId';
+
+ element.$.repoNameInput.bindValue = configInputObj.name;
+ element.$.rightsInheritFromInput.bindValue = configInputObj.parent;
+ element.$.ownerInput.text = configInputObj.owners[0];
+ element.$.initialCommit.bindValue =
+ configInputObj.create_empty_commit;
+ element.$.parentRepo.bindValue =
+ configInputObj.permissions_only;
+
+ assert.isTrue(element.hasNewRepoName);
+
+ assert.deepEqual(element._repoConfig, configInputObj);
+
+ element.handleCreateRepo().then(() => {
+ assert.isTrue(saveStub.lastCall.calledWithExactly(configInputObj));
+ done();
+ });
+ });
+
+ test('testing observer of _repoOwner', () => {
+ element._repoOwnerId = 'test-5';
+ assert.deepEqual(element._repoConfig.owners, ['test-5']);
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/admin/gr-group-audit-log/gr-group-audit-log_test.html b/polygerrit-ui/app/elements/admin/gr-group-audit-log/gr-group-audit-log_test.html
deleted file mode 100644
index 4590220..0000000
--- a/polygerrit-ui/app/elements/admin/gr-group-audit-log/gr-group-audit-log_test.html
+++ /dev/null
@@ -1,116 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-group-audit-log</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-group-audit-log></gr-group-audit-log>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-group-audit-log.js';
-suite('gr-group-audit-log tests', () => {
- let element;
- let sandbox;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- suite('members', () => {
- test('test _getNameForGroup', () => {
- let group = {
- member: {
- name: 'test-name',
- },
- };
- assert.equal(element._getNameForGroup(group.member), 'test-name');
-
- group = {
- member: {
- id: 'test-id',
- },
- };
- assert.equal(element._getNameForGroup(group.member), 'test-id');
- });
-
- test('test _isGroupEvent', () => {
- assert.isTrue(element._isGroupEvent('ADD_GROUP'));
- assert.isTrue(element._isGroupEvent('REMOVE_GROUP'));
-
- assert.isFalse(element._isGroupEvent('ADD_USER'));
- assert.isFalse(element._isGroupEvent('REMOVE_USER'));
- });
- });
-
- suite('users', () => {
- test('test _getIdForUser', () => {
- const account = {
- user: {
- username: 'test-user',
- _account_id: 12,
- },
- };
- assert.equal(element._getIdForUser(account.user), ' (12)');
- });
-
- test('test _account_id not present', () => {
- const account = {
- user: {
- username: 'test-user',
- },
- };
- assert.equal(element._getIdForUser(account.user), '');
- });
- });
-
- suite('404', () => {
- test('fires page-error', done => {
- element.groupId = 1;
-
- const response = {status: 404};
- sandbox.stub(
- element.$.restAPI, 'getGroupAuditLog', (group, errFn) => {
- errFn(response);
- });
-
- element.addEventListener('page-error', e => {
- assert.deepEqual(e.detail.response, response);
- done();
- });
-
- element._getAuditLogs();
- });
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/admin/gr-group-audit-log/gr-group-audit-log_test.js b/polygerrit-ui/app/elements/admin/gr-group-audit-log/gr-group-audit-log_test.js
new file mode 100644
index 0000000..1bbfcae
--- /dev/null
+++ b/polygerrit-ui/app/elements/admin/gr-group-audit-log/gr-group-audit-log_test.js
@@ -0,0 +1,97 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-group-audit-log.js';
+
+const basicFixture = fixtureFromElement('gr-group-audit-log');
+
+suite('gr-group-audit-log tests', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ suite('members', () => {
+ test('test _getNameForGroup', () => {
+ let group = {
+ member: {
+ name: 'test-name',
+ },
+ };
+ assert.equal(element._getNameForGroup(group.member), 'test-name');
+
+ group = {
+ member: {
+ id: 'test-id',
+ },
+ };
+ assert.equal(element._getNameForGroup(group.member), 'test-id');
+ });
+
+ test('test _isGroupEvent', () => {
+ assert.isTrue(element._isGroupEvent('ADD_GROUP'));
+ assert.isTrue(element._isGroupEvent('REMOVE_GROUP'));
+
+ assert.isFalse(element._isGroupEvent('ADD_USER'));
+ assert.isFalse(element._isGroupEvent('REMOVE_USER'));
+ });
+ });
+
+ suite('users', () => {
+ test('test _getIdForUser', () => {
+ const account = {
+ user: {
+ username: 'test-user',
+ _account_id: 12,
+ },
+ };
+ assert.equal(element._getIdForUser(account.user), ' (12)');
+ });
+
+ test('test _account_id not present', () => {
+ const account = {
+ user: {
+ username: 'test-user',
+ },
+ };
+ assert.equal(element._getIdForUser(account.user), '');
+ });
+ });
+
+ suite('404', () => {
+ test('fires page-error', done => {
+ element.groupId = 1;
+
+ const response = {status: 404};
+ sinon.stub(
+ element.$.restAPI, 'getGroupAuditLog')
+ .callsFake((group, errFn) => {
+ errFn(response);
+ });
+
+ element.addEventListener('page-error', e => {
+ assert.deepEqual(e.detail.response, response);
+ done();
+ });
+
+ element._getAuditLogs();
+ });
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members_test.html b/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members_test.js
similarity index 82%
rename from polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members_test.html
rename to polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members_test.js
index 3a5bfd8..f047cfe 100644
--- a/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members_test.js
@@ -1,51 +1,35 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-group-members</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-group-members></gr-group-members>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-group-members.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+
+const basicFixture = fixtureFromElement('gr-group-members');
+
suite('gr-group-members tests', () => {
let element;
- let sandbox;
+
let groups;
let groupMembers;
let includedGroups;
let groupStub;
setup(() => {
- sandbox = sinon.sandbox.create();
-
groups = {
name: 'Administrators',
owner: 'Administrators',
@@ -150,20 +134,16 @@
return Promise.resolve();
},
});
- element = fixture('basic');
- sandbox.stub(element, 'getBaseUrl').returns('https://test/site');
+ element = basicFixture.instantiate();
+ sinon.stub(element, 'getBaseUrl').returns('https://test/site');
element.groupId = 1;
- groupStub = sandbox.stub(
+ groupStub = sinon.stub(
element.$.restAPI,
- 'getGroupConfig',
- () => Promise.resolve(groups));
+ 'getGroupConfig')
+ .callsFake(() => Promise.resolve(groups));
return element._loadGroupDetails();
});
- teardown(() => {
- sandbox.restore();
- });
-
test('_includedGroups', () => {
assert.equal(element._includedGroups.length, 3);
assert.equal(dom(element.root)
@@ -181,8 +161,8 @@
const memberName = 'test-admin';
- const saveStub = sandbox.stub(element.$.restAPI, 'saveGroupMembers',
- () => Promise.resolve({}));
+ const saveStub = sinon.stub(element.$.restAPI, 'saveGroupMembers')
+ .callsFake(() => Promise.resolve({}));
const button = element.$.saveGroupMember;
@@ -206,8 +186,9 @@
const includedGroupName = 'testName';
- const saveIncludedGroupStub = sandbox.stub(
- element.$.restAPI, 'saveIncludedGroup', () => Promise.resolve({}));
+ const saveIncludedGroupStub = sinon.stub(
+ element.$.restAPI, 'saveIncludedGroup')
+ .callsFake(() => Promise.resolve({}));
const button = element.$.saveIncludedGroups;
@@ -230,11 +211,11 @@
element._groupOwner = true;
const memberName = 'bad-name';
- const alertStub = sandbox.stub();
+ const alertStub = sinon.stub();
element.addEventListener('show-alert', alertStub);
const error = new Error('error');
error.status = 404;
- sandbox.stub(element.$.restAPI, 'saveGroupMembers',
+ sinon.stub(element.$.restAPI, 'saveGroupMembers').callsFake(
() => Promise.reject(error));
element.$.groupMemberSearchInput.text = memberName;
@@ -359,8 +340,9 @@
element.groupId = 1;
const response = {status: 404};
- sandbox.stub(
- element.$.restAPI, 'getGroupConfig', (group, errFn) => {
+ sinon.stub(
+ element.$.restAPI, 'getGroupConfig')
+ .callsFake((group, errFn) => {
errFn(response);
});
element.addEventListener('page-error', e => {
@@ -371,4 +353,4 @@
element._loadGroupDetails();
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/admin/gr-group/gr-group_test.html b/polygerrit-ui/app/elements/admin/gr-group/gr-group_test.js
similarity index 71%
rename from polygerrit-ui/app/elements/admin/gr-group/gr-group_test.html
rename to polygerrit-ui/app/elements/admin/gr-group/gr-group_test.js
index 5621fff..c6054b2 100644
--- a/polygerrit-ui/app/elements/admin/gr-group/gr-group_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-group/gr-group_test.js
@@ -1,42 +1,28 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-group</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-group></gr-group>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-group.js';
+
+const basicFixture = fixtureFromElement('gr-group');
+
suite('gr-group tests', () => {
let element;
- let sandbox;
+
let groupStub;
const group = {
id: '6a1e70e1a88782771a91808c8af9bbb7a9871389',
@@ -50,20 +36,14 @@
};
setup(() => {
- sandbox = sinon.sandbox.create();
stub('gr-rest-api-interface', {
getLoggedIn() { return Promise.resolve(true); },
});
- element = fixture('basic');
- groupStub = sandbox.stub(
+ element = basicFixture.instantiate();
+ groupStub = sinon.stub(
element.$.restAPI,
- 'getGroupConfig',
- () => Promise.resolve(group)
- );
- });
-
- teardown(() => {
- sandbox.restore();
+ 'getGroupConfig')
+ .callsFake(() => Promise.resolve(group));
});
test('loading displays before group config is loaded', () => {
@@ -75,10 +55,10 @@
});
test('default values are populated with internal group', done => {
- sandbox.stub(
+ sinon.stub(
element.$.restAPI,
- 'getIsGroupOwner',
- () => Promise.resolve(true));
+ 'getIsGroupOwner')
+ .callsFake(() => Promise.resolve(true));
element.groupId = 1;
element._loadGroup().then(() => {
assert.isTrue(element._groupIsInternal);
@@ -91,14 +71,14 @@
const groupExternal = Object.assign({}, group);
groupExternal.id = 'external-group-id';
groupStub.restore();
- groupStub = sandbox.stub(
+ groupStub = sinon.stub(
element.$.restAPI,
- 'getGroupConfig',
- () => Promise.resolve(groupExternal));
- sandbox.stub(
+ 'getGroupConfig')
+ .callsFake(() => Promise.resolve(groupExternal));
+ sinon.stub(
element.$.restAPI,
- 'getIsGroupOwner',
- () => Promise.resolve(true));
+ 'getIsGroupOwner')
+ .callsFake(() => Promise.resolve(true));
element.groupId = 1;
element._loadGroup().then(() => {
assert.isFalse(element._groupIsInternal);
@@ -116,15 +96,15 @@
};
element._groupName = groupName;
- sandbox.stub(
+ sinon.stub(
element.$.restAPI,
- 'getIsGroupOwner',
- () => Promise.resolve(true));
+ 'getIsGroupOwner')
+ .callsFake(() => Promise.resolve(true));
- sandbox.stub(
+ sinon.stub(
element.$.restAPI,
- 'saveGroupName',
- () => Promise.resolve({status: 200}));
+ 'saveGroupName')
+ .callsFake(() => Promise.resolve({status: 200}));
const button = element.$.inputUpdateNameBtn;
@@ -155,10 +135,10 @@
element._groupConfigOwner = 'testId';
element._groupOwner = true;
- sandbox.stub(
+ sinon.stub(
element.$.restAPI,
- 'getIsGroupOwner',
- () => Promise.resolve({status: 200}));
+ 'getIsGroupOwner')
+ .callsFake(() => Promise.resolve({status: 200}));
const button = element.$.inputUpdateOwnerBtn;
@@ -182,10 +162,10 @@
test('test for undefined group name', done => {
groupStub.restore();
- sandbox.stub(
+ sinon.stub(
element.$.restAPI,
- 'getGroupConfig',
- () => Promise.resolve({}));
+ 'getGroupConfig')
+ .callsFake(() => Promise.resolve({}));
assert.isUndefined(element.groupId);
@@ -209,10 +189,10 @@
name: 'test-group',
};
- sandbox.stub(element.$.restAPI, 'saveGroupName')
+ sinon.stub(element.$.restAPI, 'saveGroupName')
.returns(Promise.resolve({status: 200}));
- const showStub = sandbox.stub(element, 'dispatchEvent');
+ const showStub = sinon.stub(element, 'dispatchEvent');
element._handleSaveName()
.then(() => {
assert.isTrue(showStub.called);
@@ -259,10 +239,10 @@
element.groupId = 1;
const response = {status: 404};
- sandbox.stub(
- element.$.restAPI, 'getGroupConfig', (group, errFn) => {
- errFn(response);
- });
+ sinon.stub(
+ element.$.restAPI, 'getGroupConfig').callsFake((group, errFn) => {
+ errFn(response);
+ });
element.addEventListener('page-error', e => {
assert.deepEqual(e.detail.response, response);
@@ -286,4 +266,4 @@
assert.equal('user/group', element.$.uuid.text);
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.js b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.js
index d25ee76..1aa3e4b 100644
--- a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.js
+++ b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.js
@@ -314,6 +314,13 @@
return RANGE_NAMES.includes(name.toUpperCase());
}
+
+ /**
+ * Work around a issue on iOS when clicking turns into double tap
+ */
+ _onTapExclusiveToggle(e) {
+ e.preventDefault();
+ }
}
customElements.define(GrPermission.is, GrPermission);
diff --git a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission_html.js b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission_html.js
index ef4f1da..ed4f64a 100644
--- a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission_html.js
+++ b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission_html.js
@@ -93,6 +93,7 @@
checked="{{permission.value.exclusive}}"
on-change="_handleValueChange"
disabled$="[[!editing]]"
+ on-tap="_onTapExclusiveToggle"
></paper-toggle-button
>Exclusive
</template>
diff --git a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission_test.html b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission_test.js
similarity index 87%
rename from polygerrit-ui/app/elements/admin/gr-permission/gr-permission_test.html
rename to polygerrit-ui/app/elements/admin/gr-permission/gr-permission_test.js
index 1ce492e..835c90a 100644
--- a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission_test.js
@@ -1,48 +1,31 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-permission</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/page/page.js"></script>
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-permission></gr-permission>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-permission.js';
+
+const basicFixture = fixtureFromElement('gr-permission');
+
suite('gr-permission tests', () => {
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- sandbox.stub(element.$.restAPI, 'getSuggestedGroups').returns(
+ element = basicFixture.instantiate();
+ sinon.stub(element.$.restAPI, 'getSuggestedGroups').returns(
Promise.resolve({
'Administrators': {
id: '4c97682e6ce61b7247f3381b6f1789356666de7f',
@@ -53,10 +36,6 @@
}));
});
- teardown(() => {
- sandbox.restore();
- });
-
suite('unit tests', () => {
test('_sortPermission', () => {
const permission = {
@@ -268,7 +247,7 @@
suite('interactions', () => {
setup(() => {
- sandbox.spy(element, '_computeLabel');
+ sinon.spy(element, '_computeLabel');
element.name = 'Priority';
element.section = 'refs/*';
element.labels = {
@@ -352,7 +331,7 @@
});
test('removing an added permission', () => {
- const removeStub = sandbox.stub();
+ const removeStub = sinon.stub();
element.addEventListener('added-permission-removed', removeStub);
element.editing = true;
element.name = 'Priority';
@@ -367,7 +346,7 @@
element.name = 'Priority';
element.section = 'refs/*';
- const removeStub = sandbox.stub();
+ const removeStub = sinon.stub();
element.addEventListener('added-permission-removed', removeStub);
assert.isFalse(element.$.permission.classList.contains('deleted'));
@@ -399,7 +378,7 @@
});
test('_handleValueChange', () => {
- const modifiedHandler = sandbox.stub();
+ const modifiedHandler = sinon.stub();
element.permission = {value: {rules: {}}};
element.addEventListener('access-modified', modifiedHandler);
assert.isNotOk(element.permission.value.modified);
@@ -431,4 +410,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/admin/gr-plugin-config-array-editor/gr-plugin-config-array-editor_test.html b/polygerrit-ui/app/elements/admin/gr-plugin-config-array-editor/gr-plugin-config-array-editor_test.js
similarity index 65%
rename from polygerrit-ui/app/elements/admin/gr-plugin-config-array-editor/gr-plugin-config-array-editor_test.html
rename to polygerrit-ui/app/elements/admin/gr-plugin-config-array-editor/gr-plugin-config-array-editor_test.js
index 5eff42d..9e9eb1c 100644
--- a/polygerrit-ui/app/elements/admin/gr-plugin-config-array-editor/gr-plugin-config-array-editor_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-plugin-config-array-editor/gr-plugin-config-array-editor_test.js
@@ -1,50 +1,35 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2018 The Android Open Source Project
+/**
+ * @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.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-plugin-config-array-editor</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-plugin-config-array-editor></gr-plugin-config-array-editor>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-plugin-config-array-editor.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+
+const basicFixture = fixtureFromElement('gr-plugin-config-array-editor');
+
suite('gr-plugin-config-array-editor tests', () => {
let element;
- let sandbox;
+
let dispatchStub;
const getAll = str => dom(element.root).querySelectorAll(str);
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.pluginOption = {
_key: 'test-key',
info: {
@@ -53,8 +38,6 @@
};
});
- teardown(() => sandbox.restore());
-
test('_computeShowInputRow', () => {
assert.equal(element._computeShowInputRow(true), 'hide');
assert.equal(element._computeShowInputRow(false), '');
@@ -72,7 +55,7 @@
suite('adding', () => {
setup(() => {
- dispatchStub = sandbox.stub(element, '_dispatchChanged');
+ dispatchStub = sinon.stub(element, '_dispatchChanged');
});
test('with enter', () => {
@@ -107,7 +90,7 @@
});
test('deleting', () => {
- dispatchStub = sandbox.stub(element, '_dispatchChanged');
+ dispatchStub = sinon.stub(element, '_dispatchChanged');
element.pluginOption = {info: {values: ['test', 'test2']}};
flushAsynchronousOperations();
@@ -131,7 +114,7 @@
});
test('_dispatchChanged', () => {
- const eventStub = sandbox.stub(element, 'dispatchEvent');
+ const eventStub = sinon.stub(element, 'dispatchEvent');
element._dispatchChanged(['new-test-value']);
assert.isTrue(eventStub.called);
@@ -141,4 +124,4 @@
assert.equal(detail.notifyPath, 'test-key.values');
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/admin/gr-plugin-list/gr-plugin-list_test.html b/polygerrit-ui/app/elements/admin/gr-plugin-list/gr-plugin-list_test.js
similarity index 70%
rename from polygerrit-ui/app/elements/admin/gr-plugin-list/gr-plugin-list_test.html
rename to polygerrit-ui/app/elements/admin/gr-plugin-list/gr-plugin-list_test.js
index e2c88a2..a73c7cf 100644
--- a/polygerrit-ui/app/elements/admin/gr-plugin-list/gr-plugin-list_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-plugin-list/gr-plugin-list_test.js
@@ -1,41 +1,26 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-plugin-list</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/page/page.js"></script>
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-plugin-list></gr-plugin-list>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-plugin-list.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+
+const basicFixture = fixtureFromElement('gr-plugin-list');
+
let counter;
const pluginGenerator = () => {
const plugin = {
@@ -53,19 +38,14 @@
suite('gr-plugin-list tests', () => {
let element;
let plugins;
- let sandbox;
+
let value;
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
+ element = basicFixture.instantiate();
counter = 0;
});
- teardown(() => {
- sandbox.restore();
- });
-
suite('list with plugins', () => {
setup(done => {
plugins = _.times(26, pluginGenerator);
@@ -125,10 +105,10 @@
suite('filter', () => {
test('_paramsChanged', done => {
- sandbox.stub(
+ sinon.stub(
element.$.restAPI,
- 'getPlugins',
- () => Promise.resolve(plugins));
+ 'getPlugins')
+ .callsFake(() => Promise.resolve(plugins));
const value = {
filter: 'test',
offset: 25,
@@ -163,7 +143,7 @@
suite('404', () => {
test('fires page-error', done => {
const response = {status: 404};
- sandbox.stub(element.$.restAPI, 'getPlugins',
+ sinon.stub(element.$.restAPI, 'getPlugins').callsFake(
(filter, pluginsPerPage, opt_offset, errFn) => {
errFn(response);
});
@@ -181,4 +161,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access_html.js b/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access_html.js
index b46c7c0..8148884 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access_html.js
+++ b/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access_html.js
@@ -37,6 +37,9 @@
.weblink {
margin-right: var(--spacing-xs);
}
+ gr-access-section {
+ margin-top: var(--spacing-l);
+ }
.weblinks.show,
.referenceContainer {
display: block;
@@ -94,25 +97,6 @@
</a>
</template>
</div>
- <gr-button id="editBtn" on-click="_handleEdit"
- >[[_editOrCancel(_editing)]]</gr-button
- >
- <gr-button
- id="saveBtn"
- primary=""
- class$="[[_computeSaveBtnClass(_ownerOf)]]"
- on-click="_handleSave"
- disabled="[[!_modified]]"
- >Save</gr-button
- >
- <gr-button
- id="saveReviewBtn"
- primary=""
- class$="[[_computeSaveReviewBtnClass(_canUpload)]]"
- on-click="_handleSaveForReview"
- disabled="[[!_modified]]"
- >Save for review</gr-button
- >
<template
is="dom-repeat"
items="{{_sections}}"
@@ -136,6 +120,27 @@
>Add Reference</gr-button
>
</div>
+ <div>
+ <gr-button id="editBtn" on-click="_handleEdit"
+ >[[_editOrCancel(_editing)]]</gr-button
+ >
+ <gr-button
+ id="saveBtn"
+ primary=""
+ class$="[[_computeSaveBtnClass(_ownerOf)]]"
+ on-click="_handleSave"
+ disabled="[[!_modified]]"
+ >Save</gr-button
+ >
+ <gr-button
+ id="saveReviewBtn"
+ primary=""
+ class$="[[_computeSaveReviewBtnClass(_canUpload)]]"
+ on-click="_handleSaveForReview"
+ disabled="[[!_modified]]"
+ >Save for review</gr-button
+ >
+ </div>
</div>
</main>
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access_test.html b/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access_test.js
similarity index 92%
rename from polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access_test.html
rename to polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access_test.js
index 7d66cb0..0248dfc 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access_test.js
@@ -1,46 +1,30 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-repo-access</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/page/page.js"></script>
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-repo-access></gr-repo-access>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-repo-access.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
+const basicFixture = fixtureFromElement('gr-repo-access');
+
suite('gr-repo-access tests', () => {
let element;
- let sandbox;
+
let repoStub;
const accessRes = {
@@ -115,37 +99,32 @@
},
};
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
+ element = basicFixture.instantiate();
stub('gr-rest-api-interface', {
getAccount() { return Promise.resolve(null); },
});
- repoStub = sandbox.stub(element.$.restAPI, 'getRepo').returns(
+ repoStub = sinon.stub(element.$.restAPI, 'getRepo').returns(
Promise.resolve(repoRes));
element._loading = false;
element._ownerOf = [];
element._canUpload = false;
});
- teardown(() => {
- sandbox.restore();
- });
-
test('_repoChanged called when repo name changes', () => {
- sandbox.stub(element, '_repoChanged');
+ sinon.stub(element, '_repoChanged');
element.repo = 'New Repo';
assert.isTrue(element._repoChanged.called);
});
test('_repoChanged', done => {
- const accessStub = sandbox.stub(element.$.restAPI,
+ const accessStub = sinon.stub(element.$.restAPI,
'getRepoAccessRights');
accessStub.withArgs('New Repo').returns(
Promise.resolve(JSON.parse(JSON.stringify(accessRes))));
accessStub.withArgs('Another New Repo')
.returns(Promise.resolve(JSON.parse(JSON.stringify(accessRes2))));
- const capabilitiesStub = sandbox.stub(element.$.restAPI,
+ const capabilitiesStub = sinon.stub(element.$.restAPI,
'getCapabilities');
capabilitiesStub.returns(Promise.resolve(capabilitiesRes));
@@ -180,9 +159,9 @@
name: 'Access Database',
},
};
- const accessStub = sandbox.stub(element.$.restAPI, 'getRepoAccessRights')
+ const accessStub = sinon.stub(element.$.restAPI, 'getRepoAccessRights')
.returns(Promise.resolve(JSON.parse(JSON.stringify(accessRes2))));
- const capabilitiesStub = sandbox.stub(element.$.restAPI,
+ const capabilitiesStub = sinon.stub(element.$.restAPI,
'getCapabilities').returns(Promise.resolve(capabilitiesRes));
element._repoChanged().then(() => {
@@ -215,7 +194,7 @@
test('inherit section', () => {
element._local = {};
element._ownerOf = [];
- sandbox.stub(element, '_computeParentHref');
+ sinon.stub(element, '_computeParentHref');
// Nothing should appear when no inherit from and not in edit mode.
assert.equal(getComputedStyle(element.$.inheritsFrom).display, 'none');
// The autocomplete should be hidden, and the link should be displayed.
@@ -260,8 +239,9 @@
test('fires page-error', done => {
const response = {status: 404};
- sandbox.stub(
- element.$.restAPI, 'getRepoAccessRights', (repoName, errFn) => {
+ sinon.stub(
+ element.$.restAPI, 'getRepoAccessRights')
+ .callsFake((repoName, errFn) => {
errFn(response);
});
@@ -368,7 +348,7 @@
});
test('_handleAccessModified called with event fired', () => {
- sandbox.spy(element, '_handleAccessModified');
+ sinon.spy(element, '_handleAccessModified');
element.dispatchEvent(
new CustomEvent('access-modified', {
composed: true, bubbles: true,
@@ -386,7 +366,7 @@
detail: {},
composed: true, bubbles: true,
}));
- sandbox.spy(element, '_handleAccessModified');
+ sinon.spy(element, '_handleAccessModified');
element.dispatchEvent(
new CustomEvent('access-modified', {
detail: {},
@@ -397,8 +377,8 @@
test('_handleSaveForReview', () => {
const saveStub =
- sandbox.stub(element.$.restAPI, 'setRepoAccessRightsForReview');
- sandbox.stub(element, '_computeAddAndRemove').returns({
+ sinon.stub(element.$.restAPI, 'setRepoAccessRightsForReview');
+ sinon.stub(element, '_computeAddAndRemove').returns({
add: {},
remove: {},
});
@@ -1180,16 +1160,16 @@
},
},
};
- sandbox.stub(element.$.restAPI, 'getRepoAccessRights').returns(
+ sinon.stub(element.$.restAPI, 'getRepoAccessRights').returns(
Promise.resolve(JSON.parse(JSON.stringify(accessRes))));
- sandbox.stub(GerritNav, 'navigateToChange');
+ sinon.stub(GerritNav, 'navigateToChange');
let resolver;
- const saveStub = sandbox.stub(element.$.restAPI,
+ const saveStub = sinon.stub(element.$.restAPI,
'setRepoAccessRights')
.returns(new Promise(r => resolver = r));
element.repo = 'test-repo';
- sandbox.stub(element, '_computeAddAndRemove').returns(repoAccessInput);
+ sinon.stub(element, '_computeAddAndRemove').returns(repoAccessInput);
element._modified = true;
MockInteractions.tap(element.$.saveBtn);
@@ -1227,16 +1207,16 @@
},
},
};
- sandbox.stub(element.$.restAPI, 'getRepoAccessRights').returns(
+ sinon.stub(element.$.restAPI, 'getRepoAccessRights').returns(
Promise.resolve(JSON.parse(JSON.stringify(accessRes))));
- sandbox.stub(GerritNav, 'navigateToChange');
+ sinon.stub(GerritNav, 'navigateToChange');
let resolver;
- const saveForReviewStub = sandbox.stub(element.$.restAPI,
+ const saveForReviewStub = sinon.stub(element.$.restAPI,
'setRepoAccessRightsForReview')
.returns(new Promise(r => resolver = r));
element.repo = 'test-repo';
- sandbox.stub(element, '_computeAddAndRemove').returns(repoAccessInput);
+ sinon.stub(element, '_computeAddAndRemove').returns(repoAccessInput);
element._modified = true;
MockInteractions.tap(element.$.saveReviewBtn);
@@ -1251,4 +1231,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands_test.html b/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands_test.html
deleted file mode 100644
index a52ab92..0000000
--- a/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands_test.html
+++ /dev/null
@@ -1,153 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-repo-commands</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/page/page.js"></script>
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-repo-commands></gr-repo-commands>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-repo-commands.js';
-import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
-
-suite('gr-repo-commands tests', () => {
- let element;
- let sandbox;
- let repoStub;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- repoStub = sandbox.stub(
- element.$.restAPI,
- 'getProjectConfig',
- () => Promise.resolve({}));
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- suite('create new change dialog', () => {
- test('_createNewChange opens modal', () => {
- const openStub = sandbox.stub(element.$.createChangeOverlay, 'open');
- element._createNewChange();
- assert.isTrue(openStub.called);
- });
-
- test('_handleCreateChange called when confirm fired', () => {
- sandbox.stub(element, '_handleCreateChange');
- element.$.createChangeDialog.dispatchEvent(
- new CustomEvent('confirm', {
- composed: true, bubbles: true,
- }));
- assert.isTrue(element._handleCreateChange.called);
- });
-
- test('_handleCloseCreateChange called when cancel fired', () => {
- sandbox.stub(element, '_handleCloseCreateChange');
- element.$.createChangeDialog.dispatchEvent(
- new CustomEvent('cancel', {
- composed: true, bubbles: true,
- }));
- assert.isTrue(element._handleCloseCreateChange.called);
- });
- });
-
- suite('edit repo config', () => {
- let createChangeStub;
- let urlStub;
- let handleSpy;
- let alertStub;
-
- setup(() => {
- createChangeStub = sandbox.stub(element.$.restAPI, 'createChange');
- urlStub = sandbox.stub(GerritNav, 'getEditUrlForDiff');
- sandbox.stub(GerritNav, 'navigateToRelativeUrl');
- handleSpy = sandbox.spy(element, '_handleEditRepoConfig');
- alertStub = sandbox.stub();
- element.addEventListener('show-alert', alertStub);
- });
-
- test('successful creation of change', () => {
- const change = {_number: '1'};
- createChangeStub.returns(Promise.resolve(change));
- MockInteractions.tap(element.$.editRepoConfig);
- assert.isTrue(element.$.editRepoConfig.loading);
- return handleSpy.lastCall.returnValue.then(() => {
- flushAsynchronousOperations();
-
- assert.isTrue(alertStub.called);
- assert.equal(alertStub.lastCall.args[0].detail.message,
- 'Navigating to change');
- assert.isTrue(urlStub.called);
- assert.deepEqual(urlStub.lastCall.args,
- [change, 'project.config', 1]);
- assert.isFalse(element.$.editRepoConfig.loading);
- });
- });
-
- test('unsuccessful creation of change', () => {
- createChangeStub.returns(Promise.resolve(null));
- MockInteractions.tap(element.$.editRepoConfig);
- assert.isTrue(element.$.editRepoConfig.loading);
- return handleSpy.lastCall.returnValue.then(() => {
- flushAsynchronousOperations();
-
- assert.isTrue(alertStub.called);
- assert.equal(alertStub.lastCall.args[0].detail.message,
- 'Failed to create change.');
- assert.isFalse(urlStub.called);
- assert.isFalse(element.$.editRepoConfig.loading);
- });
- });
- });
-
- suite('404', () => {
- test('fires page-error', done => {
- repoStub.restore();
-
- element.repo = 'test';
-
- const response = {status: 404};
- sandbox.stub(
- element.$.restAPI, 'getProjectConfig', (repo, errFn) => {
- errFn(response);
- });
- element.addEventListener('page-error', e => {
- assert.deepEqual(e.detail.response, response);
- done();
- });
-
- element._loadRepo();
- });
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands_test.js b/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands_test.js
new file mode 100644
index 0000000..0bb0c55
--- /dev/null
+++ b/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands_test.js
@@ -0,0 +1,133 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-repo-commands.js';
+import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
+
+const basicFixture = fixtureFromElement('gr-repo-commands');
+
+suite('gr-repo-commands tests', () => {
+ let element;
+
+ let repoStub;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ repoStub = sinon.stub(
+ element.$.restAPI,
+ 'getProjectConfig')
+ .callsFake(() => Promise.resolve({}));
+ });
+
+ suite('create new change dialog', () => {
+ test('_createNewChange opens modal', () => {
+ const openStub = sinon.stub(element.$.createChangeOverlay, 'open');
+ element._createNewChange();
+ assert.isTrue(openStub.called);
+ });
+
+ test('_handleCreateChange called when confirm fired', () => {
+ sinon.stub(element, '_handleCreateChange');
+ element.$.createChangeDialog.dispatchEvent(
+ new CustomEvent('confirm', {
+ composed: true, bubbles: true,
+ }));
+ assert.isTrue(element._handleCreateChange.called);
+ });
+
+ test('_handleCloseCreateChange called when cancel fired', () => {
+ sinon.stub(element, '_handleCloseCreateChange');
+ element.$.createChangeDialog.dispatchEvent(
+ new CustomEvent('cancel', {
+ composed: true, bubbles: true,
+ }));
+ assert.isTrue(element._handleCloseCreateChange.called);
+ });
+ });
+
+ suite('edit repo config', () => {
+ let createChangeStub;
+ let urlStub;
+ let handleSpy;
+ let alertStub;
+
+ setup(() => {
+ createChangeStub = sinon.stub(element.$.restAPI, 'createChange');
+ urlStub = sinon.stub(GerritNav, 'getEditUrlForDiff');
+ sinon.stub(GerritNav, 'navigateToRelativeUrl');
+ handleSpy = sinon.spy(element, '_handleEditRepoConfig');
+ alertStub = sinon.stub();
+ element.addEventListener('show-alert', alertStub);
+ });
+
+ test('successful creation of change', () => {
+ const change = {_number: '1'};
+ createChangeStub.returns(Promise.resolve(change));
+ MockInteractions.tap(element.$.editRepoConfig);
+ assert.isTrue(element.$.editRepoConfig.loading);
+ return handleSpy.lastCall.returnValue.then(() => {
+ flushAsynchronousOperations();
+
+ assert.isTrue(alertStub.called);
+ assert.equal(alertStub.lastCall.args[0].detail.message,
+ 'Navigating to change');
+ assert.isTrue(urlStub.called);
+ assert.deepEqual(urlStub.lastCall.args,
+ [change, 'project.config', 1]);
+ assert.isFalse(element.$.editRepoConfig.loading);
+ });
+ });
+
+ test('unsuccessful creation of change', () => {
+ createChangeStub.returns(Promise.resolve(null));
+ MockInteractions.tap(element.$.editRepoConfig);
+ assert.isTrue(element.$.editRepoConfig.loading);
+ return handleSpy.lastCall.returnValue.then(() => {
+ flushAsynchronousOperations();
+
+ assert.isTrue(alertStub.called);
+ assert.equal(alertStub.lastCall.args[0].detail.message,
+ 'Failed to create change.');
+ assert.isFalse(urlStub.called);
+ assert.isFalse(element.$.editRepoConfig.loading);
+ });
+ });
+ });
+
+ suite('404', () => {
+ test('fires page-error', done => {
+ repoStub.restore();
+
+ element.repo = 'test';
+
+ const response = {status: 404};
+ sinon.stub(
+ element.$.restAPI, 'getProjectConfig')
+ .callsFake((repo, errFn) => {
+ errFn(response);
+ });
+ element.addEventListener('page-error', e => {
+ assert.deepEqual(e.detail.response, response);
+ done();
+ });
+
+ element._loadRepo();
+ });
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-dashboards/gr-repo-dashboards_test.html b/polygerrit-ui/app/elements/admin/gr-repo-dashboards/gr-repo-dashboards_test.js
similarity index 67%
rename from polygerrit-ui/app/elements/admin/gr-repo-dashboards/gr-repo-dashboards_test.html
rename to polygerrit-ui/app/elements/admin/gr-repo-dashboards/gr-repo-dashboards_test.js
index dc12eff..b4d3575 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-dashboards/gr-repo-dashboards_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-repo-dashboards/gr-repo-dashboards_test.js
@@ -1,57 +1,36 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-repo-dashboards</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-repo-dashboards></gr-repo-dashboards>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-repo-dashboards.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
+const basicFixture = fixtureFromElement('gr-repo-dashboards');
+
suite('gr-repo-dashboards tests', () => {
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- });
-
- teardown(() => {
- sandbox.restore();
+ element = basicFixture.instantiate();
});
suite('dashboard table', () => {
setup(() => {
- sandbox.stub(element.$.restAPI, 'getRepoDashboards').returns(
+ sinon.stub(element.$.restAPI, 'getRepoDashboards').returns(
Promise.resolve([
{
id: 'default:contributor',
@@ -132,7 +111,7 @@
suite('test url', () => {
test('_getUrl', () => {
- sandbox.stub(GerritNav, 'getUrlForRepoDashboard',
+ sinon.stub(GerritNav, 'getUrlForRepoDashboard').callsFake(
() => '/r/dashboard/test');
assert.equal(element._getUrl('/dashboard/test', {}), '/r/dashboard/test');
@@ -144,8 +123,9 @@
suite('404', () => {
test('fires page-error', done => {
const response = {status: 404};
- sandbox.stub(
- element.$.restAPI, 'getRepoDashboards', (repo, errFn) => {
+ sinon.stub(
+ element.$.restAPI, 'getRepoDashboards')
+ .callsFake((repo, errFn) => {
errFn(response);
});
@@ -158,4 +138,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-detail-list/gr-repo-detail-list_test.html b/polygerrit-ui/app/elements/admin/gr-repo-detail-list/gr-repo-detail-list_test.js
similarity index 84%
rename from polygerrit-ui/app/elements/admin/gr-repo-detail-list/gr-repo-detail-list_test.html
rename to polygerrit-ui/app/elements/admin/gr-repo-detail-list/gr-repo-detail-list_test.js
index 9d7bba4..7190218 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-detail-list/gr-repo-detail-list_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-repo-detail-list/gr-repo-detail-list_test.js
@@ -1,42 +1,27 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-repo-detail-list</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/page/page.js"></script>
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-repo-detail-list></gr-repo-detail-list>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-repo-detail-list.js';
import page from 'page/page.mjs';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+
+const basicFixture = fixtureFromElement('gr-repo-detail-list');
+
let counter;
const branchGenerator = () => {
return {
@@ -74,18 +59,12 @@
suite('Branches', () => {
let element;
let branches;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.detailType = 'branches';
counter = 0;
- sandbox.stub(page, 'show');
- });
-
- teardown(() => {
- sandbox.restore();
+ sinon.stub(page, 'show');
});
suite('list of repo branches', () => {
@@ -137,8 +116,8 @@
});
test('Edit HEAD button not admin', done => {
- sandbox.stub(element, '_getLoggedIn').returns(Promise.resolve(true));
- sandbox.stub(element.$.restAPI, 'getRepoAccess').returns(
+ sinon.stub(element, '_getLoggedIn').returns(Promise.resolve(true));
+ sinon.stub(element.$.restAPI, 'getRepoAccess').returns(
Promise.resolve({
test: {is_owner: false},
}));
@@ -161,12 +140,12 @@
const revisionWithEditing = dom(element.root)
.querySelector('.revisionWithEditing');
- sandbox.stub(element, '_getLoggedIn').returns(Promise.resolve(true));
- sandbox.stub(element.$.restAPI, 'getRepoAccess').returns(
+ sinon.stub(element, '_getLoggedIn').returns(Promise.resolve(true));
+ sinon.stub(element.$.restAPI, 'getRepoAccess').returns(
Promise.resolve({
test: {is_owner: true},
}));
- sandbox.stub(element, '_handleSaveRevision');
+ sinon.stub(element, '_handleSaveRevision');
element._determineIfOwner('test').then(() => {
assert.equal(element._isOwner, true);
// The revision container for non-editing enabled row is not visible.
@@ -237,9 +216,9 @@
});
test('_handleSaveRevision with invalid rev', done => {
- const event = {model: {set: sandbox.stub()}};
+ const event = {model: {set: sinon.stub()}};
element._isEditing = true;
- sandbox.stub(element.$.restAPI, 'setRepoHead').returns(
+ sinon.stub(element.$.restAPI, 'setRepoHead').returns(
Promise.resolve({
status: 400,
})
@@ -253,9 +232,9 @@
});
test('_handleSaveRevision with valid rev', done => {
- const event = {model: {set: sandbox.stub()}};
+ const event = {model: {set: sinon.stub()}};
element._isEditing = true;
- sandbox.stub(element.$.restAPI, 'setRepoHead').returns(
+ sinon.stub(element.$.restAPI, 'setRepoHead').returns(
Promise.resolve({
status: 200,
})
@@ -299,10 +278,10 @@
suite('filter', () => {
test('_paramsChanged', done => {
- sandbox.stub(
+ sinon.stub(
element.$.restAPI,
- 'getRepoBranches',
- () => Promise.resolve(branches));
+ 'getRepoBranches')
+ .callsFake(() => Promise.resolve(branches));
const params = {
detail: 'branches',
repo: 'test',
@@ -326,7 +305,7 @@
suite('404', () => {
test('fires page-error', done => {
const response = {status: 404};
- sandbox.stub(element.$.restAPI, 'getRepoBranches',
+ sinon.stub(element.$.restAPI, 'getRepoBranches').callsFake(
(filter, repo, reposBranchesPerPage, opt_offset, errFn) => {
errFn(response);
});
@@ -350,18 +329,12 @@
suite('Tags', () => {
let element;
let tags;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.detailType = 'tags';
counter = 0;
- sandbox.stub(page, 'show');
- });
-
- teardown(() => {
- sandbox.restore();
+ sinon.stub(page, 'show');
});
test('_computeMessage', () => {
@@ -483,10 +456,10 @@
suite('filter', () => {
test('_paramsChanged', done => {
- sandbox.stub(
+ sinon.stub(
element.$.restAPI,
- 'getRepoTags',
- () => Promise.resolve(tags));
+ 'getRepoTags')
+ .callsFake(() => Promise.resolve(tags));
const params = {
repo: 'test',
detail: 'tags',
@@ -509,7 +482,7 @@
suite('create new', () => {
test('_handleCreateClicked called when create-click fired', () => {
- sandbox.stub(element, '_handleCreateClicked');
+ sinon.stub(element, '_handleCreateClicked');
element.shadowRoot
.querySelector('gr-list-view').dispatchEvent(
new CustomEvent('create-clicked', {
@@ -519,13 +492,13 @@
});
test('_handleCreateClicked opens modal', () => {
- const openStub = sandbox.stub(element.$.createOverlay, 'open');
+ const openStub = sinon.stub(element.$.createOverlay, 'open');
element._handleCreateClicked();
assert.isTrue(openStub.called);
});
test('_handleCreateItem called when confirm fired', () => {
- sandbox.stub(element, '_handleCreateItem');
+ sinon.stub(element, '_handleCreateItem');
element.$.createDialog.dispatchEvent(
new CustomEvent('confirm', {
composed: true, bubbles: true,
@@ -534,7 +507,7 @@
});
test('_handleCloseCreate called when cancel fired', () => {
- sandbox.stub(element, '_handleCloseCreate');
+ sinon.stub(element, '_handleCloseCreate');
element.$.createDialog.dispatchEvent(
new CustomEvent('cancel', {
composed: true, bubbles: true,
@@ -546,7 +519,7 @@
suite('404', () => {
test('fires page-error', done => {
const response = {status: 404};
- sandbox.stub(element.$.restAPI, 'getRepoTags',
+ sinon.stub(element.$.restAPI, 'getRepoTags').callsFake(
(filter, repo, reposTagsPerPage, opt_offset, errFn) => {
errFn(response);
});
@@ -573,4 +546,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list_test.html b/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list_test.js
similarity index 69%
rename from polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list_test.html
rename to polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list_test.js
index 96cb9ff..b629cf4 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list_test.js
@@ -1,42 +1,26 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-repo-list</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/page/page.js"></script>
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-repo-list></gr-repo-list>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-repo-list.js';
import page from 'page/page.mjs';
+const basicFixture = fixtureFromElement('gr-repo-list');
+
let counter;
const repoGenerator = () => {
return {
@@ -54,20 +38,15 @@
suite('gr-repo-list tests', () => {
let element;
let repos;
- let sandbox;
+
let value;
setup(() => {
- sandbox = sinon.sandbox.create();
- sandbox.stub(page, 'show');
- element = fixture('basic');
+ sinon.stub(page, 'show');
+ element = basicFixture.instantiate();
counter = 0;
});
- teardown(() => {
- sandbox.restore();
- });
-
suite('list with repos', () => {
setup(done => {
repos = _.times(26, repoGenerator);
@@ -91,7 +70,7 @@
});
test('_maybeOpenCreateOverlay', () => {
- const overlayOpen = sandbox.stub(element.$.createOverlay, 'open');
+ const overlayOpen = sinon.stub(element.$.createOverlay, 'open');
element._maybeOpenCreateOverlay();
assert.isFalse(overlayOpen.called);
const params = {};
@@ -129,7 +108,8 @@
});
test('_paramsChanged', done => {
- sandbox.stub(element.$.restAPI, 'getRepos', () => Promise.resolve(repos));
+ sinon.stub(element.$.restAPI, 'getRepos')
+ .callsFake( () => Promise.resolve(repos));
const value = {
filter: 'test',
offset: 25,
@@ -142,7 +122,7 @@
});
test('latest repos requested are always set', done => {
- const repoStub = sandbox.stub(element.$.restAPI, 'getRepos');
+ const repoStub = sinon.stub(element.$.restAPI, 'getRepos');
repoStub.withArgs('test').returns(Promise.resolve(repos));
repoStub.withArgs('filter').returns(Promise.resolve(reposFiltered));
element._filter = 'test';
@@ -172,7 +152,7 @@
suite('create new', () => {
test('_handleCreateClicked called when create-click fired', () => {
- sandbox.stub(element, '_handleCreateClicked');
+ sinon.stub(element, '_handleCreateClicked');
element.shadowRoot
.querySelector('gr-list-view').dispatchEvent(
new CustomEvent('create-clicked', {
@@ -182,13 +162,13 @@
});
test('_handleCreateClicked opens modal', () => {
- const openStub = sandbox.stub(element.$.createOverlay, 'open');
+ const openStub = sinon.stub(element.$.createOverlay, 'open');
element._handleCreateClicked();
assert.isTrue(openStub.called);
});
test('_handleCreateRepo called when confirm fired', () => {
- sandbox.stub(element, '_handleCreateRepo');
+ sinon.stub(element, '_handleCreateRepo');
element.$.createDialog.dispatchEvent(
new CustomEvent('confirm', {
composed: true, bubbles: true,
@@ -197,7 +177,7 @@
});
test('_handleCloseCreate called when cancel fired', () => {
- sandbox.stub(element, '_handleCloseCreate');
+ sinon.stub(element, '_handleCloseCreate');
element.$.createDialog.dispatchEvent(
new CustomEvent('cancel', {
composed: true, bubbles: true,
@@ -206,4 +186,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config.js b/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config.js
index a70aa11..fba5e4e 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config.js
+++ b/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config.js
@@ -150,6 +150,13 @@
this.dispatchEvent(new CustomEvent(
this.PLUGIN_CONFIG_CHANGED, {detail, bubbles: true, composed: true}));
}
+
+ /**
+ * Work around a issue on iOS when clicking turns into double tap
+ */
+ _onTapPluginBoolean(e) {
+ e.preventDefault();
+ }
}
customElements.define(GrRepoPluginConfig.is, GrRepoPluginConfig);
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config_html.js b/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config_html.js
index 80d77d6..ee633463 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config_html.js
+++ b/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config_html.js
@@ -63,6 +63,7 @@
on-change="_handleBooleanChange"
data-option-key$="[[option._key]]"
disabled$="[[_computeDisabled(option.info.editable)]]"
+ on-tap="_onTapPluginBoolean"
></paper-toggle-button>
</template>
<template is="dom-if" if="[[_isList(option.info.type)]]">
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config_test.html b/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config_test.js
similarity index 72%
rename from polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config_test.html
rename to polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config_test.js
index a2370d9..1730839 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config_test.js
@@ -1,50 +1,32 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2018 The Android Open Source Project
+/**
+ * @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.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-repo-plugin-config</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-repo-plugin-config></gr-repo-plugin-config>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-repo-plugin-config.js';
+
+const basicFixture = fixtureFromElement('gr-repo-plugin-config');
+
suite('gr-repo-plugin-config tests', () => {
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
+ element = basicFixture.instantiate();
});
- teardown(() => sandbox.restore());
-
test('_computePluginConfigOptions', () => {
assert.deepEqual(element._computePluginConfigOptions(), []);
assert.deepEqual(element._computePluginConfigOptions({}), []);
@@ -62,7 +44,7 @@
});
test('_handleChange', () => {
- const eventStub = sandbox.stub(element, 'dispatchEvent');
+ const eventStub = sinon.stub(element, 'dispatchEvent');
element.pluginData = {
name: 'testName',
config: {plugin: {value: 'test'}},
@@ -86,8 +68,8 @@
let buildStub;
setup(() => {
- changeStub = sandbox.stub(element, '_handleChange');
- buildStub = sandbox.stub(element, '_buildConfigChangeInfo');
+ changeStub = sinon.stub(element, '_handleChange');
+ buildStub = sinon.stub(element, '_buildConfigChangeInfo');
});
test('ARRAY type option', () => {
@@ -178,4 +160,4 @@
assert.equal(detail.notifyPath, 'plugin.value');
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo_test.html b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo_test.js
similarity index 83%
rename from polygerrit-ui/app/elements/admin/gr-repo/gr-repo_test.html
rename to polygerrit-ui/app/elements/admin/gr-repo/gr-repo_test.js
index 58b488a..3b42e3b 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo_test.js
@@ -1,44 +1,30 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-repo</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-repo></gr-repo>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-repo.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
+
+const basicFixture = fixtureFromElement('gr-repo');
+
suite('gr-repo tests', () => {
let element;
- let sandbox;
+
let repoStub;
const repoConf = {
description: 'Access inherited by all other projects.',
@@ -113,22 +99,17 @@
}
setup(() => {
- sandbox = sinon.sandbox.create();
stub('gr-rest-api-interface', {
getLoggedIn() { return Promise.resolve(false); },
getConfig() {
return Promise.resolve({download: {}});
},
});
- element = fixture('basic');
- repoStub = sandbox.stub(
+ element = basicFixture.instantiate();
+ repoStub = sinon.stub(
element.$.restAPI,
- 'getProjectConfig',
- () => Promise.resolve(repoConf));
- });
-
- teardown(() => {
- sandbox.restore();
+ 'getProjectConfig')
+ .callsFake(() => Promise.resolve(repoConf));
});
test('_computePluginData', () => {
@@ -140,7 +121,7 @@
});
test('_handlePluginConfigChanged', () => {
- const notifyStub = sandbox.stub(element, 'notifyPath');
+ const notifyStub = sinon.stub(element, 'notifyPath');
element._repoConfig = {plugin_config: {}};
element._handlePluginConfigChanged({detail: {
name: 'test',
@@ -189,11 +170,11 @@
test('form defaults to read only when logged in and not admin', done => {
element.repo = REPO;
- sandbox.stub(element, '_getLoggedIn', () => Promise.resolve(true));
- sandbox.stub(
+ sinon.stub(element, '_getLoggedIn').callsFake(() => Promise.resolve(true));
+ sinon.stub(
element.$.restAPI,
- 'getRepoAccess',
- () => Promise.resolve({'test-repo': {}}));
+ 'getRepoAccess')
+ .callsFake(() => Promise.resolve({'test-repo': {}}));
element._loadRepo().then(() => {
assert.isTrue(element._readOnly);
done();
@@ -266,10 +247,10 @@
element.repo = 'test';
const response = {status: 404};
- sandbox.stub(
- element.$.restAPI, 'getProjectConfig', (repo, errFn) => {
- errFn(response);
- });
+ sinon.stub(
+ element.$.restAPI, 'getProjectConfig').callsFake((repo, errFn) => {
+ errFn(response);
+ });
element.addEventListener('page-error', e => {
assert.deepEqual(e.detail.response, response);
done();
@@ -281,11 +262,12 @@
suite('admin', () => {
setup(() => {
element.repo = REPO;
- sandbox.stub(element, '_getLoggedIn', () => Promise.resolve(true));
- sandbox.stub(
+ sinon.stub(element, '_getLoggedIn')
+ .callsFake(() => Promise.resolve(true));
+ sinon.stub(
element.$.restAPI,
- 'getRepoAccess',
- () => Promise.resolve({'test-repo': {is_owner: true}}));
+ 'getRepoAccess')
+ .callsFake(() => Promise.resolve({'test-repo': {is_owner: true}}));
});
test('all form elements are enabled', done => {
@@ -341,8 +323,8 @@
enable_reviewer_by_email: 'TRUE',
};
- const saveStub = sandbox.stub(element.$.restAPI, 'saveRepoConfig'
- , () => Promise.resolve({}));
+ const saveStub = sinon.stub(element.$.restAPI, 'saveRepoConfig')
+ .callsFake(() => Promise.resolve({}));
const button = dom(element.root).querySelector('gr-button');
@@ -397,4 +379,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor_test.html b/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor_test.js
similarity index 91%
rename from polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor_test.html
rename to polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor_test.js
index f096eed..9364a50 100644
--- a/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor_test.js
@@ -1,52 +1,31 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-rule-editor</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/page/page.js"></script>
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-rule-editor></gr-rule-editor>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-rule-editor.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+
+const basicFixture = fixtureFromElement('gr-rule-editor');
+
suite('gr-rule-editor tests', () => {
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- });
-
- teardown(() => {
- sandbox.restore();
+ element = basicFixture.instantiate();
});
suite('unit tests', () => {
@@ -148,7 +127,7 @@
test('_setDefaultRuleValues', () => {
element.rule = {id: 123};
const defaultValue = {action: 'ALLOW'};
- sandbox.stub(element, '_getDefaultRuleValues').returns(defaultValue);
+ sinon.stub(element, '_getDefaultRuleValues').returns(defaultValue);
element._setDefaultRuleValues();
assert.isTrue(element._getDefaultRuleValues.called);
assert.equal(element.rule.value, defaultValue);
@@ -171,7 +150,7 @@
});
test('_handleValueChange', () => {
- const modifiedHandler = sandbox.stub();
+ const modifiedHandler = sinon.stub();
element.rule = {value: {}};
element.addEventListener('access-modified', modifiedHandler);
element._handleValueChange();
@@ -361,7 +340,7 @@
test('remove value', () => {
element.editing = true;
- const removeStub = sandbox.stub();
+ const removeStub = sinon.stub();
element.addEventListener('added-rule-removed', removeStub);
MockInteractions.tap(element.$.removeBtn);
flushAsynchronousOperations();
@@ -414,7 +393,7 @@
});
test('modify value', () => {
- const removeStub = sandbox.stub();
+ const removeStub = sinon.stub();
element.addEventListener('added-rule-removed', removeStub);
assert.isNotOk(element.rule.value.modified);
dom(element.root).querySelector('#labelMin').bindValue = 1;
@@ -429,7 +408,7 @@
suite('new rule with labels', () => {
setup(done => {
- sandbox.spy(element, '_setDefaultRuleValues');
+ sinon.spy(element, '_setDefaultRuleValues');
element.label = {values: [
{value: -2, text: 'This shall not be merged'},
{value: -1, text: 'I would prefer this is not merged as is'},
@@ -623,4 +602,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.js b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.js
index a3fe990..d8101c8 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.js
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.js
@@ -37,6 +37,7 @@
import {URLEncodingBehavior} from '../../../behaviors/gr-url-encoding-behavior/gr-url-encoding-behavior.js';
import {RESTClientBehavior} from '../../../behaviors/rest-client-behavior/rest-client-behavior.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
+import {GrDisplayNameUtils} from '../../../scripts/gr-display-name-utils/gr-display-name-utils.js';
import {pluginEndpoints} from '../../shared/gr-js-api-interface/gr-plugin-endpoints.js';
import {pluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
@@ -47,6 +48,9 @@
LARGE: 1000,
};
+// How many reviewers should be shown with an account-label?
+const PRIMARY_REVIEWERS_COUNT = 2;
+
/**
* @appliesMixin RESTClientMixin
* @extends PolymerElement
@@ -66,6 +70,11 @@
static get properties() {
return {
+ /** The logged-in user's account, or null if no user is logged in. */
+ account: {
+ type: Object,
+ value: null,
+ },
visibleChangeTableColumns: Array,
labelNames: {
type: Array,
@@ -73,6 +82,7 @@
/** @type {?} */
change: Object,
+ config: Object,
changeURL: {
type: String,
computed: '_computeChangeURL(change)',
@@ -207,6 +217,49 @@
}
}
+ _hasAttention(account) {
+ if (!this.change || !this.change.attention_set) return false;
+ return this.change.attention_set.hasOwnProperty(account._account_id);
+ }
+
+ /**
+ * Computes the array of all reviewers with sorting the reviewers in the
+ * attention set before others, and the current user first.
+ */
+ _computeReviewers(change) {
+ if (!change || !change.reviewers || !change.reviewers.REVIEWER) return [];
+ const reviewers = [...change.reviewers.REVIEWER];
+ reviewers.sort((r1, r2) => {
+ if (this.account) {
+ if (r1._account_id === this.account._account_id) return -1;
+ if (r2._account_id === this.account._account_id) return 1;
+ }
+ if (this._hasAttention(r1) && !this._hasAttention(r2)) return -1;
+ if (this._hasAttention(r2) && !this._hasAttention(r1)) return 1;
+ return r1.name.localeCompare(r2.name);
+ });
+ return reviewers;
+ }
+
+ _computePrimaryReviewers(change) {
+ return this._computeReviewers(change).slice(0, PRIMARY_REVIEWERS_COUNT);
+ }
+
+ _computeAdditionalReviewers(change) {
+ return this._computeReviewers(change).slice(PRIMARY_REVIEWERS_COUNT);
+ }
+
+ _computeAdditionalReviewersCount(change) {
+ return this._computeAdditionalReviewers(change).length;
+ }
+
+ _computeAdditionalReviewersTitle(change, config) {
+ if (!change || !config) return '';
+ return this._computeAdditionalReviewers(change)
+ .map(user => GrDisplayNameUtils.getDisplayName(config, user))
+ .join(', ');
+ }
+
_computeComments(unresolved_comment_count) {
if (!unresolved_comment_count || unresolved_comment_count < 1) return '';
return `${unresolved_comment_count} unresolved`;
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_html.js b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_html.js
index 4e826aa..cc1bf62 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_html.js
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_html.js
@@ -45,10 +45,20 @@
white-space: nowrap;
width: 100%;
}
+ .content a {
+ display: block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ width: 100%;
+ }
.comments,
.reviewers {
white-space: nowrap;
}
+ .reviewers {
+ --account-max-length: 90px;
+ }
.spacer {
height: 0;
overflow: hidden;
@@ -149,7 +159,11 @@
class="cell owner"
hidden$="[[isColumnHidden('Owner', visibleChangeTableColumns)]]"
>
- <gr-account-link account="[[change.owner]]"></gr-account-link>
+ <gr-account-link
+ highlight-attention
+ change="[[change]]"
+ account="[[change.owner]]"
+ ></gr-account-link>
</td>
<td
class="cell assignee"
@@ -172,16 +186,22 @@
<div>
<template
is="dom-repeat"
- items="[[change.reviewers.REVIEWER]]"
+ items="[[_computePrimaryReviewers(change)]]"
as="reviewer"
>
<gr-account-link
hide-avatar=""
hide-status=""
+ highlight-attention
+ change="[[change]]"
account="[[reviewer]]"
></gr-account-link
- ><!--
- --><span class="lastChildHidden">, </span>
+ ><span class="lastChildHidden">, </span>
+ </template>
+ <template is="dom-if" if="[[_computeAdditionalReviewersCount(change)]]">
+ <span title="[[_computeAdditionalReviewersTitle(change, config)]]">
+ +[[_computeAdditionalReviewersCount(change, config)]]
+ </span>
</template>
</div>
</td>
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_test.html b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_test.js
similarity index 81%
rename from polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_test.html
rename to polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_test.js
index 6b45618..4b9424b 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_test.html
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_test.js
@@ -1,56 +1,37 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2015 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-change-list-item</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-change-list-item></gr-change-list-item>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-change-list-item.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
+const basicFixture = fixtureFromElement('gr-change-list-item');
+
suite('gr-change-list-item tests', () => {
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
stub('gr-rest-api-interface', {
getConfig() { return Promise.resolve({}); },
getLoggedIn() { return Promise.resolve(false); },
});
- element = fixture('basic');
+ element = basicFixture.instantiate();
});
- teardown(() => { sandbox.restore(); });
-
test('computed fields', () => {
assert.equal(element._computeLabelClass({labels: {}}),
'cell label u-gray-background');
@@ -173,6 +154,37 @@
}
});
+ function checkComputeReviewers(
+ userId, reviewerIds, reviewerNames, attSetIds, expected) {
+ element.account = userId ? {_account_id: userId} : null;
+ element.change = {
+ reviewers: {
+ REVIEWER: [],
+ },
+ attention_set: {},
+ };
+ for (let i = 0; i < reviewerIds.length; i++) {
+ element.change.reviewers.REVIEWER.push({
+ _account_id: reviewerIds[i],
+ name: reviewerNames[i],
+ });
+ }
+ attSetIds.forEach(id => element.change.attention_set[id] = {});
+
+ const actual = element._computeReviewers(element.change)
+ .map(r => r._account_id);
+ assert.deepEqual(actual, expected);
+ }
+
+ test('compute reviewers', () => {
+ checkComputeReviewers(null, [], [], [], []);
+ checkComputeReviewers(1, [], [], [], []);
+ checkComputeReviewers(
+ 1, [2, 3, 4, 5], ['b', 'a', 'd', 'c'], [3, 4], [3, 4, 2, 5]);
+ checkComputeReviewers(
+ 1, [2, 3, 1, 4, 5], ['b', 'a', 'x', 'd', 'c'], [3, 4], [1, 3, 4, 2, 5]);
+ });
+
test('random column does not exist', () => {
element.visibleChangeTableColumns = [
'Bad',
@@ -245,7 +257,7 @@
});
test('change params passed to gr-navigation', () => {
- sandbox.stub(GerritNav);
+ sinon.stub(GerritNav);
const change = {
internalHost: 'test-host',
project: 'test-repo',
@@ -278,4 +290,4 @@
'…/test/repo');
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view_test.html b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view_test.js
similarity index 74%
rename from polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view_test.html
rename to polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view_test.js
index 58ec4e1..f945476 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view_test.html
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view_test.js
@@ -1,49 +1,32 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-change-list-view</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/page/page.js"></script>
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-change-list-view></gr-change-list-view>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-change-list-view.js';
import page from 'page/page.mjs';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
+const basicFixture = fixtureFromElement('gr-change-list-view');
+
const CHANGE_ID = 'IcA3dAB3edAB9f60B8dcdA6ef71A75980e4B7127';
const COMMIT_HASH = '12345678';
suite('gr-change-list-view tests', () => {
let element;
- let sandbox;
setup(() => {
stub('gr-rest-api-interface', {
@@ -54,13 +37,11 @@
getAccountDetails() { return Promise.resolve({}); },
getAccountStatus() { return Promise.resolve({}); },
});
- element = fixture('basic');
- sandbox = sinon.sandbox.create();
+ element = basicFixture.instantiate();
});
teardown(done => {
flush(() => {
- sandbox.restore();
done();
});
});
@@ -80,7 +61,7 @@
});
test('_computeNavLink', () => {
- const getUrlStub = sandbox.stub(GerritNav, 'getUrlForSearchQuery')
+ const getUrlStub = sinon.stub(GerritNav, 'getUrlForSearchQuery')
.returns('');
const query = 'status:open';
let offset = 0;
@@ -126,7 +107,7 @@
});
test('_handleNextPage', () => {
- const showStub = sandbox.stub(page, 'show');
+ const showStub = sinon.stub(page, 'show');
element.$.nextArrow.hidden = true;
element._handleNextPage();
assert.isFalse(showStub.called);
@@ -136,7 +117,7 @@
});
test('_handlePreviousPage', () => {
- const showStub = sandbox.stub(page, 'show');
+ const showStub = sinon.stub(page, 'show');
element.$.prevArrow.hidden = true;
element._handlePreviousPage();
assert.isFalse(showStub.called);
@@ -202,16 +183,16 @@
teardown(done => {
flush(() => {
- sandbox.restore();
+ sinon.restore();
done();
});
});
test('Searching for a change ID redirects to change', done => {
const change = {_number: 1};
- sandbox.stub(element, '_getChanges')
+ sinon.stub(element, '_getChanges')
.returns(Promise.resolve([change]));
- sandbox.stub(GerritNav, 'navigateToChange', url => {
+ sinon.stub(GerritNav, 'navigateToChange').callsFake( url => {
assert.equal(url, change);
done();
});
@@ -221,9 +202,9 @@
test('Searching for a change num redirects to change', done => {
const change = {_number: 1};
- sandbox.stub(element, '_getChanges')
+ sinon.stub(element, '_getChanges')
.returns(Promise.resolve([change]));
- sandbox.stub(GerritNav, 'navigateToChange', url => {
+ sinon.stub(GerritNav, 'navigateToChange').callsFake( url => {
assert.equal(url, change);
done();
});
@@ -233,9 +214,9 @@
test('Commit hash redirects to change', done => {
const change = {_number: 1};
- sandbox.stub(element, '_getChanges')
+ sinon.stub(element, '_getChanges')
.returns(Promise.resolve([change]));
- sandbox.stub(GerritNav, 'navigateToChange', url => {
+ sinon.stub(GerritNav, 'navigateToChange').callsFake( url => {
assert.equal(url, change);
done();
});
@@ -244,9 +225,9 @@
});
test('Searching for an invalid change ID searches', () => {
- sandbox.stub(element, '_getChanges')
+ sinon.stub(element, '_getChanges')
.returns(Promise.resolve([]));
- const stub = sandbox.stub(GerritNav, 'navigateToChange');
+ const stub = sinon.stub(GerritNav, 'navigateToChange');
element.params = {view: GerritNav.View.SEARCH, query: CHANGE_ID};
flushAsynchronousOperations();
@@ -255,9 +236,9 @@
});
test('Change ID with multiple search results searches', () => {
- sandbox.stub(element, '_getChanges')
+ sinon.stub(element, '_getChanges')
.returns(Promise.resolve([{}, {}]));
- const stub = sandbox.stub(GerritNav, 'navigateToChange');
+ const stub = sinon.stub(GerritNav, 'navigateToChange');
element.params = {view: GerritNav.View.SEARCH, query: CHANGE_ID};
flushAsynchronousOperations();
@@ -266,4 +247,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js
index baf9920..b238689 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js
@@ -202,7 +202,7 @@
_computePreferences(account, preferences, config) {
// Polymer 2: check for undefined
- if ([account, preferences, config].some(arg => arg === undefined)) {
+ if ([account, preferences, config].includes(undefined)) {
return;
}
@@ -300,8 +300,10 @@
? 0 : undefined;
}
- _computeItemNeedsReview(account, change, showReviewedState) {
- return showReviewedState && !change.reviewed &&
+ _computeItemNeedsReview(account, change, showReviewedState, config) {
+ const isAttentionSetEnabled =
+ !!config && !!config.change && config.change.enable_attention_set;
+ return !isAttentionSetEnabled && showReviewedState && !change.reviewed &&
!change.work_in_progress &&
this.changeIsOpen(change) &&
(!account || account._account_id != change.owner._account_id);
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_html.js b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_html.js
index 2e50cd8..a18ffd0 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_html.js
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_html.js
@@ -131,10 +131,12 @@
</template>
<template is="dom-repeat" items="[[changeSection.results]]" as="change">
<gr-change-list-item
+ account="[[account]]"
selected$="[[_computeItemSelected(sectionIndex, index, selectedIndex)]]"
highlight$="[[_computeItemHighlight(account, change)]]"
- needs-review$="[[_computeItemNeedsReview(account, change, showReviewedState)]]"
+ needs-review$="[[_computeItemNeedsReview(account, change, showReviewedState, _config)]]"
change="[[change]]"
+ config="[[_config]]"
visible-change-table-columns="[[visibleChangeTableColumns]]"
show-number="[[showNumber]]"
show-star="[[showStar]]"
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.html b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.js
similarity index 85%
rename from polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.html
rename to polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.js
index 62763d9..78973df 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.html
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.js
@@ -1,76 +1,55 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2015 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-change-list</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<script src="/node_modules/page/page.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-change-list></gr-change-list>
- </template>
-</test-fixture>
-
-<test-fixture id="grouped">
- <template>
- <gr-change-list></gr-change-list>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-change-list.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {afterNextRender} from '@polymer/polymer/lib/utils/render-status.js';
-import {KeyboardShortcutBinder} from '../../../behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
+import {TestKeyboardShortcutBinder} from '../../../test/test-utils.js';
+
+const basicFixture = fixtureFromElement('gr-change-list');
suite('gr-change-list basic tests', () => {
- // Define keybindings before attaching other fixtures.
- const kb = KeyboardShortcutBinder;
- kb.bindShortcut(kb.Shortcut.CURSOR_NEXT_CHANGE, 'j');
- kb.bindShortcut(kb.Shortcut.CURSOR_PREV_CHANGE, 'k');
- kb.bindShortcut(kb.Shortcut.OPEN_CHANGE, 'o');
- kb.bindShortcut(kb.Shortcut.REFRESH_CHANGE_LIST, 'shift+r');
- kb.bindShortcut(kb.Shortcut.TOGGLE_CHANGE_REVIEWED, 'r');
- kb.bindShortcut(kb.Shortcut.TOGGLE_CHANGE_STAR, 's');
- kb.bindShortcut(kb.Shortcut.NEXT_PAGE, 'n');
- kb.bindShortcut(kb.Shortcut.NEXT_PAGE, 'p');
-
let element;
- let sandbox;
- setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
+ suiteSetup(() => {
+ const kb = TestKeyboardShortcutBinder.push();
+ kb.bindShortcut(kb.Shortcut.CURSOR_NEXT_CHANGE, 'j');
+ kb.bindShortcut(kb.Shortcut.CURSOR_PREV_CHANGE, 'k');
+ kb.bindShortcut(kb.Shortcut.OPEN_CHANGE, 'o');
+ kb.bindShortcut(kb.Shortcut.REFRESH_CHANGE_LIST, 'shift+r');
+ kb.bindShortcut(kb.Shortcut.TOGGLE_CHANGE_REVIEWED, 'r');
+ kb.bindShortcut(kb.Shortcut.TOGGLE_CHANGE_STAR, 's');
+ kb.bindShortcut(kb.Shortcut.NEXT_PAGE, 'n');
+ kb.bindShortcut(kb.Shortcut.NEXT_PAGE, 'p');
});
- teardown(() => { sandbox.restore(); });
+ suiteTeardown(() => {
+ TestKeyboardShortcutBinder.pop();
+ });
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
suite('test show change number not logged in', () => {
setup(() => {
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.account = null;
element.preferences = null;
element._config = {};
@@ -83,7 +62,7 @@
suite('test show change number preference enabled', () => {
setup(() => {
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.preferences = {
legacycid_in_change_table: true,
time_format: 'HHMM_12',
@@ -101,7 +80,7 @@
suite('test show change number preference disabled', () => {
setup(() => {
- element = fixture('basic');
+ element = basicFixture.instantiate();
// legacycid_in_change_table is not set when false.
element.preferences = {
time_format: 'HHMM_12',
@@ -170,7 +149,7 @@
});
test('keyboard shortcuts', done => {
- sandbox.stub(element, '_computeLabelNames');
+ sinon.stub(element, '_computeLabelNames');
element.sections = [
{results: new Array(1)},
{results: new Array(2)},
@@ -195,7 +174,7 @@
assert.equal(element.selectedIndex, 2);
assert.isTrue(elementItems[2].hasAttribute('selected'));
- const navStub = sandbox.stub(GerritNav, 'navigateToChange');
+ const navStub = sinon.stub(GerritNav, 'navigateToChange');
assert.equal(element.selectedIndex, 2);
MockInteractions.pressAndReleaseKeyOn(element, 13, null, 'enter');
assert.deepEqual(navStub.lastCall.args[0], {_number: 2},
@@ -212,7 +191,7 @@
MockInteractions.pressAndReleaseKeyOn(element, 75, null, 'k');
assert.equal(element.selectedIndex, 0);
- const reloadStub = sandbox.stub(element, '_reloadWindow');
+ const reloadStub = sinon.stub(element, '_reloadWindow');
MockInteractions.pressAndReleaseKeyOn(element, 82, 'shift', 'r');
assert.isTrue(reloadStub.called);
@@ -277,6 +256,15 @@
assert.isFalse(elementItems[2].hasAttribute('needs-review'));
assert.isFalse(elementItems[3].hasAttribute('needs-review'));
assert.isFalse(elementItems[4].hasAttribute('needs-review'));
+
+ element._config = {
+ change: {enable_attention_set: true},
+ };
+ elementItems = dom(element.root).querySelectorAll(
+ 'gr-change-list-item');
+ for (let i = 0; i < elementItems.length; i++) {
+ assert.isFalse(elementItems[i].hasAttribute('needs-review'));
+ }
});
test('no changes', () => {
@@ -331,7 +319,7 @@
let element;
setup(() => {
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.sections = [
{results: [{}]},
];
@@ -362,7 +350,7 @@
let element;
setup(() => {
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.sections = [
{results: [{}]},
];
@@ -400,7 +388,7 @@
let element;
setup(() => {
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.sections = [
{results: [{}]},
];
@@ -444,7 +432,7 @@
/* This would only exist if somebody manually updated the config
file. */
setup(() => {
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.account = {_account_id: 1001};
element.preferences = {
legacycid_in_change_table: true,
@@ -465,14 +453,12 @@
suite('dashboard queries', () => {
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
+ element = basicFixture.instantiate();
});
- teardown(() => { sandbox.restore(); });
+ teardown(() => { sinon.restore(); });
test('query without age and limit unchanged', () => {
const query = 'status:closed owner:me';
@@ -518,15 +504,11 @@
suite('gr-change-list sections', () => {
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
+ element = basicFixture.instantiate();
});
- teardown(() => { sandbox.restore(); });
-
test('keyboard shortcuts', done => {
element.selectedIndex = 0;
element.sections = [
@@ -562,7 +544,7 @@
assert.equal(element.selectedIndex, 1);
MockInteractions.pressAndReleaseKeyOn(element, 74); // 'j'
- const navStub = sandbox.stub(GerritNav, 'navigateToChange');
+ const navStub = sinon.stub(GerritNav, 'navigateToChange');
assert.equal(element.selectedIndex, 2);
MockInteractions.pressAndReleaseKeyOn(element, 13); // 'enter'
@@ -631,7 +613,7 @@
});
test('_computeItemAbsoluteIndex', () => {
- sandbox.stub(element, '_computeLabelNames');
+ sinon.stub(element, '_computeLabelNames');
element.sections = [
{results: new Array(1)},
{results: new Array(2)},
@@ -650,4 +632,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/change-list/gr-create-change-help/gr-create-change-help_test.html b/polygerrit-ui/app/elements/change-list/gr-create-change-help/gr-create-change-help_test.html
deleted file mode 100644
index 9b8ed29..0000000
--- a/polygerrit-ui/app/elements/change-list/gr-create-change-help/gr-create-change-help_test.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-create-change-help</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-create-change-help></gr-create-change-help>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-create-change-help.js';
-suite('gr-create-change-help tests', () => {
- let element;
-
- setup(() => {
- element = fixture('basic');
- });
-
- test('Create change tap', done => {
- element.addEventListener('create-tap', () => done());
- MockInteractions.tap(element.shadowRoot
- .querySelector('gr-button'));
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/change-list/gr-create-change-help/gr-create-change-help_test.js b/polygerrit-ui/app/elements/change-list/gr-create-change-help/gr-create-change-help_test.js
new file mode 100644
index 0000000..9dd0a35
--- /dev/null
+++ b/polygerrit-ui/app/elements/change-list/gr-create-change-help/gr-create-change-help_test.js
@@ -0,0 +1,36 @@
+/**
+ * @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.
+ */
+
+import '../../../test/common-test-setup-karma.js';
+import './gr-create-change-help.js';
+
+const basicFixture = fixtureFromElement('gr-create-change-help');
+
+suite('gr-create-change-help tests', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ test('Create change tap', done => {
+ element.addEventListener('create-tap', () => done());
+ MockInteractions.tap(element.shadowRoot
+ .querySelector('gr-button'));
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog_test.html b/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog_test.html
deleted file mode 100644
index e6cd587..0000000
--- a/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog_test.html
+++ /dev/null
@@ -1,54 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-create-commands-dialog</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-create-commands-dialog></gr-create-commands-dialog>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-create-commands-dialog.js';
-suite('gr-create-commands-dialog tests', () => {
- let element;
-
- setup(() => {
- element = fixture('basic');
- });
-
- test('_computePushCommand', () => {
- element.branch = 'master';
- assert.equal(element._pushCommand,
- 'git push origin HEAD:refs/for/master');
-
- element.branch = 'stable-2.15';
- assert.equal(element._pushCommand,
- 'git push origin HEAD:refs/for/stable-2.15');
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog_test.js b/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog_test.js
new file mode 100644
index 0000000..9dbcd29
--- /dev/null
+++ b/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog_test.js
@@ -0,0 +1,40 @@
+/**
+ * @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.
+ */
+
+import '../../../test/common-test-setup-karma.js';
+import './gr-create-commands-dialog.js';
+
+const basicFixture = fixtureFromElement('gr-create-commands-dialog');
+
+suite('gr-create-commands-dialog tests', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ test('_computePushCommand', () => {
+ element.branch = 'master';
+ assert.equal(element._pushCommand,
+ 'git push origin HEAD:refs/for/master');
+
+ element.branch = 'stable-2.15';
+ assert.equal(element._pushCommand,
+ 'git push origin HEAD:refs/for/stable-2.15');
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js
index 1cc2316..c5d50c1 100644
--- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js
+++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js
@@ -182,10 +182,14 @@
const {project, dashboard, title, user, sections} = this.params;
const dashboardPromise = project ?
this._getProjectDashboard(project, dashboard) :
- Promise.resolve(GerritNav.getUserDashboard(
- user,
- sections,
- title || this._computeTitle(user)));
+ this.$.restAPI.getConfig().then(
+ config => Promise.resolve(GerritNav.getUserDashboard(
+ user,
+ sections,
+ title || this._computeTitle(user),
+ config
+ ))
+ );
const checkForNewUser = !project && user === 'self';
return dashboardPromise
diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.html b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.js
similarity index 78%
rename from polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.html
rename to polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.js
index 2fcf233..bdd374a 100644
--- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.html
+++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.js
@@ -1,45 +1,30 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-dashboard-view</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-dashboard-view></gr-dashboard-view>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-dashboard-view.js';
import {isHidden} from '../../../test/test-utils.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
+const basicFixture = fixtureFromElement('gr-dashboard-view');
+
suite('gr-dashboard-view tests', () => {
let element;
- let sandbox;
+
let paramsChangedPromise;
let getChangesStub;
@@ -49,9 +34,9 @@
getAccountDetails() { return Promise.resolve({}); },
getAccountStatus() { return Promise.resolve(false); },
});
- element = fixture('basic');
- sandbox = sinon.sandbox.create();
- getChangesStub = sandbox.stub(element.$.restAPI, 'getChanges',
+ element = basicFixture.instantiate();
+
+ getChangesStub = sinon.stub(element.$.restAPI, 'getChanges').callsFake(
(_, qs) => Promise.resolve(qs.map(() => [])));
let resolver;
@@ -59,15 +44,11 @@
resolver = resolve;
});
const paramsChanged = element._paramsChanged.bind(element);
- sandbox.stub(element, '_paramsChanged', params => {
+ sinon.stub(element, '_paramsChanged').callsFake( params => {
paramsChanged(params).then(() => resolver());
});
});
- teardown(() => {
- sandbox.restore();
- });
-
suite('drafts banner functionality', () => {
suite('_maybeShowDraftsBanner', () => {
test('not dashboard/self', () => {
@@ -86,7 +67,7 @@
test('no drafts on open changes', () => {
element.params = {user: 'self'};
element._results = [{query: 'has:draft', results: [{status: '_'}]}];
- sandbox.stub(element, 'changeIsOpen').returns(true);
+ sinon.stub(element, 'changeIsOpen').returns(true);
element._maybeShowDraftsBanner();
assert.isFalse(element._showDraftsBanner);
});
@@ -94,7 +75,7 @@
test('no drafts on open changes', () => {
element.params = {user: 'self'};
element._results = [{query: 'has:draft', results: [{status: '_'}]}];
- sandbox.stub(element, 'changeIsOpen').returns(false);
+ sinon.stub(element, 'changeIsOpen').returns(false);
element._maybeShowDraftsBanner();
assert.isTrue(element._showDraftsBanner);
});
@@ -113,7 +94,7 @@
});
test('delete tap opens dialog', () => {
- sandbox.stub(element, '_handleOpenDeleteDialog');
+ sinon.stub(element, '_handleOpenDeleteDialog');
element._showDraftsBanner = true;
flushAsynchronousOperations();
@@ -123,15 +104,15 @@
});
test('delete comments flow', async () => {
- sandbox.spy(element, '_handleConfirmDelete');
- sandbox.stub(element, '_reload');
+ sinon.spy(element, '_handleConfirmDelete');
+ sinon.stub(element, '_reload');
// Set up control over timing of when RPC resolves.
let deleteDraftCommentsPromiseResolver;
const deleteDraftCommentsPromise = new Promise(resolve => {
deleteDraftCommentsPromiseResolver = resolve;
});
- sandbox.stub(element.$.restAPI, 'deleteDraftComments')
+ sinon.stub(element.$.restAPI, 'deleteDraftComments')
.returns(deleteDraftCommentsPromise);
// Open confirmation dialog and tap confirm button.
@@ -246,14 +227,15 @@
suite('_getProjectDashboard', () => {
test('dashboard with foreach', () => {
- sandbox.stub(element.$.restAPI, 'getDashboard', () => Promise.resolve({
- title: 'title',
- foreach: 'foreach for ${project}',
- sections: [
- {name: 'section 1', query: 'query 1'},
- {name: 'section 2', query: '${project} query 2'},
- ],
- }));
+ sinon.stub(element.$.restAPI, 'getDashboard')
+ .callsFake( () => Promise.resolve({
+ title: 'title',
+ foreach: 'foreach for ${project}',
+ sections: [
+ {name: 'section 1', query: 'query 1'},
+ {name: 'section 2', query: '${project} query 2'},
+ ],
+ }));
return element._getProjectDashboard('project', '').then(dashboard => {
assert.deepEqual(
dashboard,
@@ -271,13 +253,14 @@
});
test('dashboard without foreach', () => {
- sandbox.stub(element.$.restAPI, 'getDashboard', () => Promise.resolve({
- title: 'title',
- sections: [
- {name: 'section 1', query: 'query 1'},
- {name: 'section 2', query: '${project} query 2'},
- ],
- }));
+ sinon.stub(element.$.restAPI, 'getDashboard').callsFake(
+ () => Promise.resolve({
+ title: 'title',
+ sections: [
+ {name: 'section 1', query: 'query 1'},
+ {name: 'section 2', query: '${project} query 2'},
+ ],
+ }));
return element._getProjectDashboard('project', '').then(dashboard => {
assert.deepEqual(
dashboard,
@@ -298,7 +281,7 @@
{name: 'test2', query: 'test2', hideIfEmpty: true},
];
getChangesStub.restore();
- sandbox.stub(element.$.restAPI, 'getChanges')
+ sinon.stub(element.$.restAPI, 'getChanges')
.returns(Promise.resolve([[], ['nonempty']]));
return element._fetchDashboardChanges({sections}, false).then(() => {
@@ -313,7 +296,7 @@
{name: 'test2', query: 'test2'},
];
getChangesStub.restore();
- sandbox.stub(element.$.restAPI, 'getChanges')
+ sinon.stub(element.$.restAPI, 'getChanges')
.returns(Promise.resolve([[], []]));
return element._fetchDashboardChanges({sections}, false).then(() => {
@@ -351,7 +334,7 @@
test('404 page', done => {
const response = {status: 404};
- sandbox.stub(element.$.restAPI, 'getDashboard',
+ sinon.stub(element.$.restAPI, 'getDashboard').callsFake(
async (project, dashboard, errFn) => {
errFn(response);
});
@@ -367,7 +350,7 @@
});
test('params change triggers dashboardDisplayed()', () => {
- sandbox.stub(element.reporting, 'dashboardDisplayed');
+ sinon.stub(element.reporting, 'dashboardDisplayed');
element.params = {
view: GerritNav.View.DASHBOARD,
project: 'project',
@@ -378,4 +361,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header_test.html b/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header_test.html
deleted file mode 100644
index 78c1f09..0000000
--- a/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header_test.html
+++ /dev/null
@@ -1,59 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-repo-header</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-repo-header></gr-repo-header>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-repo-header.js';
-import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
-
-suite('gr-repo-header tests', () => {
- let element;
- let sandbox;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- });
-
- teardown(() => { sandbox.restore(); });
-
- test('repoUrl reset once repo changed', () => {
- sandbox.stub(GerritNav, 'getUrlForRepo',
- repoName => `http://test.com/${repoName}`
- );
- assert.equal(element._repoUrl, undefined);
- element.repo = 'test';
- assert.equal(element._repoUrl, 'http://test.com/test');
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header_test.js b/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header_test.js
new file mode 100644
index 0000000..4f93d54
--- /dev/null
+++ b/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header_test.js
@@ -0,0 +1,40 @@
+/**
+ * @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.
+ */
+
+import '../../../test/common-test-setup-karma.js';
+import './gr-repo-header.js';
+import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
+
+const basicFixture = fixtureFromElement('gr-repo-header');
+
+suite('gr-repo-header tests', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ test('repoUrl reset once repo changed', () => {
+ sinon.stub(GerritNav, 'getUrlForRepo').callsFake(
+ repoName => `http://test.com/${repoName}`
+ );
+ assert.equal(element._repoUrl, undefined);
+ element.repo = 'test';
+ assert.equal(element._repoUrl, 'http://test.com/test');
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header_test.html b/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header_test.html
deleted file mode 100644
index 44eb96c..0000000
--- a/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header_test.html
+++ /dev/null
@@ -1,81 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-user-header</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-user-header></gr-user-header>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-user-header.js';
-suite('gr-user-header tests', () => {
- let element;
- let sandbox;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- });
-
- teardown(() => { sandbox.restore(); });
-
- test('loads and clears account info', done => {
- sandbox.stub(element.$.restAPI, 'getAccountDetails')
- .returns(Promise.resolve({
- name: 'foo',
- email: 'bar',
- registered_on: '2015-03-12 18:32:08.000000000',
- }));
- sandbox.stub(element.$.restAPI, 'getAccountStatus')
- .returns(Promise.resolve('baz'));
-
- element.userId = 'foo.bar@baz';
- flush(() => {
- assert.isOk(element._accountDetails);
- assert.isOk(element._status);
-
- element.userId = null;
- flush(() => {
- flushAsynchronousOperations();
- assert.isNull(element._accountDetails);
- assert.isNull(element._status);
-
- done();
- });
- });
- });
-
- test('_computeDashboardLinkClass', () => {
- assert.include(element._computeDashboardLinkClass(false, false), 'hide');
- assert.include(element._computeDashboardLinkClass(true, false), 'hide');
- assert.include(element._computeDashboardLinkClass(false, true), 'hide');
- assert.notInclude(element._computeDashboardLinkClass(true, true), 'hide');
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header_test.js b/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header_test.js
new file mode 100644
index 0000000..6baacef
--- /dev/null
+++ b/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header_test.js
@@ -0,0 +1,63 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-user-header.js';
+
+const basicFixture = fixtureFromElement('gr-user-header');
+
+suite('gr-user-header tests', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ test('loads and clears account info', done => {
+ sinon.stub(element.$.restAPI, 'getAccountDetails')
+ .returns(Promise.resolve({
+ name: 'foo',
+ email: 'bar',
+ registered_on: '2015-03-12 18:32:08.000000000',
+ }));
+ sinon.stub(element.$.restAPI, 'getAccountStatus')
+ .returns(Promise.resolve('baz'));
+
+ element.userId = 'foo.bar@baz';
+ flush(() => {
+ assert.isOk(element._accountDetails);
+ assert.isOk(element._status);
+
+ element.userId = null;
+ flush(() => {
+ flushAsynchronousOperations();
+ assert.isNull(element._accountDetails);
+ assert.isNull(element._status);
+
+ done();
+ });
+ });
+ });
+
+ test('_computeDashboardLinkClass', () => {
+ assert.include(element._computeDashboardLinkClass(false, false), 'hide');
+ assert.include(element._computeDashboardLinkClass(true, false), 'hide');
+ assert.include(element._computeDashboardLinkClass(false, true), 'hide');
+ assert.notInclude(element._computeDashboardLinkClass(true, true), 'hide');
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.js b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.js
index 8dc8058..21ccf82 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.js
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.js
@@ -233,6 +233,11 @@
*/
const SKIP_ACTION_KEYS = [ChangeActions.REVERT_SUBMISSION];
+const SKIP_ACTION_KEYS_ATTENTION_SET = [
+ ChangeActions.REVIEWED,
+ ChangeActions.UNREVIEWED,
+];
+
/**
* @extends PolymerElement
*/
@@ -360,7 +365,7 @@
type: Array,
computed: '_computeAllActions(actions.*, revisionActions.*,' +
'primaryActionKeys.*, _additionalActions.*, change, ' +
- '_actionPriorityOverrides.*)',
+ '_config, _actionPriorityOverrides.*)',
},
_topLevelActions: {
type: Array,
@@ -462,6 +467,7 @@
type: Boolean,
value: true,
},
+ _config: Object,
};
}
@@ -487,6 +493,9 @@
ready() {
super.ready();
this.$.jsAPI.addElement(this.$.jsAPI.Element.CHANGE_ACTIONS, this);
+ this.$.restAPI.getConfig().then(config => {
+ this._config = config;
+ });
this._handleLoadingComplete();
}
@@ -669,7 +678,7 @@
actionsChangeRecord,
revisionActionsChangeRecord,
additionalActionsChangeRecord,
- ].some(arg => arg === undefined)) {
+ ].includes(undefined)) {
return;
}
@@ -708,7 +717,7 @@
editMode,
editBasedOnCurrentPatchSet,
disableEdit,
- ].some(arg => arg === undefined)) {
+ ].includes(undefined)) {
return;
}
@@ -1515,10 +1524,11 @@
* @param {!Array} primariesRecord
* @param {!Array} additionalActionsRecord
* @param {!Object} change The change object.
+ * @param {!Object} config server configuration info
* @return {!Array}
*/
_computeAllActions(changeActionsRecord, revisionActionsRecord,
- primariesRecord, additionalActionsRecord, change) {
+ primariesRecord, additionalActionsRecord, change, config) {
// Polymer 2: check for undefined
if ([
changeActionsRecord,
@@ -1526,7 +1536,7 @@
primariesRecord,
additionalActionsRecord,
change,
- ].some(arg => arg === undefined)) {
+ ].includes(undefined)) {
return [];
}
@@ -1554,7 +1564,7 @@
// End of hack
return action;
})
- .filter(action => !this._shouldSkipAction(action));
+ .filter(action => !this._shouldSkipAction(action, config));
}
_getActionPriority(action) {
@@ -1592,8 +1602,14 @@
}
}
- _shouldSkipAction(action) {
- return SKIP_ACTION_KEYS.includes(action.__key);
+ _shouldSkipAction(action, config) {
+ const skipActionKeys = [...SKIP_ACTION_KEYS];
+ const isAttentionSetEnabled = !!config && !!config.change
+ && config.change.enable_attention_set;
+ if (isAttentionSetEnabled) {
+ skipActionKeys.push(...SKIP_ACTION_KEYS_ATTENTION_SET);
+ }
+ return skipActionKeys.includes(action.__key);
}
_computeTopLevelActions(actionRecord, hiddenActionsRecord) {
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.html b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.js
similarity index 90%
rename from polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.html
rename to polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.js
index cda53c5..2702af4 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.html
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.js
@@ -1,42 +1,28 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-change-actions</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-change-actions></gr-change-actions>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-change-actions.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
import {pluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
+
+const basicFixture = fixtureFromElement('gr-change-actions');
+
const CHERRY_PICK_TYPES = {
SINGLE_CHANGE: 1,
TOPIC: 2,
@@ -44,7 +30,6 @@
// TODO(dhruvsri): remove use of _populateRevertMessage as it's private
suite('gr-change-actions tests', () => {
let element;
- let sandbox;
suite('basic tests', () => {
setup(() => {
@@ -99,11 +84,10 @@
getProjectConfig() { return Promise.resolve({}); },
});
- sandbox = sinon.sandbox.create();
- sandbox.stub(pluginLoader, 'awaitPluginsLoaded')
+ sinon.stub(pluginLoader, 'awaitPluginsLoaded')
.returns(Promise.resolve());
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.change = {};
element.changeNum = '42';
element.latestPatchNum = '2';
@@ -115,18 +99,14 @@
enabled: true,
},
};
- sandbox.stub(element.$.confirmCherrypick.$.restAPI,
+ sinon.stub(element.$.confirmCherrypick.$.restAPI,
'getRepoBranches').returns(Promise.resolve([]));
- sandbox.stub(element.$.confirmMove.$.restAPI,
+ sinon.stub(element.$.confirmMove.$.restAPI,
'getRepoBranches').returns(Promise.resolve([]));
return element.reload();
});
- teardown(() => {
- sandbox.restore();
- });
-
test('show-revision-actions event should fire', done => {
const spy = sinon.spy(element, '_sendShowRevisionActions');
element.reload();
@@ -145,8 +125,10 @@
});
test('revert submission action is skipped', () => {
- assert.isFalse(element._allActionValues.includes(action =>
- action.key === 'revert_submission'));
+ assert.equal(element._allActionValues.filter(action =>
+ action.__key === 'submit').length, 1);
+ assert.equal(element._allActionValues.filter(action =>
+ action.__key === 'revert_submission').length, 0);
});
test('_shouldHideActions', () => {
@@ -156,7 +138,7 @@
});
test('plugin revision actions', done => {
- sandbox.stub(element.$.restAPI, 'getChangeActionURL').returns(
+ sinon.stub(element.$.restAPI, 'getChangeActionURL').returns(
Promise.resolve('the-url'));
element.revisionActions = {
'plugin~action': {},
@@ -171,7 +153,7 @@
});
test('plugin change actions', done => {
- sandbox.stub(element.$.restAPI, 'getChangeActionURL').returns(
+ sinon.stub(element.$.restAPI, 'getChangeActionURL').returns(
Promise.resolve('the-url'));
element.actions = {
'plugin~action': {},
@@ -286,12 +268,12 @@
});
test('submit change', () => {
- const showSpy = sandbox.spy(element, '_showActionDialog');
- sandbox.stub(element.$.restAPI, 'getFromProjectLookup')
+ const showSpy = sinon.spy(element, '_showActionDialog');
+ sinon.stub(element.$.restAPI, 'getFromProjectLookup')
.returns(Promise.resolve('test'));
- sandbox.stub(element, 'fetchChangeUpdates',
+ sinon.stub(element, 'fetchChangeUpdates').callsFake(
() => Promise.resolve({isLatest: true}));
- sandbox.stub(element.$.overlay, 'open').returns(Promise.resolve());
+ sinon.stub(element.$.overlay, 'open').returns(Promise.resolve());
element.change = {
revisions: {
rev1: {_number: 1},
@@ -310,12 +292,12 @@
});
test('submit change, tap on icon', done => {
- sandbox.stub(element.$.confirmSubmitDialog, 'resetFocus', done);
- sandbox.stub(element.$.restAPI, 'getFromProjectLookup')
+ sinon.stub(element.$.confirmSubmitDialog, 'resetFocus').callsFake( done);
+ sinon.stub(element.$.restAPI, 'getFromProjectLookup')
.returns(Promise.resolve('test'));
- sandbox.stub(element, 'fetchChangeUpdates',
+ sinon.stub(element, 'fetchChangeUpdates').callsFake(
() => Promise.resolve({isLatest: true}));
- sandbox.stub(element.$.overlay, 'open').returns(Promise.resolve());
+ sinon.stub(element.$.overlay, 'open').returns(Promise.resolve());
element.change = {
revisions: {
rev1: {_number: 1},
@@ -332,8 +314,8 @@
});
test('_handleSubmitConfirm', () => {
- const fireStub = sandbox.stub(element, '_fireAction');
- sandbox.stub(element, '_canSubmitChange').returns(true);
+ const fireStub = sinon.stub(element, '_fireAction');
+ sinon.stub(element, '_canSubmitChange').returns(true);
element._handleSubmitConfirm();
assert.isTrue(fireStub.calledOnce);
assert.deepEqual(fireStub.lastCall.args,
@@ -341,16 +323,16 @@
});
test('_handleSubmitConfirm when not able to submit', () => {
- const fireStub = sandbox.stub(element, '_fireAction');
- sandbox.stub(element, '_canSubmitChange').returns(false);
+ const fireStub = sinon.stub(element, '_fireAction');
+ sinon.stub(element, '_canSubmitChange').returns(false);
element._handleSubmitConfirm();
assert.isFalse(fireStub.called);
});
test('submit change with plugin hook', done => {
- sandbox.stub(element, '_canSubmitChange',
+ sinon.stub(element, '_canSubmitChange').callsFake(
() => false);
- const fireActionStub = sandbox.stub(element, '_fireAction');
+ const fireActionStub = sinon.stub(element, '_fireAction');
flush(() => {
const submitButton = element.shadowRoot
.querySelector('gr-button[data-action-key="submit"]');
@@ -390,8 +372,8 @@
});
test('rebase change', done => {
- const fireActionStub = sandbox.stub(element, '_fireAction');
- const fetchChangesStub = sandbox.stub(element.$.confirmRebase,
+ const fireActionStub = sinon.stub(element, '_fireAction');
+ const fetchChangesStub = sinon.stub(element.$.confirmRebase,
'fetchRecentChanges').returns(Promise.resolve([]));
element._hasKnownChainState = true;
flush(() => {
@@ -416,8 +398,8 @@
});
test('rebase change calls navigateToChange', done => {
- const navigateToChangeStub = sandbox.stub(GerritNav, 'navigateToChange');
- sandbox.stub(element.$.restAPI, 'getResponseObject').returns(
+ const navigateToChangeStub = sinon.stub(GerritNav, 'navigateToChange');
+ sinon.stub(element.$.restAPI, 'getResponseObject').returns(
Promise.resolve({}));
element._handleResponse({__key: 'rebase'}, {});
flush(() => {
@@ -427,7 +409,7 @@
});
test(`rebase dialog gets recent changes each time it's opened`, done => {
- const fetchChangesStub = sandbox.stub(element.$.confirmRebase,
+ const fetchChangesStub = sinon.stub(element.$.confirmRebase,
'fetchRecentChanges').returns(Promise.resolve([]));
element._hasKnownChainState = true;
const rebaseButton = element.shadowRoot
@@ -455,7 +437,7 @@
MockInteractions.tap(rebaseButton);
flushAsynchronousOperations();
assert.isFalse(element.$.confirmRebase.hidden);
- sandbox.stub(element.$.restAPI, 'getChanges')
+ sinon.stub(element.$.restAPI, 'getChanges')
.returns(Promise.resolve([]));
element._handleCherrypickTap();
flush(() => {
@@ -467,7 +449,7 @@
});
test('fullscreen-overlay-opened hides content', () => {
- sandbox.spy(element, '_handleHideBackgroundContent');
+ sinon.spy(element, '_handleHideBackgroundContent');
element.$.overlay.dispatchEvent(
new CustomEvent('fullscreen-overlay-opened', {
composed: true, bubbles: true,
@@ -477,7 +459,7 @@
});
test('fullscreen-overlay-closed shows content', () => {
- sandbox.spy(element, '_handleShowBackgroundContent');
+ sinon.spy(element, '_handleShowBackgroundContent');
element.$.overlay.dispatchEvent(
new CustomEvent('fullscreen-overlay-closed', {
composed: true, bubbles: true,
@@ -489,8 +471,8 @@
test('_setLabelValuesOnRevert', () => {
const labels = {'Foo': 1, 'Bar-Baz': -2};
const changeId = 1234;
- sandbox.stub(element.$.jsAPI, 'getLabelValuesPostRevert').returns(labels);
- const saveStub = sandbox.stub(element.$.restAPI, 'saveChangeReview')
+ sinon.stub(element.$.jsAPI, 'getLabelValuesPostRevert').returns(labels);
+ const saveStub = sinon.stub(element.$.restAPI, 'saveChangeReview')
.returns(Promise.resolve());
return element._setLabelValuesOnRevert(changeId).then(() => {
assert.isTrue(saveStub.calledOnce);
@@ -523,7 +505,7 @@
element.set('editMode', true);
element.set('editPatchsetLoaded', true);
- const fireActionStub = sandbox.stub(element, '_fireAction');
+ const fireActionStub = sinon.stub(element, '_fireAction');
element._handleDeleteEditTap();
assert.isFalse(element.$.confirmDeleteEditDialog.hidden);
MockInteractions.tap(
@@ -656,8 +638,8 @@
let fireActionStub;
setup(() => {
- fireActionStub = sandbox.stub(element, '_fireAction');
- sandbox.stub(window, 'alert');
+ fireActionStub = sinon.stub(element, '_fireAction');
+ sinon.stub(window, 'alert');
});
test('works', () => {
@@ -765,7 +747,7 @@
},
];
setup(done => {
- sandbox.stub(element.$.restAPI, 'getChanges')
+ sinon.stub(element.$.restAPI, 'getChanges')
.returns(Promise.resolve(changes));
element._handleCherrypickTap();
flush(() => {
@@ -830,8 +812,8 @@
let fireActionStub;
setup(() => {
- fireActionStub = sandbox.stub(element, '_fireAction');
- sandbox.stub(window, 'alert');
+ fireActionStub = sinon.stub(element, '_fireAction');
+ sinon.stub(window, 'alert');
});
test('works', () => {
@@ -912,8 +894,8 @@
let fireActionStub;
setup(() => {
- fireActionStub = sandbox.stub(element, '_fireAction');
- alertStub = sandbox.stub(window, 'alert');
+ fireActionStub = sinon.stub(element, '_fireAction');
+ alertStub = sinon.stub(window, 'alert');
element.actions = {
abandon: {
method: 'POST',
@@ -982,7 +964,7 @@
let fireActionStub;
setup(() => {
- fireActionStub = sandbox.stub(element, '_fireAction');
+ fireActionStub = sinon.stub(element, '_fireAction');
element.commitMessage = 'random commit message';
element.change.current_revision = 'abcdef';
element.actions = {
@@ -998,18 +980,18 @@
test('revert change with plugin hook', done => {
const newRevertMsg = 'Modified revert msg';
- sandbox.stub(element.$.confirmRevertDialog, '_modifyRevertMsg',
+ sinon.stub(element.$.confirmRevertDialog, '_modifyRevertMsg').callsFake(
() => newRevertMsg);
element.change = {
current_revision: 'abc1234',
};
- sandbox.stub(element.$.restAPI, 'getChanges')
+ sinon.stub(element.$.restAPI, 'getChanges')
.returns(Promise.resolve([
{change_id: '12345678901234', topic: 'T', subject: 'random'},
{change_id: '23456', topic: 'T', subject: 'a'.repeat(100)},
]));
- sandbox.stub(element.$.confirmRevertDialog,
- '_populateRevertSubmissionMessage', () => 'original msg');
+ sinon.stub(element.$.confirmRevertDialog,
+ '_populateRevertSubmissionMessage').callsFake(() => 'original msg');
flush(() => {
const revertButton = element.shadowRoot
.querySelector('gr-button[data-action-key="revert"]');
@@ -1028,7 +1010,7 @@
submission_id: '199 0',
current_revision: '2000',
};
- getChangesStub = sandbox.stub(element.$.restAPI, 'getChanges')
+ getChangesStub = sinon.stub(element.$.restAPI, 'getChanges')
.returns(Promise.resolve([
{change_id: '12345678901234', topic: 'T', subject: 'random'},
{change_id: '23456', topic: 'T', subject: 'a'.repeat(100)},
@@ -1075,7 +1057,7 @@
.querySelector('gr-button[data-action-key="revert"]');
const confirmRevertDialog = element.$.confirmRevertDialog;
MockInteractions.tap(revertButton);
- const fireStub = sandbox.stub(confirmRevertDialog, 'dispatchEvent');
+ const fireStub = sinon.stub(confirmRevertDialog, 'dispatchEvent');
flush(() => {
const confirmButton = element.$.confirmRevertDialog.shadowRoot
.querySelector('gr-dialog')
@@ -1138,7 +1120,7 @@
submission_id: '199',
current_revision: '2000',
};
- sandbox.stub(element.$.restAPI, 'getChanges')
+ sinon.stub(element.$.restAPI, 'getChanges')
.returns(Promise.resolve([
{change_id: '12345678901234', topic: 'T', subject: 'random'},
]));
@@ -1149,7 +1131,7 @@
.querySelector('gr-button[data-action-key="revert"]');
const confirmRevertDialog = element.$.confirmRevertDialog;
MockInteractions.tap(revertButton);
- const fireStub = sandbox.stub(confirmRevertDialog, 'dispatchEvent');
+ const fireStub = sinon.stub(confirmRevertDialog, 'dispatchEvent');
flush(() => {
const confirmButton = element.$.confirmRevertDialog.shadowRoot
.querySelector('gr-dialog')
@@ -1301,7 +1283,7 @@
let deleteAction;
setup(() => {
- fireActionStub = sandbox.stub(element, '_fireAction');
+ fireActionStub = sinon.stub(element, '_fireAction');
element.change = {
current_revision: 'abc1234',
};
@@ -1350,7 +1332,7 @@
suite('ignore change', () => {
setup(done => {
- sandbox.stub(element, '_fireAction');
+ sinon.stub(element, '_fireAction');
const IgnoreAction = {
__key: 'ignore',
@@ -1393,7 +1375,7 @@
suite('unignore change', () => {
setup(done => {
- sandbox.stub(element, '_fireAction');
+ sinon.stub(element, '_fireAction');
const UnignoreAction = {
__key: 'unignore',
@@ -1436,7 +1418,7 @@
suite('reviewed change', () => {
setup(done => {
- sandbox.stub(element, '_fireAction');
+ sinon.stub(element, '_fireAction');
const ReviewedAction = {
__key: 'reviewed',
@@ -1458,6 +1440,19 @@
element.reload().then(() => { flush(done); });
});
+ test('action is enabled', () => {
+ assert.equal(element._allActionValues.filter(action =>
+ action.__key === 'reviewed').length, 1);
+ });
+
+ test('action is skipped when attention set is enabled', () => {
+ element._config = {
+ change: {enable_attention_set: true},
+ };
+ assert.equal(element._allActionValues.filter(action =>
+ action.__key === 'reviewed').length, 0);
+ });
+
test('make sure the reviewed button is not outside of the overflow menu',
() => {
assert.isNotOk(element.shadowRoot
@@ -1480,7 +1475,7 @@
suite('unreviewed change', () => {
setup(done => {
- sandbox.stub(element, '_fireAction');
+ sinon.stub(element, '_fireAction');
const UnreviewedAction = {
__key: 'unreviewed',
@@ -1612,7 +1607,7 @@
});
test('approves when tapped', () => {
- const fireActionStub = sandbox.stub(element, '_fireAction');
+ const fireActionStub = sinon.stub(element, '_fireAction');
MockInteractions.tap(
element.shadowRoot
.querySelector('gr-button[data-action-key=\'review\']'));
@@ -1716,7 +1711,7 @@
});
test('adds download revision action', () => {
- const handler = sandbox.stub();
+ const handler = sinon.stub();
element.addEventListener('download-tap', handler);
assert.ok(element.revisionActions.download);
element._handleDownloadTap();
@@ -1726,7 +1721,7 @@
});
test('changing changeNum or patchNum does not reload', () => {
- const reloadStub = sandbox.stub(element, 'reload');
+ const reloadStub = sinon.stub(element, 'reload');
element.changeNum = 123;
assert.isFalse(reloadStub.called);
element.latestPatchNum = 456;
@@ -1768,7 +1763,7 @@
suite('_waitForChangeReachable', () => {
setup(() => {
- sandbox.stub(element, 'async', fn => fn());
+ sinon.stub(element, 'async').callsFake( fn => fn());
});
const makeGetChange = numTries => () => {
@@ -1781,14 +1776,16 @@
};
test('succeed', () => {
- sandbox.stub(element.$.restAPI, 'getChange', makeGetChange(5));
+ sinon.stub(element.$.restAPI, 'getChange')
+ .callsFake( makeGetChange(5));
return element._waitForChangeReachable(123).then(success => {
assert.isTrue(success);
});
});
test('fail', () => {
- sandbox.stub(element.$.restAPI, 'getChange', makeGetChange(6));
+ sinon.stub(element.$.restAPI, 'getChange')
+ .callsFake( makeGetChange(6));
return element._waitForChangeReachable(123).then(success => {
assert.isFalse(success);
});
@@ -1819,15 +1816,15 @@
suite('happy path', () => {
let sendStub;
setup(() => {
- sandbox.stub(element, 'fetchChangeUpdates')
+ sinon.stub(element, 'fetchChangeUpdates')
.returns(Promise.resolve({isLatest: true}));
- sendStub = sandbox.stub(element.$.restAPI, 'executeChangeAction')
+ sendStub = sinon.stub(element.$.restAPI, 'executeChangeAction')
.returns(Promise.resolve({}));
- getResponseObjectStub = sandbox.stub(element.$.restAPI,
+ getResponseObjectStub = sinon.stub(element.$.restAPI,
'getResponseObject');
- sandbox.stub(GerritNav,
+ sinon.stub(GerritNav,
'navigateToChange').returns(Promise.resolve(true));
- sandbox.stub(element, 'computeLatestPatchNum')
+ sinon.stub(element, 'computeLatestPatchNum')
.returns(element.latestPatchNum);
});
@@ -1847,7 +1844,7 @@
setup(() => {
element.change.submission_id = '199';
element.change.current_revision = '2000';
- sandbox.stub(element.$.restAPI, 'getChanges')
+ sinon.stub(element.$.restAPI, 'getChanges')
.returns(Promise.resolve([
{change_id: '12345678901234', topic: 'T', subject: 'random'},
{change_id: '23456', topic: 'T', subject: 'a'.repeat(100)},
@@ -1862,7 +1859,7 @@
'23456: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...' +
'\n';
const modifiedMsg = expectedMsg + 'abcd';
- sandbox.stub(element.$.confirmRevertSubmissionDialog,
+ sinon.stub(element.$.confirmRevertSubmissionDialog,
'_modifyRevertSubmissionMsg').returns(modifiedMsg);
element.showRevertSubmissionDialog();
flush(() => {
@@ -1880,7 +1877,7 @@
.returns(Promise.resolve({revert_changes: [
{change_id: 12345},
]}));
- navigateToSearchQueryStub = sandbox.stub(GerritNav,
+ navigateToSearchQueryStub = sinon.stub(GerritNav,
'navigateToSearchQuery');
});
@@ -1905,8 +1902,8 @@
{change_id: 12345, topic: 'T'},
{change_id: 23456, topic: 'T'},
]}));
- showActionDialogStub = sandbox.stub(element, '_showActionDialog');
- navigateToSearchQueryStub = sandbox.stub(GerritNav,
+ showActionDialogStub = sinon.stub(element, '_showActionDialog');
+ navigateToSearchQueryStub = sinon.stub(GerritNav,
'navigateToSearchQuery');
});
@@ -1939,9 +1936,9 @@
suite('failure modes', () => {
test('non-latest', () => {
- sandbox.stub(element, 'fetchChangeUpdates')
+ sinon.stub(element, 'fetchChangeUpdates')
.returns(Promise.resolve({isLatest: false}));
- const sendStub = sandbox.stub(element.$.restAPI,
+ const sendStub = sinon.stub(element.$.restAPI,
'executeChangeAction');
return element._send('DELETE', payload, '/endpoint', true, cleanup)
@@ -1954,15 +1951,15 @@
});
test('send fails', () => {
- sandbox.stub(element, 'fetchChangeUpdates')
+ sinon.stub(element, 'fetchChangeUpdates')
.returns(Promise.resolve({isLatest: true}));
- const sendStub = sandbox.stub(element.$.restAPI,
- 'executeChangeAction',
+ const sendStub = sinon.stub(element.$.restAPI,
+ 'executeChangeAction').callsFake(
(num, method, patchNum, endpoint, payload, onErr) => {
onErr();
return Promise.resolve(null);
});
- const handleErrorStub = sandbox.stub(element, '_handleResponseError');
+ const handleErrorStub = sinon.stub(element, '_handleResponseError');
return element._send('DELETE', payload, '/endpoint', true, cleanup)
.then(() => {
@@ -1976,8 +1973,8 @@
});
test('_handleAction reports', () => {
- sandbox.stub(element, '_fireAction');
- const reportStub = sandbox.stub(element.reporting, 'reportInteraction');
+ sinon.stub(element, '_fireAction');
+ const reportStub = sinon.stub(element.reporting, 'reportInteraction');
element._handleAction('type', 'key');
assert.isTrue(reportStub.called);
assert.equal(reportStub.lastCall.args[0], 'type-key');
@@ -1986,7 +1983,7 @@
suite('getChangeRevisionActions returns only some actions', () => {
let element;
- let sandbox;
+
let changeRevisionActions;
setup(() => {
@@ -2000,28 +1997,23 @@
getProjectConfig() { return Promise.resolve({}); },
});
- sandbox = sinon.sandbox.create();
- sandbox.stub(pluginLoader, 'awaitPluginsLoaded')
+ sinon.stub(pluginLoader, 'awaitPluginsLoaded')
.returns(Promise.resolve());
- element = fixture('basic');
+ element = basicFixture.instantiate();
// getChangeRevisionActions is not called without
// set the following properies
element.change = {};
element.changeNum = '42';
element.latestPatchNum = '2';
- sandbox.stub(element.$.confirmCherrypick.$.restAPI,
+ sinon.stub(element.$.confirmCherrypick.$.restAPI,
'getRepoBranches').returns(Promise.resolve([]));
- sandbox.stub(element.$.confirmMove.$.restAPI,
+ sinon.stub(element.$.confirmMove.$.restAPI,
'getRepoBranches').returns(Promise.resolve([]));
return element.reload();
});
- teardown(() => {
- sandbox.restore();
- });
-
test('confirmSubmitDialog and confirmRebase properties are changed', () => {
changeRevisionActions = {};
element.reload();
@@ -2049,4 +2041,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata-it_test.html b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata-it_test.html
deleted file mode 100644
index d08f529..0000000
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata-it_test.html
+++ /dev/null
@@ -1,183 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-change-metadata</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="element">
- <template>
- <gr-change-metadata mutable="true"></gr-change-metadata>
- </template>
-</test-fixture>
-
-<test-fixture id="plugin-host">
- <template>
- <gr-plugin-host></gr-plugin-host>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import '../../plugins/gr-plugin-host/gr-plugin-host.js';
-import './gr-change-metadata.js';
-import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
-import {resetPlugins} from '../../../test/test-utils.js';
-import {pluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
-import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit.js';
-
-const pluginApi = _testOnly_initGerritPluginApi();
-
-suite('gr-change-metadata integration tests', () => {
- let sandbox;
- let element;
-
- const sectionSelectors = [
- 'section.strategy',
- 'section.topic',
- ];
-
- const labels = {
- CI: {
- all: [
- {value: 1, name: 'user 2', _account_id: 1},
- {value: 2, name: 'user '},
- ],
- values: {
- ' 0': 'Don\'t submit as-is',
- '+1': 'No score',
- '+2': 'Looks good to me',
- },
- },
- };
-
- const getStyle = function(selector, name) {
- return window.getComputedStyle(
- dom(element.root).querySelector(selector))[name];
- };
-
- function createElement() {
- const element = fixture('element');
- element.change = {labels, status: 'NEW'};
- element.revision = {};
- return element;
- }
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- stub('gr-rest-api-interface', {
- getConfig() { return Promise.resolve({}); },
- getLoggedIn() { return Promise.resolve(false); },
- deleteVote() { return Promise.resolve({ok: true}); },
- });
- });
-
- teardown(() => {
- sandbox.restore();
- resetPlugins();
- });
-
- suite('by default', () => {
- setup(done => {
- element = createElement();
- flush(done);
- });
-
- for (const sectionSelector of sectionSelectors) {
- test(sectionSelector + ' does not have display: none', () => {
- assert.notEqual(getStyle(sectionSelector, 'display'), 'none');
- });
- }
- });
-
- suite('with plugin style', () => {
- setup(done => {
- resetPlugins();
- const pluginHost = fixture('plugin-host');
- pluginHost.config = {
- plugin: {
- js_resource_paths: [],
- html_resource_paths: [
- new URL('test/plugin.html?' + Math.random(),
- window.location.href).toString(),
- ],
- },
- };
- element = createElement();
- const importSpy = sandbox.spy(element.$.externalStyle, '_import');
- pluginLoader.awaitPluginsLoaded().then(() => {
- Promise.all(importSpy.returnValues).then(() => {
- flush(done);
- });
- });
- });
-
- for (const sectionSelector of sectionSelectors) {
- test(sectionSelector + ' may have display: none', () => {
- assert.equal(getStyle(sectionSelector, 'display'), 'none');
- });
- }
- });
-
- suite('label updates', () => {
- let plugin;
-
- setup(() => {
- pluginApi.install(p => plugin = p, '0.1',
- new URL('test/plugin.html?' + Math.random(),
- window.location.href).toString());
- sandbox.stub(pluginLoader, 'arePluginsLoaded').returns(true);
- pluginLoader.loadPlugins([]);
- element = createElement();
- });
-
- test('labels changed callback', done => {
- let callCount = 0;
- const labelChangeSpy = sandbox.spy(arg => {
- callCount++;
- if (callCount === 1) {
- assert.deepEqual(arg, labels);
- assert.equal(arg.CI.all.length, 2);
- element.set(['change', 'labels'], {
- CI: {
- all: [
- {value: 1, name: 'user 2', _account_id: 1},
- ],
- values: {
- ' 0': 'Don\'t submit as-is',
- '+1': 'No score',
- '+2': 'Looks good to me',
- },
- },
- });
- } else if (callCount === 2) {
- assert.equal(arg.CI.all.length, 1);
- done();
- }
- });
-
- plugin.changeMetadata().onLabelsChanged(labelChangeSpy);
- });
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata-it_test.js b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata-it_test.js
new file mode 100644
index 0000000..50c2355
--- /dev/null
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata-it_test.js
@@ -0,0 +1,188 @@
+/**
+ * @license
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import '../../../test/common-test-setup-karma.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+import './gr-change-metadata.js';
+import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+import {resetPlugins} from '../../../test/test-utils.js';
+import {pluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
+import {pluginEndpoints} from '../../shared/gr-js-api-interface/gr-plugin-endpoints.js';
+import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit.js';
+
+const testHtmlPlugin = document.createElement('dom-module');
+testHtmlPlugin.innerHTML = `
+ <template>
+ <style>
+ html {
+ --change-metadata-assignee: {
+ display: none;
+ }
+ --change-metadata-label-status: {
+ display: none;
+ }
+ --change-metadata-strategy: {
+ display: none;
+ }
+ --change-metadata-topic: {
+ display: none;
+ }
+ }
+ </style>
+ </template>
+ `;
+testHtmlPlugin.register('my-plugin-style');
+
+const basicFixture = fixtureFromTemplate(
+ html`<gr-change-metadata mutable="true"></gr-change-metadata>`
+);
+
+const pluginApi = _testOnly_initGerritPluginApi();
+
+suite('gr-change-metadata integration tests', () => {
+ let element;
+
+ const sectionSelectors = [
+ 'section.strategy',
+ 'section.topic',
+ ];
+
+ const labels = {
+ CI: {
+ all: [
+ {value: 1, name: 'user 2', _account_id: 1},
+ {value: 2, name: 'user '},
+ ],
+ values: {
+ ' 0': 'Don\'t submit as-is',
+ '+1': 'No score',
+ '+2': 'Looks good to me',
+ },
+ },
+ };
+
+ const getStyle = function(selector, name) {
+ return window.getComputedStyle(
+ dom(element.root).querySelector(selector))[name];
+ };
+
+ function createElement() {
+ const element = basicFixture.instantiate();
+ element.change = {labels, status: 'NEW'};
+ element.revision = {};
+ return element;
+ }
+
+ setup(() => {
+ stub('gr-rest-api-interface', {
+ getConfig() { return Promise.resolve({}); },
+ getLoggedIn() { return Promise.resolve(false); },
+ deleteVote() { return Promise.resolve({ok: true}); },
+ });
+ });
+
+ teardown(() => {
+ resetPlugins();
+ });
+
+ suite('by default', () => {
+ setup(done => {
+ element = createElement();
+ flush(done);
+ });
+
+ for (const sectionSelector of sectionSelectors) {
+ test(sectionSelector + ' does not have display: none', () => {
+ assert.notEqual(getStyle(sectionSelector, 'display'), 'none');
+ });
+ }
+ });
+
+ suite('with plugin style', () => {
+ setup(done => {
+ resetPlugins();
+ pluginApi.install(plugin => {
+ plugin.registerStyleModule('change-metadata', 'my-plugin-style');
+ }, undefined, 'http://test.com/plugins/style.js');
+ element = createElement();
+ sinon.stub(pluginEndpoints, 'importUrl')
+ .callsFake( url => Promise.resolve());
+ pluginLoader.loadPlugins([]);
+ pluginLoader.awaitPluginsLoaded().then(() => {
+ flush(done);
+ });
+ });
+
+ teardown(() => {
+ document.body.querySelectorAll('custom-style')
+ .forEach(style => style.remove());
+ });
+
+ for (const sectionSelector of sectionSelectors) {
+ test('section.strategy may have display: none', () => {
+ assert.equal(getStyle(sectionSelector, 'display'), 'none');
+ });
+ }
+ });
+
+ suite('label updates', () => {
+ let plugin;
+
+ setup(() => {
+ pluginApi.install(p => {
+ plugin = p;
+ plugin.registerStyleModule('change-metadata', 'my-plugin-style');
+ }, undefined, 'http://test.com/plugins/style.js');
+ sinon.stub(pluginLoader, 'arePluginsLoaded').returns(true);
+ pluginLoader.loadPlugins([]);
+ element = createElement();
+ });
+
+ teardown(() => {
+ document.body.querySelectorAll('custom-style')
+ .forEach(style => style.remove());
+ });
+
+ test('labels changed callback', done => {
+ let callCount = 0;
+ const labelChangeSpy = sinon.spy(arg => {
+ callCount++;
+ if (callCount === 1) {
+ assert.deepEqual(arg, labels);
+ assert.equal(arg.CI.all.length, 2);
+ element.set(['change', 'labels'], {
+ CI: {
+ all: [
+ {value: 1, name: 'user 2', _account_id: 1},
+ ],
+ values: {
+ ' 0': 'Don\'t submit as-is',
+ '+1': 'No score',
+ '+2': 'Looks good to me',
+ },
+ },
+ });
+ } else if (callCount === 2) {
+ assert.equal(arg.CI.all.length, 1);
+ done();
+ }
+ });
+
+ plugin.changeMetadata().onLabelsChanged(labelChangeSpy);
+ });
+ });
+});
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_html.js b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_html.js
index ca176be..7d84835 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_html.js
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_html.js
@@ -108,7 +108,11 @@
<section>
<span class="title">Owner</span>
<span class="value">
- <gr-account-link account="[[change.owner]]"></gr-account-link>
+ <gr-account-link
+ account="[[change.owner]]"
+ change="[[change]]"
+ highlight-attention
+ ></gr-account-link>
<template is="dom-if" if="[[_pushCertificateValidation]]">
<gr-tooltip-content
has-tooltip=""
@@ -128,6 +132,8 @@
<span class="value">
<gr-account-link
account="[[_getNonOwnerRole(change, _CHANGE_ROLE.UPLOADER)]]"
+ change="[[change]]"
+ highlight-attention
></gr-account-link>
</span>
</section>
@@ -136,6 +142,8 @@
<span class="value">
<gr-account-link
account="[[_getNonOwnerRole(change, _CHANGE_ROLE.AUTHOR)]]"
+ change="[[change]]"
+ highlight-attention
></gr-account-link>
</span>
</section>
@@ -144,6 +152,8 @@
<span class="value">
<gr-account-link
account="[[_getNonOwnerRole(change, _CHANGE_ROLE.COMMITTER)]]"
+ change="[[change]]"
+ highlight-attention
></gr-account-link>
</span>
</section>
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.html b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.js
similarity index 91%
rename from polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.html
rename to polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.js
index 8e780d7..26baf3c 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.html
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.js
@@ -1,65 +1,44 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2015 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-change-metadata</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-change-metadata></gr-change-metadata>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import '../../core/gr-router/gr-router.js';
import './gr-change-metadata.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
import {pluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
+import {pluginEndpoints} from '../../shared/gr-js-api-interface/gr-plugin-endpoints.js';
import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit.js';
+const basicFixture = fixtureFromElement('gr-change-metadata');
+
const pluginApi = _testOnly_initGerritPluginApi();
suite('gr-change-metadata tests', () => {
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
- stub('gr-endpoint-decorator', {
- _import: sandbox.stub().returns(Promise.resolve()),
- });
stub('gr-rest-api-interface', {
getConfig() { return Promise.resolve({}); },
getLoggedIn() { return Promise.resolve(false); },
});
- element = fixture('basic');
- });
-
- teardown(() => {
- sandbox.restore();
+ element = basicFixture.instantiate();
+ sinon.stub(pluginEndpoints, 'importUrl')
+ .callsFake( url => Promise.resolve());
});
test('computed fields', () => {
@@ -127,7 +106,7 @@
});
test('weblinks use GerritNav interface', () => {
- const weblinksStub = sandbox.stub(GerritNav, '_generateWeblinks')
+ const weblinksStub = sinon.stub(GerritNav, '_generateWeblinks')
.returns([{name: 'stubb', url: '#s'}]);
element.commitInfo = {};
element.serverConfig = {};
@@ -170,7 +149,7 @@
test('weblinks are visible when other weblinks', () => {
const router = document.createElement('gr-router');
- sandbox.stub(GerritNav, '_generateWeblinks',
+ sinon.stub(GerritNav, '_generateWeblinks').callsFake(
router._generateWeblinks.bind(router));
element.commitInfo = {web_links: [{name: 'test', url: '#'}]};
@@ -186,7 +165,7 @@
test('weblinks are visible when gitiles and other weblinks', () => {
const router = document.createElement('gr-router');
- sandbox.stub(GerritNav, '_generateWeblinks',
+ sinon.stub(GerritNav, '_generateWeblinks').callsFake(
router._generateWeblinks.bind(router));
element.commitInfo = {
@@ -628,7 +607,7 @@
suite('remove reviewer votes', () => {
setup(() => {
- sandbox.stub(element, '_computeTopicReadOnly').returns(true);
+ sinon.stub(element, '_computeTopicReadOnly').returns(true);
element.change = {
_number: 42,
change_id: 'the id',
@@ -663,8 +642,8 @@
let setStub;
setup(() => {
- deleteStub = sandbox.stub(element.$.restAPI, 'deleteAssignee');
- setStub = sandbox.stub(element.$.restAPI, 'setAssignee');
+ deleteStub = sinon.stub(element.$.restAPI, 'deleteAssignee');
+ setStub = sinon.stub(element.$.restAPI, 'setAssignee');
element.serverConfig = {
change: {
enable_assignee: true,
@@ -708,10 +687,10 @@
test('changing topic', () => {
const newTopic = 'the new topic';
- sandbox.stub(element.$.restAPI, 'setChangeTopic').returns(
+ sinon.stub(element.$.restAPI, 'setChangeTopic').returns(
Promise.resolve(newTopic));
element._handleTopicChanged({}, newTopic);
- const topicChangedSpy = sandbox.spy();
+ const topicChangedSpy = sinon.spy();
element.addEventListener('topic-changed', topicChangedSpy);
assert.isTrue(element.$.restAPI.setChangeTopic.calledWith(
42, newTopic));
@@ -723,12 +702,12 @@
});
test('topic removal', () => {
- sandbox.stub(element.$.restAPI, 'setChangeTopic').returns(
+ sinon.stub(element.$.restAPI, 'setChangeTopic').returns(
Promise.resolve());
const chip = element.shadowRoot
.querySelector('gr-linked-chip');
const remove = chip.$.remove;
- const topicChangedSpy = sandbox.spy();
+ const topicChangedSpy = sinon.spy();
element.addEventListener('topic-changed', topicChangedSpy);
MockInteractions.tap(remove);
assert.isTrue(chip.disabled);
@@ -746,7 +725,7 @@
flushAsynchronousOperations();
element._newHashtag = 'new hashtag';
const newHashtag = ['new hashtag'];
- sandbox.stub(element.$.restAPI, 'setChangeHashtag').returns(
+ sinon.stub(element.$.restAPI, 'setChangeHashtag').returns(
Promise.resolve(newHashtag));
element._handleHashtagChanged({}, 'new hashtag');
assert.isTrue(element.$.restAPI.setChangeHashtag.calledWith(
@@ -766,7 +745,7 @@
const label = element.shadowRoot
.querySelector('.topicEditableLabel');
assert.ok(label);
- sandbox.stub(label, 'open');
+ sinon.stub(label, 'open');
element.editTopic();
flushAsynchronousOperations();
@@ -797,4 +776,3 @@
});
});
});
-</script>
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/test/plugin.html b/polygerrit-ui/app/elements/change/gr-change-metadata/test/plugin.html
deleted file mode 100644
index b3aa98f..0000000
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/test/plugin.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<dom-module id="my-plugin">
- <script>
- Gerrit.install(plugin => {
- plugin.registerStyleModule('change-metadata', 'my-plugin-style');
- });
- </script>
-</dom-module>
-
-<dom-module id="my-plugin-style">
- <template>
- <style>
- html {
- --change-metadata-assignee: {
- display: none;
- }
- --change-metadata-label-status: {
- display: none;
- }
- --change-metadata-strategy: {
- display: none;
- }
- --change-metadata-topic: {
- display: none;
- }
- }
- </style>
- </template>
-</dom-module>
diff --git a/polygerrit-ui/app/elements/change/gr-change-requirements/gr-change-requirements_test.html b/polygerrit-ui/app/elements/change/gr-change-requirements/gr-change-requirements_test.js
similarity index 81%
rename from polygerrit-ui/app/elements/change/gr-change-requirements/gr-change-requirements_test.html
rename to polygerrit-ui/app/elements/change/gr-change-requirements/gr-change-requirements_test.js
index 276e821..d8a90fc 100644
--- a/polygerrit-ui/app/elements/change/gr-change-requirements/gr-change-requirements_test.html
+++ b/polygerrit-ui/app/elements/change/gr-change-requirements/gr-change-requirements_test.js
@@ -1,45 +1,31 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2018 The Android Open Source Project
+/**
+ * @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.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-change-requirements</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-change-requirements></gr-change-requirements>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-change-requirements.js';
import {isHidden} from '../../../test/test-utils.js';
+
+const basicFixture = fixtureFromElement('gr-change-requirements');
+
suite('gr-change-metadata tests', () => {
let element;
setup(() => {
- element = fixture('basic');
+ element = basicFixture.instantiate();
});
test('requirements computed fields', () => {
@@ -233,4 +219,4 @@
assert.strictEqual(requirement.querySelector('.approved'), null);
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
index 799adde..072708e 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
@@ -441,6 +441,13 @@
[this.Shortcut.COLLAPSE_ALL_MESSAGES]: '_handleCollapseAllMessages',
[this.Shortcut.OPEN_DIFF_PREFS]: '_handleOpenDiffPrefsShortcut',
[this.Shortcut.EDIT_TOPIC]: '_handleEditTopic',
+ [this.Shortcut.DIFF_AGAINST_BASE]: '_handleDiffAgainstBase',
+ [this.Shortcut.DIFF_AGAINST_LATEST]: '_handleDiffAgainstLatest',
+ [this.Shortcut.DIFF_BASE_AGAINST_LEFT]: '_handleDiffBaseAgainstLeft',
+ [this.Shortcut.DIFF_RIGHT_AGAINST_LATEST]:
+ '_handleDiffRightAgainstLatest',
+ [this.Shortcut.DIFF_BASE_AGAINST_LATEST]:
+ '_handleDiffBaseAgainstLatest',
};
}
@@ -718,7 +725,7 @@
if ([
change,
mergeable,
- ].some(arg => arg === undefined)) {
+ ].includes(undefined)) {
// To keep consistent with Polymer 1, we are returning undefined
// if not all dependencies are defined
return undefined;
@@ -1112,7 +1119,7 @@
_paramsAndChangeChanged(value, change) {
// Polymer 2: check for undefined
- if ([value, change].some(arg => arg === undefined)) {
+ if ([value, change].includes(undefined)) {
return;
}
@@ -1293,7 +1300,7 @@
_computeChangeIdCommitMessageError(commitMessage, change) {
// Polymer 2: check for undefined
- if ([commitMessage, change].some(arg => arg === undefined)) {
+ if ([commitMessage, change].includes(undefined)) {
return undefined;
}
@@ -1352,7 +1359,7 @@
_computeReplyButtonLabel(changeRecord, canStartReview) {
// Polymer 2: check for undefined
- if ([changeRecord, canStartReview].some(arg => arg === undefined)) {
+ if ([changeRecord, canStartReview].includes(undefined)) {
return 'Reply';
}
if (canStartReview) {
@@ -1393,7 +1400,7 @@
this.modifierPressed(e)) { return; }
e.preventDefault();
- this.$.downloadOverlay.open();
+ this._handleOpenDownloadDialog();
}
_handleEditTopic(e) {
@@ -1404,6 +1411,82 @@
this.$.metadata.editTopic();
}
+ _handleDiffAgainstBase(e) {
+ if (this.shouldSuppressKeyboardShortcut(e)) { return; }
+ if (this.patchNumEquals(this._patchRange.basePatchNum, 'PARENT')) {
+ this.dispatchEvent(new CustomEvent('show-alert', {
+ detail: {
+ message: 'Base is already selected.',
+ },
+ composed: true, bubbles: true,
+ }));
+ return;
+ }
+ GerritNav.navigateToChange(this._change, this._patchRange.patchNum);
+ }
+
+ _handleDiffBaseAgainstLeft(e) {
+ if (this.shouldSuppressKeyboardShortcut(e)) { return; }
+ if (this.patchNumEquals(this._patchRange.basePatchNum, 'PARENT')) {
+ this.dispatchEvent(new CustomEvent('show-alert', {
+ detail: {
+ message: 'Left is already base.',
+ },
+ composed: true, bubbles: true,
+ }));
+ return;
+ }
+ GerritNav.navigateToChange(this._change, this._patchRange.basePatchNum);
+ }
+
+ _handleDiffAgainstLatest(e) {
+ if (this.shouldSuppressKeyboardShortcut(e)) { return; }
+ const latestPatchNum = this.computeLatestPatchNum(this._allPatchSets);
+ if (this.patchNumEquals(this._patchRange.patchNum, latestPatchNum)) {
+ this.dispatchEvent(new CustomEvent('show-alert', {
+ detail: {
+ message: 'Latest is already selected.',
+ },
+ composed: true, bubbles: true,
+ }));
+ return;
+ }
+ GerritNav.navigateToChange(this._change, latestPatchNum,
+ this._patchRange.basePatchNum);
+ }
+
+ _handleDiffRightAgainstLatest(e) {
+ if (this.shouldSuppressKeyboardShortcut(e)) { return; }
+ const latestPatchNum = this.computeLatestPatchNum(this._allPatchSets);
+ if (this.patchNumEquals(this._patchRange.patchNum, latestPatchNum)) {
+ this.dispatchEvent(new CustomEvent('show-alert', {
+ detail: {
+ message: 'Right is already latest.',
+ },
+ composed: true, bubbles: true,
+ }));
+ return;
+ }
+ GerritNav.navigateToChange(this._change, latestPatchNum,
+ this._patchRange.patchNum);
+ }
+
+ _handleDiffBaseAgainstLatest(e) {
+ if (this.shouldSuppressKeyboardShortcut(e)) { return; }
+ const latestPatchNum = this.computeLatestPatchNum(this._allPatchSets);
+ if (this.patchNumEquals(this._patchRange.patchNum, latestPatchNum) &&
+ this.patchNumEquals(this._patchRange.basePatchNum, 'PARENT')) {
+ this.dispatchEvent(new CustomEvent('show-alert', {
+ detail: {
+ message: 'Already diffing base against latest.',
+ },
+ composed: true, bubbles: true,
+ }));
+ return;
+ }
+ GerritNav.navigateToChange(this._change, latestPatchNum);
+ }
+
_handleRefreshChange(e) {
if (this.shouldSuppressKeyboardShortcut(e)) { return; }
e.preventDefault();
@@ -2100,7 +2183,7 @@
}
_computeEditMode(patchRangeRecord, paramsRecord) {
- if ([patchRangeRecord, paramsRecord].some(arg => arg === undefined)) {
+ if ([patchRangeRecord, paramsRecord].includes(undefined)) {
return undefined;
}
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.js b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.js
index f5a0463..c9fdb78 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.js
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.js
@@ -777,6 +777,7 @@
permitted-labels="[[_change.permitted_labels]]"
draft-comment-threads="[[_draftCommentThreads]]"
project-config="[[_projectConfig]]"
+ server-config="[[_serverConfig]]"
can-be-started="[[_canStartReview]]"
on-send="_handleReplySent"
on-cancel="_handleReplyCancel"
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.js b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.js
index faa81b6..d2e8ea7 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.js
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.js
@@ -21,7 +21,6 @@
import {PrimaryTab, SecondaryTab, ChangeStatus} from '../../../constants/constants.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
-import {KeyboardShortcutBinder} from '../../../behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.js';
import {GrEditConstants} from '../../edit/gr-edit-constants.js';
import {_testOnly_resetEndpoints} from '../../shared/gr-js-api-interface/gr-plugin-endpoints.js';
import {getComputedStyleValue} from '../../../utils/dom-util.js';
@@ -30,27 +29,35 @@
import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit.js';
import 'lodash/lodash.js';
+import {TestKeyboardShortcutBinder} from '../../../test/test-utils.js';
const pluginApi = _testOnly_initGerritPluginApi();
const fixture = fixtureFromElement('gr-change-view');
suite('gr-change-view tests', () => {
- const kb = KeyboardShortcutBinder;
- kb.bindShortcut(kb.Shortcut.SEND_REPLY, 'ctrl+enter');
- kb.bindShortcut(kb.Shortcut.REFRESH_CHANGE, 'shift+r');
- kb.bindShortcut(kb.Shortcut.OPEN_REPLY_DIALOG, 'a');
- kb.bindShortcut(kb.Shortcut.OPEN_DOWNLOAD_DIALOG, 'd');
- kb.bindShortcut(kb.Shortcut.TOGGLE_DIFF_MODE, 'm');
- kb.bindShortcut(kb.Shortcut.TOGGLE_CHANGE_STAR, 's');
- kb.bindShortcut(kb.Shortcut.UP_TO_DASHBOARD, 'u');
- kb.bindShortcut(kb.Shortcut.EXPAND_ALL_MESSAGES, 'x');
- kb.bindShortcut(kb.Shortcut.COLLAPSE_ALL_MESSAGES, 'z');
- kb.bindShortcut(kb.Shortcut.OPEN_DIFF_PREFS, ',');
- kb.bindShortcut(kb.Shortcut.EDIT_TOPIC, 't');
-
let element;
- let sandbox;
+
let navigateToChangeStub;
+
+ suiteSetup(() => {
+ const kb = TestKeyboardShortcutBinder.push();
+ kb.bindShortcut(kb.Shortcut.SEND_REPLY, 'ctrl+enter');
+ kb.bindShortcut(kb.Shortcut.REFRESH_CHANGE, 'shift+r');
+ kb.bindShortcut(kb.Shortcut.OPEN_REPLY_DIALOG, 'a');
+ kb.bindShortcut(kb.Shortcut.OPEN_DOWNLOAD_DIALOG, 'd');
+ kb.bindShortcut(kb.Shortcut.TOGGLE_DIFF_MODE, 'm');
+ kb.bindShortcut(kb.Shortcut.TOGGLE_CHANGE_STAR, 's');
+ kb.bindShortcut(kb.Shortcut.UP_TO_DASHBOARD, 'u');
+ kb.bindShortcut(kb.Shortcut.EXPAND_ALL_MESSAGES, 'x');
+ kb.bindShortcut(kb.Shortcut.COLLAPSE_ALL_MESSAGES, 'z');
+ kb.bindShortcut(kb.Shortcut.OPEN_DIFF_PREFS, ',');
+ kb.bindShortcut(kb.Shortcut.EDIT_TOPIC, 't');
+ });
+
+ suiteTeardown(() => {
+ TestKeyboardShortcutBinder.pop();
+ });
+
const TEST_SCROLL_TOP_PX = 100;
const ROBOT_COMMENTS_LIMIT = 10;
@@ -278,13 +285,9 @@
];
setup(() => {
- sandbox = sinon.sandbox.create();
- stub('gr-endpoint-decorator', {
- _import: sandbox.stub().returns(Promise.resolve()),
- });
// Since pluginEndpoints are global, must reset state.
_testOnly_resetEndpoints();
- navigateToChangeStub = sandbox.stub(GerritNav, 'navigateToChange');
+ navigateToChangeStub = sinon.stub(GerritNav, 'navigateToChange');
stub('gr-rest-api-interface', {
getConfig() { return Promise.resolve({test: 'config'}); },
getAccount() { return Promise.resolve(null); },
@@ -294,7 +297,7 @@
_fetchSharedCacheURL() { return Promise.resolve({}); },
});
element = fixture.instantiate();
- sandbox.stub(element.$.actions, 'reload').returns(Promise.resolve());
+ sinon.stub(element.$.actions, 'reload').returns(Promise.resolve());
pluginLoader.loadPlugins([]);
pluginApi.install(
plugin => {
@@ -314,7 +317,6 @@
teardown(done => {
flush(() => {
- sandbox.restore();
done();
});
});
@@ -328,14 +330,89 @@
basePatchNum: 'PARENT',
patchNum: 1,
};
- const getUrlStub = sandbox.stub(GerritNav, 'getUrlForChange');
- const replaceStateStub = sandbox.stub(history, 'replaceState');
+ const getUrlStub = sinon.stub(GerritNav, 'getUrlForChange');
+ const replaceStateStub = sinon.stub(history, 'replaceState');
element._handleMessageAnchorTap({detail: {id: 'a12345'}});
assert.equal(getUrlStub.lastCall.args[4], '#message-a12345');
assert.isTrue(replaceStateStub.called);
});
+ test('_handleDiffAgainstBase', () => {
+ element._changeNum = '1';
+ element._patchRange = {
+ patchNum: 3,
+ basePatchNum: 1,
+ };
+ sinon.stub(element, 'computeLatestPatchNum').returns(10);
+ sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
+ element._handleDiffAgainstBase(new CustomEvent(''));
+ assert(navigateToChangeStub.called);
+ const args = navigateToChangeStub.getCall(0).args;
+ assert.equal(args[1], 3);
+ assert.isNotOk(args[0]);
+ });
+
+ test('_handleDiffAgainstLatest', () => {
+ element._changeNum = '1';
+ element._patchRange = {
+ basePatchNum: 1,
+ patchNum: 3,
+ };
+ sinon.stub(element, 'computeLatestPatchNum').returns(10);
+ sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
+ element._handleDiffAgainstLatest(new CustomEvent(''));
+ assert(navigateToChangeStub.called);
+ const args = navigateToChangeStub.getCall(0).args;
+ assert.equal(args[1], 10);
+ assert.equal(args[2], 1);
+ });
+
+ test('_handleDiffBaseAgainstLeft', () => {
+ element._changeNum = '1';
+ element._patchRange = {
+ patchNum: 3,
+ basePatchNum: 1,
+ };
+ sinon.stub(element, 'computeLatestPatchNum').returns(10);
+ sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
+ element._handleDiffBaseAgainstLeft(new CustomEvent(''));
+ assert(navigateToChangeStub.called);
+ const args = navigateToChangeStub.getCall(0).args;
+ assert.equal(args[1], 1);
+ assert.isNotOk(args[0]);
+ });
+
+ test('_handleDiffRightAgainstLatest', () => {
+ element._changeNum = '1';
+ element._patchRange = {
+ basePatchNum: 1,
+ patchNum: 3,
+ };
+ sinon.stub(element, 'computeLatestPatchNum').returns(10);
+ sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
+ element._handleDiffRightAgainstLatest(new CustomEvent(''));
+ assert(navigateToChangeStub.called);
+ const args = navigateToChangeStub.getCall(0).args;
+ assert.equal(args[1], 10);
+ assert.equal(args[2], 3);
+ });
+
+ test('_handleDiffBaseAgainstLatest', () => {
+ element._changeNum = '1';
+ element._patchRange = {
+ basePatchNum: 1,
+ patchNum: 3,
+ };
+ sinon.stub(element, 'computeLatestPatchNum').returns(10);
+ sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
+ element._handleDiffBaseAgainstLatest(new CustomEvent(''));
+ assert(navigateToChangeStub.called);
+ const args = navigateToChangeStub.getCall(0).args;
+ assert.equal(args[1], 10);
+ assert.isNotOk(args[2]);
+ });
+
suite('plugins adding to file tab', () => {
setup(done => {
// Resolving it here instead of during setup() as other tests depend
@@ -363,7 +440,14 @@
});
test('show-primary-tab switched primary tab correctly', done => {
- element.fire('show-primary-tab', {tab: 'change-view-tab-header-url'});
+ element.dispatchEvent(
+ new CustomEvent('show-primary-tab', {
+ composed: true,
+ bubbles: true,
+ detail: {
+ tab: 'change-view-tab-header-url',
+ },
+ }));
flush(() => {
assert.equal(element._activeTabs[0], 'change-view-tab-header-url');
done();
@@ -415,19 +499,19 @@
suite('keyboard shortcuts', () => {
test('t to add topic', () => {
- const editStub = sandbox.stub(element.$.metadata, 'editTopic');
+ const editStub = sinon.stub(element.$.metadata, 'editTopic');
MockInteractions.pressAndReleaseKeyOn(element, 83, null, 't');
assert(editStub.called);
});
test('S should toggle the CL star', () => {
- const starStub = sandbox.stub(element.$.changeStar, 'toggleStar');
+ const starStub = sinon.stub(element.$.changeStar, 'toggleStar');
MockInteractions.pressAndReleaseKeyOn(element, 83, null, 's');
assert(starStub.called);
});
test('U should navigate to root if no backPage set', () => {
- const relativeNavStub = sandbox.stub(GerritNav,
+ const relativeNavStub = sinon.stub(GerritNav,
'navigateToRelativeUrl');
MockInteractions.pressAndReleaseKeyOn(element, 85, null, 'u');
assert.isTrue(relativeNavStub.called);
@@ -436,7 +520,7 @@
});
test('U should navigate to backPage if set', () => {
- const relativeNavStub = sandbox.stub(GerritNav,
+ const relativeNavStub = sinon.stub(GerritNav,
'navigateToRelativeUrl');
element.backPage = '/dashboard/self';
MockInteractions.pressAndReleaseKeyOn(element, 85, null, 'u');
@@ -446,8 +530,8 @@
});
test('A fires an error event when not logged in', done => {
- sandbox.stub(element, '_getLoggedIn').returns(Promise.resolve(false));
- const loggedInErrorSpy = sandbox.spy();
+ sinon.stub(element, '_getLoggedIn').returns(Promise.resolve(false));
+ const loggedInErrorSpy = sinon.spy();
element.addEventListener('show-auth-required', loggedInErrorSpy);
MockInteractions.pressAndReleaseKeyOn(element, 65, null, 'a');
flush(() => {
@@ -458,7 +542,7 @@
});
test('shift A does not open reply overlay', done => {
- sandbox.stub(element, '_getLoggedIn').returns(Promise.resolve(true));
+ sinon.stub(element, '_getLoggedIn').returns(Promise.resolve(true));
MockInteractions.pressAndReleaseKeyOn(element, 65, 'shift', 'a');
flush(() => {
assert.isFalse(element.$.replyOverlay.opened);
@@ -467,11 +551,11 @@
});
test('A toggles overlay when logged in', done => {
- sandbox.stub(element, '_getLoggedIn').returns(Promise.resolve(true));
- sandbox.stub(element.$.replyDialog, 'fetchChangeUpdates')
+ sinon.stub(element, '_getLoggedIn').returns(Promise.resolve(true));
+ sinon.stub(element.$.replyDialog, 'fetchChangeUpdates')
.returns(Promise.resolve({isLatest: true}));
element._change = {labels: {}};
- const openSpy = sandbox.spy(element, '_openReplyDialog');
+ const openSpy = sinon.spy(element, '_openReplyDialog');
MockInteractions.pressAndReleaseKeyOn(element, 65, null, 'a');
flush(() => {
@@ -501,7 +585,7 @@
},
},
};
- sandbox.spy(element, '_handleHideBackgroundContent');
+ sinon.spy(element, '_handleHideBackgroundContent');
element.$.replyDialog.dispatchEvent(
new CustomEvent('fullscreen-overlay-opened', {
composed: true, bubbles: true,
@@ -526,7 +610,7 @@
},
},
};
- sandbox.spy(element, '_handleShowBackgroundContent');
+ sinon.spy(element, '_handleShowBackgroundContent');
element.$.replyDialog.dispatchEvent(
new CustomEvent('fullscreen-overlay-closed', {
composed: true, bubbles: true,
@@ -537,7 +621,7 @@
test('expand all messages when expand-diffs fired', () => {
const handleExpand =
- sandbox.stub(element.$.fileList, 'expandAllDiffs');
+ sinon.stub(element.$.fileList, 'expandAllDiffs');
element.$.fileListHeader.dispatchEvent(
new CustomEvent('expand-diffs', {
composed: true, bubbles: true,
@@ -547,7 +631,7 @@
test('collapse all messages when collapse-diffs fired', () => {
const handleCollapse =
- sandbox.stub(element.$.fileList, 'collapseAllDiffs');
+ sinon.stub(element.$.fileList, 'collapseAllDiffs');
element.$.fileListHeader.dispatchEvent(
new CustomEvent('collapse-diffs', {
composed: true, bubbles: true,
@@ -557,7 +641,7 @@
test('X should expand all messages', done => {
flush(() => {
- const handleExpand = sandbox.stub(element.messagesList,
+ const handleExpand = sinon.stub(element.messagesList,
'handleExpandCollapse');
MockInteractions.pressAndReleaseKeyOn(element, 88, null, 'x');
assert(handleExpand.calledWith(true));
@@ -567,7 +651,7 @@
test('Z should collapse all messages', done => {
flush(() => {
- const handleExpand = sandbox.stub(element.messagesList,
+ const handleExpand = sinon.stub(element.messagesList,
'handleExpandCollapse');
MockInteractions.pressAndReleaseKeyOn(element, 90, null, 'z');
assert(handleExpand.calledWith(false));
@@ -595,8 +679,8 @@
};
navigateToChangeStub.restore();
- navigateToChangeStub = sandbox.stub(GerritNav, 'navigateToChange',
- (change, patchNum, basePatchNum) => {
+ navigateToChangeStub = sinon.stub(GerritNav, 'navigateToChange')
+ .callsFake((change, patchNum, basePatchNum) => {
assert.equal(change, element._change);
assert.isUndefined(patchNum);
assert.isUndefined(basePatchNum);
@@ -607,13 +691,15 @@
});
test('d should open download overlay', () => {
- const stub = sandbox.stub(element.$.downloadOverlay, 'open');
+ const stub = sinon.stub(element.$.downloadOverlay, 'open').returns(
+ new Promise(resolve => {})
+ );
MockInteractions.pressAndReleaseKeyOn(element, 68, null, 'd');
assert.isTrue(stub.called);
});
test(', should open diff preferences', () => {
- const stub = sandbox.stub(
+ const stub = sinon.stub(
element.$.fileList.$.diffPreferencesDialog, 'open');
element._loggedIn = false;
element.disableDiffPrefs = true;
@@ -630,8 +716,8 @@
});
test('m should toggle diff mode', () => {
- sandbox.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
- const setModeStub = sandbox.stub(element.$.fileListHeader,
+ sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
+ const setModeStub = sinon.stub(element.$.fileListHeader,
'setDiffViewMode');
const e = {preventDefault: () => {}};
flushAsynchronousOperations();
@@ -663,7 +749,7 @@
setup(() => {
// Fake computeDraftCount as its required for ChangeComments,
// see gr-comment-api#reloadDrafts.
- reloadStub = sandbox.stub(element.$.commentAPI, 'reloadDrafts')
+ reloadStub = sinon.stub(element.$.commentAPI, 'reloadDrafts')
.returns(Promise.resolve({
drafts,
getAllThreadsForChange: () => ([]),
@@ -698,7 +784,7 @@
setup(() => {
// Fake computeDraftCount as its required for ChangeComments,
// see gr-comment-api#reloadDrafts.
- sandbox.stub(element.$.commentAPI, 'reloadDrafts')
+ sinon.stub(element.$.commentAPI, 'reloadDrafts')
.returns(Promise.resolve({
drafts: {},
getAllThreadsForChange: () => THREADS,
@@ -745,7 +831,7 @@
});
test('diff comments modified', () => {
- sandbox.spy(element, '_handleReloadCommentThreads');
+ sinon.spy(element, '_handleReloadCommentThreads');
return element._reloadComments().then(() => {
element.dispatchEvent(
new CustomEvent('diff-comments-modified', {
@@ -756,7 +842,7 @@
});
test('thread list modified', () => {
- sandbox.spy(element, '_handleReloadDiffComments');
+ sinon.spy(element, '_handleReloadDiffComments');
element._activeTabs = [PrimaryTab.COMMENT_THREADS, SecondaryTab.CHANGE_LOG];
flushAsynchronousOperations();
@@ -815,9 +901,9 @@
},
},
};
- sandbox.stub(element.$.relatedChanges, 'reload');
- sandbox.stub(element, '_reload').returns(Promise.resolve());
- sandbox.spy(element, '_paramsChanged');
+ sinon.stub(element.$.relatedChanges, 'reload');
+ sinon.stub(element, '_reload').returns(Promise.resolve());
+ sinon.spy(element, '_paramsChanged');
element.params = {view: 'change', changeNum: '1'};
});
});
@@ -915,7 +1001,7 @@
});
test('download tap calls _handleOpenDownloadDialog', () => {
- sandbox.stub(element, '_handleOpenDownloadDialog');
+ sinon.stub(element, '_handleOpenDownloadDialog');
element.$.actions.dispatchEvent(
new CustomEvent('download-tap', {
composed: true, bubbles: true,
@@ -931,7 +1017,7 @@
});
test('_changeStatuses', () => {
- sandbox.stub(element, 'changeStatuses').returns(
+ sinon.stub(element, 'changeStatuses').returns(
['Merged', 'WIP']);
element._loading = false;
element._change = {
@@ -963,7 +1049,7 @@
});
test('diff preferences open when open-diff-prefs is fired', () => {
- const overlayOpenStub = sandbox.stub(element.$.fileList,
+ const overlayOpenStub = sinon.stub(element.$.fileList,
'openDiffPrefs');
element.$.fileListHeader.dispatchEvent(
new CustomEvent('open-diff-prefs', {
@@ -1021,7 +1107,7 @@
},
};
flushAsynchronousOperations();
- const reloadStub = sandbox.stub(element, '_reload');
+ const reloadStub = sinon.stub(element, '_reload');
element.splice('_change.labels.test.all', 0, 1);
assert.isFalse(reloadStub.called);
element._change.labels.test.all.push(vote);
@@ -1126,7 +1212,7 @@
test('_setDiffViewMode is called with reset when new change is loaded',
() => {
- sandbox.stub(element, '_setDiffViewMode');
+ sinon.stub(element, '_setDiffViewMode');
element.viewState = {changeNum: 1};
element._changeNum = 2;
element._resetFileListViewState();
@@ -1141,7 +1227,7 @@
});
test('diffMode defaults to side by side without preferences', done => {
- sandbox.stub(element.$.restAPI, 'getPreferences').returns(
+ sinon.stub(element.$.restAPI, 'getPreferences').returns(
Promise.resolve({}));
// No user prefs or diff view mode set.
@@ -1152,7 +1238,7 @@
});
test('diffMode defaults to preference when not already set', done => {
- sandbox.stub(element.$.restAPI, 'getPreferences').returns(
+ sinon.stub(element.$.restAPI, 'getPreferences').returns(
Promise.resolve({default_diff_view: 'UNIFIED'}));
element._setDiffViewMode().then(() => {
@@ -1163,7 +1249,7 @@
test('existing diffMode overrides preference', done => {
element.viewState.diffMode = 'SIDE_BY_SIDE';
- sandbox.stub(element.$.restAPI, 'getPreferences').returns(
+ sinon.stub(element.$.restAPI, 'getPreferences').returns(
Promise.resolve({default_diff_view: 'UNIFIED'}));
element._setDiffViewMode().then(() => {
assert.equal(element.viewState.diffMode, 'SIDE_BY_SIDE');
@@ -1172,13 +1258,13 @@
});
test('don’t reload entire page when patchRange changes', () => {
- const reloadStub = sandbox.stub(element, '_reload',
+ const reloadStub = sinon.stub(element, '_reload').callsFake(
() => Promise.resolve());
- const reloadPatchDependentStub = sandbox.stub(element,
- '_reloadPatchNumDependentResources',
- () => Promise.resolve());
- const relatedClearSpy = sandbox.spy(element.$.relatedChanges, 'clear');
- const collapseStub = sandbox.stub(element.$.fileList, 'collapseAllDiffs');
+ const reloadPatchDependentStub = sinon.stub(element,
+ '_reloadPatchNumDependentResources')
+ .callsFake(() => Promise.resolve());
+ const relatedClearSpy = sinon.spy(element.$.relatedChanges, 'clear');
+ const collapseStub = sinon.stub(element.$.fileList, 'collapseAllDiffs');
const value = {
view: GerritNav.View.CHANGE,
@@ -1200,9 +1286,9 @@
});
test('reload entire page when patchRange doesnt change', () => {
- const reloadStub = sandbox.stub(element, '_reload',
+ const reloadStub = sinon.stub(element, '_reload').callsFake(
() => Promise.resolve());
- const collapseStub = sandbox.stub(element.$.fileList, 'collapseAllDiffs');
+ const collapseStub = sinon.stub(element.$.fileList, 'collapseAllDiffs');
const value = {
view: GerritNav.View.CHANGE,
};
@@ -1215,8 +1301,8 @@
});
test('related changes are not updated after other action', done => {
- sandbox.stub(element, '_reload', () => Promise.resolve());
- sandbox.stub(element.$.relatedChanges, 'reload');
+ sinon.stub(element, '_reload').callsFake(() => Promise.resolve());
+ sinon.stub(element.$.relatedChanges, 'reload');
const e = {detail: {action: 'abandon'}};
element._handleReloadChange(e).then(() => {
assert.isFalse(navigateToChangeStub.called);
@@ -1249,7 +1335,7 @@
},
current_revision: 'rev3',
};
- sandbox.stub(GerritNav, 'getUrlForChange')
+ sinon.stub(GerritNav, 'getUrlForChange')
.returns('/change/123');
assert.equal(
element._computeCopyTextForTitle(change),
@@ -1291,7 +1377,7 @@
});
test('_handleCommitMessageSave trims trailing whitespace', () => {
- const putStub = sandbox.stub(element.$.restAPI, 'putChangeCommitMessage')
+ const putStub = sinon.stub(element.$.restAPI, 'putChangeCommitMessage')
.returns(Promise.resolve({}));
const mockEvent = content => { return {detail: {content}}; };
@@ -1378,13 +1464,14 @@
});
test('topic is coalesced to null', done => {
- sandbox.stub(element, '_changeChanged');
- sandbox.stub(element.$.restAPI, 'getChangeDetail', () => Promise.resolve({
- id: '123456789',
- labels: {},
- current_revision: 'foo',
- revisions: {foo: {commit: {}}},
- }));
+ sinon.stub(element, '_changeChanged');
+ sinon.stub(element.$.restAPI, 'getChangeDetail').callsFake(
+ () => Promise.resolve({
+ id: '123456789',
+ labels: {},
+ current_revision: 'foo',
+ revisions: {foo: {commit: {}}},
+ }));
element._getChangeDetail().then(() => {
assert.isNull(element._change.topic);
@@ -1393,13 +1480,14 @@
});
test('commit sha is populated from getChangeDetail', done => {
- sandbox.stub(element, '_changeChanged');
- sandbox.stub(element.$.restAPI, 'getChangeDetail', () => Promise.resolve({
- id: '123456789',
- labels: {},
- current_revision: 'foo',
- revisions: {foo: {commit: {}}},
- }));
+ sinon.stub(element, '_changeChanged');
+ sinon.stub(element.$.restAPI, 'getChangeDetail').callsFake(
+ () => Promise.resolve({
+ id: '123456789',
+ labels: {},
+ current_revision: 'foo',
+ revisions: {foo: {commit: {}}},
+ }));
element._getChangeDetail().then(() => {
assert.equal('foo', element._commitInfo.commit);
@@ -1408,14 +1496,15 @@
});
test('edit is added to change', () => {
- sandbox.stub(element, '_changeChanged');
- sandbox.stub(element.$.restAPI, 'getChangeDetail', () => Promise.resolve({
- id: '123456789',
- labels: {},
- current_revision: 'foo',
- revisions: {foo: {commit: {}}},
- }));
- sandbox.stub(element, '_getEdit', () => Promise.resolve({
+ sinon.stub(element, '_changeChanged');
+ sinon.stub(element.$.restAPI, 'getChangeDetail').callsFake(
+ () => Promise.resolve({
+ id: '123456789',
+ labels: {},
+ current_revision: 'foo',
+ revisions: {foo: {commit: {}}},
+ }));
+ sinon.stub(element, '_getEdit').callsFake(() => Promise.resolve({
base_patch_set_number: 1,
commit: {commit: 'bar'},
}));
@@ -1483,7 +1572,7 @@
test('_openReplyDialog called with `ANY` when coming from tap event',
() => {
- const openStub = sandbox.stub(element, '_openReplyDialog');
+ const openStub = sinon.stub(element, '_openReplyDialog');
element._serverConfig = {};
MockInteractions.tap(element.$.replyBtn);
assert(openStub.lastCall.calledWithExactly(
@@ -1495,7 +1584,7 @@
test('_openReplyDialog called with `BODY` when coming from message reply' +
'event', done => {
flush(() => {
- const openStub = sandbox.stub(element, '_openReplyDialog');
+ const openStub = sinon.stub(element, '_openReplyDialog');
element.messagesList.dispatchEvent(
new CustomEvent('reply', {
detail:
@@ -1512,7 +1601,7 @@
test('reply dialog focus can be controlled', () => {
const FocusTarget = element.$.replyDialog.FocusTarget;
- const openStub = sandbox.stub(element, '_openReplyDialog');
+ const openStub = sinon.stub(element, '_openReplyDialog');
const e = {detail: {}};
element._handleShowReplyDialog(e);
@@ -1528,7 +1617,7 @@
});
test('getUrlParameter functionality', () => {
- const locationStub = sandbox.stub(element, '_getLocationSearch');
+ const locationStub = sinon.stub(element, '_getLocationSearch');
locationStub.returns('?test');
assert.equal(element._getUrlParameter('test'), 'test');
@@ -1543,8 +1632,10 @@
});
test('revert dialog opened with revert param', done => {
- sandbox.stub(element.$.restAPI, 'getLoggedIn', () => Promise.resolve(true));
- sandbox.stub(pluginLoader, 'awaitPluginsLoaded', () => Promise.resolve());
+ sinon.stub(element.$.restAPI, 'getLoggedIn')
+ .callsFake(() => Promise.resolve(true));
+ sinon.stub(pluginLoader, 'awaitPluginsLoaded')
+ .callsFake(() => Promise.resolve());
element._patchRange = {
basePatchNum: 'PARENT',
@@ -1562,13 +1653,13 @@
actions: {},
};
- sandbox.stub(element, '_getUrlParameter',
+ sinon.stub(element, '_getUrlParameter').callsFake(
param => {
assert.equal(param, 'revert');
return param;
});
- sandbox.stub(element.$.actions, 'showRevertDialog',
+ sinon.stub(element.$.actions, 'showRevertDialog').callsFake(
done);
element._maybeShowRevertDialog();
@@ -1578,7 +1669,7 @@
suite('scroll related tests', () => {
test('document scrolling calls function to set scroll height', done => {
const originalHeight = document.body.scrollHeight;
- const scrollStub = sandbox.stub(element, '_handleScroll',
+ const scrollStub = sinon.stub(element, '_handleScroll').callsFake(
() => {
assert.isTrue(scrollStub.called);
document.body.style.height = originalHeight + 'px';
@@ -1592,7 +1683,7 @@
test('scrollTop is set correctly', () => {
element.viewState = {scrollTop: TEST_SCROLL_TOP_PX};
- sandbox.stub(element, '_reload', () => {
+ sinon.stub(element, '_reload').callsFake(() => {
// When element is reloaded, ensure that the history
// state has the scrollTop set earlier. This will then
// be reset.
@@ -1613,8 +1704,8 @@
suite('reply dialog tests', () => {
setup(() => {
- sandbox.stub(element.$.replyDialog, '_draftChanged');
- sandbox.stub(element.$.replyDialog, 'fetchChangeUpdates',
+ sinon.stub(element.$.replyDialog, '_draftChanged');
+ sinon.stub(element.$.replyDialog, 'fetchChangeUpdates').callsFake(
() => Promise.resolve({isLatest: true}));
element._change = {labels: {}};
});
@@ -1647,7 +1738,7 @@
const div = document.createElement('div');
element.$.replyDialog.draft = '> quote text\n\n some draft text';
element.$.replyDialog.quote = '> quote text\n\n';
- const e = {target: div, preventDefault: sandbox.spy()};
+ const e = {target: div, preventDefault: sinon.spy()};
element._handleReplyTap(e);
assert.equal(element.$.replyDialog.draft,
'> quote text\n\n some draft text');
@@ -1663,7 +1754,7 @@
suite('commit message expand/collapse', () => {
setup(() => {
- sandbox.stub(element, 'fetchChangeUpdates',
+ sinon.stub(element, 'fetchChangeUpdates').callsFake(
() => Promise.resolve({isLatest: false}));
});
@@ -1694,17 +1785,18 @@
suite('related changes expand/collapse', () => {
let updateHeightSpy;
setup(() => {
- updateHeightSpy = sandbox.spy(element, '_updateRelatedChangeMaxHeight');
+ updateHeightSpy = sinon.spy(element, '_updateRelatedChangeMaxHeight');
});
test('relatedChangesToggle shown height greater than changeInfo height',
() => {
assert.isFalse(element.$.relatedChangesToggle.classList
.contains('showToggle'));
- sandbox.stub(element, '_getOffsetHeight', () => 50);
- sandbox.stub(element, '_getScrollHeight', () => 60);
- sandbox.stub(element, '_getLineHeight', () => 5);
- sandbox.stub(window, 'matchMedia', () => { return {matches: true}; });
+ sinon.stub(element, '_getOffsetHeight').callsFake(() => 50);
+ sinon.stub(element, '_getScrollHeight').callsFake(() => 60);
+ sinon.stub(element, '_getLineHeight').callsFake(() => 5);
+ sinon.stub(window, 'matchMedia')
+ .callsFake(() => { return {matches: true}; });
element.$.relatedChanges.dispatchEvent(
new CustomEvent('new-section-loaded'));
assert.isTrue(element.$.relatedChangesToggle.classList
@@ -1716,10 +1808,11 @@
() => {
assert.isFalse(element.$.relatedChangesToggle.classList
.contains('showToggle'));
- sandbox.stub(element, '_getOffsetHeight', () => 50);
- sandbox.stub(element, '_getScrollHeight', () => 40);
- sandbox.stub(element, '_getLineHeight', () => 5);
- sandbox.stub(window, 'matchMedia', () => { return {matches: true}; });
+ sinon.stub(element, '_getOffsetHeight').callsFake(() => 50);
+ sinon.stub(element, '_getScrollHeight').callsFake(() => 40);
+ sinon.stub(element, '_getLineHeight').callsFake(() => 5);
+ sinon.stub(window, 'matchMedia')
+ .callsFake(() => { return {matches: true}; });
element.$.relatedChanges.dispatchEvent(
new CustomEvent('new-section-loaded'));
assert.isFalse(element.$.relatedChangesToggle.classList
@@ -1728,8 +1821,9 @@
});
test('relatedChangesToggle functions', () => {
- sandbox.stub(element, '_getOffsetHeight', () => 50);
- sandbox.stub(window, 'matchMedia', () => { return {matches: false}; });
+ sinon.stub(element, '_getOffsetHeight').callsFake(() => 50);
+ sinon.stub(window, 'matchMedia')
+ .callsFake(() => { return {matches: false}; });
element._relatedChangesLoading = false;
assert.isTrue(element._relatedChangesCollapsed);
assert.isTrue(
@@ -1741,9 +1835,10 @@
});
test('_updateRelatedChangeMaxHeight without commit toggle', () => {
- sandbox.stub(element, '_getOffsetHeight', () => 50);
- sandbox.stub(element, '_getLineHeight', () => 12);
- sandbox.stub(window, 'matchMedia', () => { return {matches: false}; });
+ sinon.stub(element, '_getOffsetHeight').callsFake(() => 50);
+ sinon.stub(element, '_getLineHeight').callsFake(() => 12);
+ sinon.stub(window, 'matchMedia')
+ .callsFake(() => { return {matches: false}; });
// 50 (existing height) - 30 (extra height) = 20 (adjusted height).
// 20 (max existing height) % 12 (line height) = 6 (remainder).
@@ -1758,9 +1853,10 @@
test('_updateRelatedChangeMaxHeight with commit toggle', () => {
element._latestCommitMessage = _.times(31, String).join('\n');
- sandbox.stub(element, '_getOffsetHeight', () => 50);
- sandbox.stub(element, '_getLineHeight', () => 12);
- sandbox.stub(window, 'matchMedia', () => { return {matches: false}; });
+ sinon.stub(element, '_getOffsetHeight').callsFake(() => 50);
+ sinon.stub(element, '_getLineHeight').callsFake(() => 12);
+ sinon.stub(window, 'matchMedia')
+ .callsFake(() => { return {matches: false}; });
// 50 (existing height) % 12 (line height) = 2 (remainder).
// 50 (existing height) - 2 (remainder) = 48 (max height to set).
@@ -1774,9 +1870,10 @@
test('_updateRelatedChangeMaxHeight in small screen mode', () => {
element._latestCommitMessage = _.times(31, String).join('\n');
- sandbox.stub(element, '_getOffsetHeight', () => 50);
- sandbox.stub(element, '_getLineHeight', () => 12);
- sandbox.stub(window, 'matchMedia', () => { return {matches: true}; });
+ sinon.stub(element, '_getOffsetHeight').callsFake(() => 50);
+ sinon.stub(element, '_getLineHeight').callsFake(() => 12);
+ sinon.stub(window, 'matchMedia')
+ .callsFake(() => { return {matches: true}; });
element._updateRelatedChangeMaxHeight();
@@ -1789,9 +1886,9 @@
test('_updateRelatedChangeMaxHeight in medium screen mode', () => {
element._latestCommitMessage = _.times(31, String).join('\n');
- sandbox.stub(element, '_getOffsetHeight', () => 50);
- sandbox.stub(element, '_getLineHeight', () => 12);
- sandbox.stub(window, 'matchMedia', () => {
+ sinon.stub(element, '_getOffsetHeight').callsFake(() => 50);
+ sinon.stub(element, '_getLineHeight').callsFake(() => 12);
+ sinon.stub(window, 'matchMedia').callsFake(() => {
if (window.matchMedia.lastCall.args[0] === '(max-width: 75em)') {
return {matches: true};
} else {
@@ -1808,8 +1905,8 @@
suite('update checks', () => {
setup(() => {
- sandbox.spy(element, '_startUpdateCheckTimer');
- sandbox.stub(element, 'async', f => {
+ sinon.spy(element, '_startUpdateCheckTimer');
+ sinon.stub(element, 'async').callsFake( f => {
// Only fire the async callback one time.
if (element.async.callCount > 1) { return; }
f.call(element);
@@ -1817,7 +1914,7 @@
});
test('_startUpdateCheckTimer negative delay', () => {
- sandbox.stub(element, 'fetchChangeUpdates');
+ sinon.stub(element, 'fetchChangeUpdates');
element._serverConfig = {change: {update_delay: -1}};
@@ -1826,7 +1923,7 @@
});
test('_startUpdateCheckTimer up-to-date', () => {
- sandbox.stub(element, 'fetchChangeUpdates',
+ sinon.stub(element, 'fetchChangeUpdates').callsFake(
() => Promise.resolve({isLatest: true}));
element._serverConfig = {change: {update_delay: 12345}};
@@ -1837,7 +1934,7 @@
});
test('_startUpdateCheckTimer out-of-date shows an alert', done => {
- sandbox.stub(element, 'fetchChangeUpdates',
+ sinon.stub(element, 'fetchChangeUpdates').callsFake(
() => Promise.resolve({isLatest: false}));
element.addEventListener('show-alert', e => {
assert.equal(e.detail.message,
@@ -1848,7 +1945,7 @@
});
test('_startUpdateCheckTimer new status shows an alert', done => {
- sandbox.stub(element, 'fetchChangeUpdates')
+ sinon.stub(element, 'fetchChangeUpdates')
.returns(Promise.resolve({
isLatest: true,
newStatus: ChangeStatus.MERGED,
@@ -1861,7 +1958,7 @@
});
test('_startUpdateCheckTimer new messages shows an alert', done => {
- sandbox.stub(element, 'fetchChangeUpdates')
+ sinon.stub(element, 'fetchChangeUpdates')
.returns(Promise.resolve({
isLatest: true,
newMessages: true,
@@ -1904,7 +2001,7 @@
test('_maybeScrollToMessage', done => {
flush(() => {
- const scrollStub = sandbox.stub(element.messagesList,
+ const scrollStub = sinon.stub(element.messagesList,
'scrollToMessage');
element._maybeScrollToMessage('');
@@ -1919,7 +2016,7 @@
});
test('topic update reloads related changes', () => {
- sandbox.stub(element.$.relatedChanges, 'reload');
+ sinon.stub(element.$.relatedChanges, 'reload');
element.dispatchEvent(new CustomEvent('topic-changed'));
assert.isTrue(element.$.relatedChanges.reload.calledOnce);
});
@@ -1986,11 +2083,11 @@
flushAsynchronousOperations();
const controls = element.$.fileListHeader
.shadowRoot.querySelector('#editControls');
- sandbox.stub(controls, 'openDeleteDialog');
- sandbox.stub(controls, 'openRenameDialog');
- sandbox.stub(controls, 'openRestoreDialog');
- sandbox.stub(GerritNav, 'getEditUrlForDiff');
- sandbox.stub(GerritNav, 'navigateToRelativeUrl');
+ sinon.stub(controls, 'openDeleteDialog');
+ sinon.stub(controls, 'openRenameDialog');
+ sinon.stub(controls, 'openRestoreDialog');
+ sinon.stub(GerritNav, 'getEditUrlForDiff');
+ sinon.stub(GerritNav, 'navigateToRelativeUrl');
// Delete
fileList.dispatchEvent(new CustomEvent('file-action-tap', {
@@ -2042,7 +2139,7 @@
test('_selectedRevision updates when patchNum is changed', () => {
const revision1 = {_number: 1, commit: {parents: []}};
const revision2 = {_number: 2, commit: {parents: []}};
- sandbox.stub(element.$.restAPI, 'getChangeDetail').returns(
+ sinon.stub(element.$.restAPI, 'getChangeDetail').returns(
Promise.resolve({
revisions: {
aaa: revision1,
@@ -2053,8 +2150,8 @@
current_revision: 'bbb',
change_id: 'loremipsumdolorsitamet',
}));
- sandbox.stub(element, '_getEdit').returns(Promise.resolve());
- sandbox.stub(element, '_getPreferences').returns(Promise.resolve({}));
+ sinon.stub(element, '_getEdit').returns(Promise.resolve());
+ sinon.stub(element, '_getPreferences').returns(Promise.resolve({}));
element._patchRange = {patchNum: '2'};
return element._getChangeDetail().then(() => {
assert.strictEqual(element._selectedRevision, revision2);
@@ -2068,7 +2165,7 @@
const revision1 = {_number: 1, commit: {parents: []}};
const revision2 = {_number: 2, commit: {parents: []}};
const revision3 = {_number: 'edit', commit: {parents: []}};
- sandbox.stub(element.$.restAPI, 'getChangeDetail').returns(
+ sinon.stub(element.$.restAPI, 'getChangeDetail').returns(
Promise.resolve({
revisions: {
aaa: revision1,
@@ -2080,8 +2177,8 @@
current_revision: 'ccc',
change_id: 'loremipsumdolorsitamet',
}));
- sandbox.stub(element, '_getEdit').returns(Promise.resolve());
- sandbox.stub(element, '_getPreferences').returns(Promise.resolve({}));
+ sinon.stub(element, '_getEdit').returns(Promise.resolve());
+ sinon.stub(element, '_getPreferences').returns(Promise.resolve({}));
element._patchRange = {patchNum: 'edit'};
return element._getChangeDetail().then(() => {
assert.strictEqual(element._selectedRevision, revision3);
@@ -2092,7 +2189,7 @@
element._change = {labels: {}};
element._patchRange = {patchNum: 4};
element._mergeable = true;
- const showStub = sandbox.stub(element.$.jsAPI, 'handleEvent');
+ const showStub = sinon.stub(element.$.jsAPI, 'handleEvent');
element._sendShowChangeEvent();
assert.isTrue(showStub.calledOnce);
assert.equal(
@@ -2117,7 +2214,7 @@
});
test('edit exists in revisions', done => {
- sandbox.stub(GerritNav, 'navigateToChange', (...args) => {
+ sinon.stub(GerritNav, 'navigateToChange').callsFake((...args) => {
assert.equal(args.length, 2);
assert.equal(args[1], element.EDIT_NAME); // patchNum
done();
@@ -2130,7 +2227,7 @@
});
test('no edit exists in revisions, non-latest patchset', done => {
- sandbox.stub(GerritNav, 'navigateToChange', (...args) => {
+ sinon.stub(GerritNav, 'navigateToChange').callsFake((...args) => {
assert.equal(args.length, 4);
assert.equal(args[1], 1); // patchNum
assert.equal(args[3], true); // opt_isEdit
@@ -2145,7 +2242,7 @@
});
test('no edit exists in revisions, latest patchset', done => {
- sandbox.stub(GerritNav, 'navigateToChange', (...args) => {
+ sinon.stub(GerritNav, 'navigateToChange').callsFake((...args) => {
assert.equal(args.length, 4);
// No patch should be specified when patchNum == latest.
assert.isNotOk(args[1]); // patchNum
@@ -2162,10 +2259,10 @@
});
test('_handleStopEditTap', done => {
- sandbox.stub(element.$.metadata, '_computeLabelNames');
+ sinon.stub(element.$.metadata, '_computeLabelNames');
navigateToChangeStub.restore();
- sandbox.stub(element, 'computeLatestPatchNum').returns(1);
- sandbox.stub(GerritNav, 'navigateToChange', (...args) => {
+ sinon.stub(element, 'computeLatestPatchNum').returns(1);
+ sinon.stub(GerritNav, 'navigateToChange').callsFake((...args) => {
assert.equal(args.length, 2);
assert.equal(args[1], 1); // patchNum
done();
@@ -2205,7 +2302,7 @@
setup(() => {
element._change = {labels: {}};
- getMergeableStub = sandbox.stub(element.$.restAPI, 'getMergeable')
+ getMergeableStub = sinon.stub(element.$.restAPI, 'getMergeable')
.returns(Promise.resolve({mergeable: true}));
});
@@ -2237,9 +2334,9 @@
});
test('_paramsChanged sets in projectLookup', () => {
- sandbox.stub(element.$.relatedChanges, 'reload');
- sandbox.stub(element, '_reload').returns(Promise.resolve());
- const setStub = sandbox.stub(element.$.restAPI, 'setInProjectLookup');
+ sinon.stub(element.$.relatedChanges, 'reload');
+ sinon.stub(element, '_reload').returns(Promise.resolve());
+ const setStub = sinon.stub(element.$.restAPI, 'setInProjectLookup');
element._paramsChanged({
view: GerritNav.View.CHANGE,
changeNum: 101,
@@ -2255,7 +2352,7 @@
starred: false,
};
element._loggedIn = true;
- const stub = sandbox.stub(element, '_handleToggleStar');
+ const stub = sinon.stub(element, '_handleToggleStar');
flushAsynchronousOperations();
MockInteractions.tap(element.$.changeStar.shadowRoot
@@ -2269,19 +2366,19 @@
basePatchNum: 'PARENT',
patchNum: 1,
};
- sandbox.stub(element, '_getChangeDetail').returns(Promise.resolve());
- sandbox.stub(element, '_getProjectConfig').returns(Promise.resolve());
- sandbox.stub(element, '_reloadComments').returns(Promise.resolve());
- sandbox.stub(element, '_getMergeability').returns(Promise.resolve());
- sandbox.stub(element, '_getLatestCommitMessage')
+ sinon.stub(element, '_getChangeDetail').returns(Promise.resolve());
+ sinon.stub(element, '_getProjectConfig').returns(Promise.resolve());
+ sinon.stub(element, '_reloadComments').returns(Promise.resolve());
+ sinon.stub(element, '_getMergeability').returns(Promise.resolve());
+ sinon.stub(element, '_getLatestCommitMessage')
.returns(Promise.resolve());
});
test('don\'t report changedDisplayed on reply', done => {
const changeDisplayStub =
- sandbox.stub(element.reporting, 'changeDisplayed');
+ sinon.stub(element.reporting, 'changeDisplayed');
const changeFullyLoadedStub =
- sandbox.stub(element.reporting, 'changeFullyLoaded');
+ sinon.stub(element.reporting, 'changeFullyLoaded');
element._handleReplySent();
flush(() => {
assert.isFalse(changeDisplayStub.called);
@@ -2292,9 +2389,9 @@
test('report changedDisplayed on _paramsChanged', done => {
const changeDisplayStub =
- sandbox.stub(element.reporting, 'changeDisplayed');
+ sinon.stub(element.reporting, 'changeDisplayed');
const changeFullyLoadedStub =
- sandbox.stub(element.reporting, 'changeFullyLoaded');
+ sinon.stub(element.reporting, 'changeFullyLoaded');
element._paramsChanged({
view: GerritNav.View.CHANGE,
changeNum: 101,
diff --git a/polygerrit-ui/app/elements/change/gr-comment-list/gr-comment-list.js b/polygerrit-ui/app/elements/change/gr-comment-list/gr-comment-list.js
index 576b8bd..3554dff 100644
--- a/polygerrit-ui/app/elements/change/gr-comment-list/gr-comment-list.js
+++ b/polygerrit-ui/app/elements/change/gr-comment-list/gr-comment-list.js
@@ -70,7 +70,7 @@
}
_computeDiffURL(filePath, changeNum, allComments) {
- if ([filePath, changeNum, allComments].some(arg => arg === undefined)) {
+ if ([filePath, changeNum, allComments].includes(undefined)) {
return;
}
const fileComments = this._computeCommentsForFile(allComments, filePath);
diff --git a/polygerrit-ui/app/elements/change/gr-comment-list/gr-comment-list_test.html b/polygerrit-ui/app/elements/change/gr-comment-list/gr-comment-list_test.js
similarity index 64%
rename from polygerrit-ui/app/elements/change/gr-comment-list/gr-comment-list_test.html
rename to polygerrit-ui/app/elements/change/gr-comment-list/gr-comment-list_test.js
index 075b883..704d83f 100644
--- a/polygerrit-ui/app/elements/change/gr-comment-list/gr-comment-list_test.html
+++ b/polygerrit-ui/app/elements/change/gr-comment-list/gr-comment-list_test.js
@@ -1,53 +1,35 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-comment-list</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-comment-list></gr-comment-list>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-comment-list.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
+const basicFixture = fixtureFromElement('gr-comment-list');
+
suite('gr-comment-list tests', () => {
let element;
- let sandbox;
setup(() => {
- element = fixture('basic');
- sandbox = sinon.sandbox.create();
- sandbox.stub(GerritNav, 'mapCommentlinks', x => x);
- });
+ element = basicFixture.instantiate();
- teardown(() => { sandbox.restore(); });
+ sinon.stub(GerritNav, 'mapCommentlinks').callsFake( x => x);
+ });
test('_computeFilesFromComments w/ special file path sorting', () => {
const comments = {
@@ -106,7 +88,7 @@
});
test('_computeDiffLineURL', () => {
- const getUrlStub = sandbox.stub(GerritNav, 'getUrlForDiffById');
+ const getUrlStub = sinon.stub(GerritNav, 'getUrlForDiffById');
element.projectName = 'proj';
element.changeNum = 123;
@@ -129,4 +111,4 @@
[123, 'proj', 'foo.cc', 4, -12, 456, true]);
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info.js b/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info.js
index 052189e..3ed48e7 100644
--- a/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info.js
+++ b/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info.js
@@ -59,7 +59,7 @@
_computeShowWebLink(change, commitInfo, serverConfig) {
// Polymer 2: check for undefined
- if ([change, commitInfo, serverConfig].some(arg => arg === undefined)) {
+ if ([change, commitInfo, serverConfig].includes(undefined)) {
return undefined;
}
@@ -69,7 +69,7 @@
_computeWebLink(change, commitInfo, serverConfig) {
// Polymer 2: check for undefined
- if ([change, commitInfo, serverConfig].some(arg => arg === undefined)) {
+ if ([change, commitInfo, serverConfig].includes(undefined)) {
return undefined;
}
diff --git a/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info_test.html b/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info_test.js
similarity index 65%
rename from polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info_test.html
rename to polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info_test.js
index d9664ec..c120c33 100644
--- a/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info_test.html
+++ b/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info_test.js
@@ -1,57 +1,36 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2015 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-commit-info</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-commit-info></gr-commit-info>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import '../../core/gr-router/gr-router.js';
import './gr-commit-info.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
+const basicFixture = fixtureFromElement('gr-commit-info');
+
suite('gr-commit-info tests', () => {
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- });
-
- teardown(() => {
- sandbox.restore();
+ element = basicFixture.instantiate();
});
test('weblinks use GerritNav interface', () => {
- const weblinksStub = sandbox.stub(GerritNav, '_generateWeblinks')
+ const weblinksStub = sinon.stub(GerritNav, '_generateWeblinks')
.returns([{name: 'stubb', url: '#s'}]);
element.change = {};
element.commitInfo = {};
@@ -70,7 +49,7 @@
test('use web link when available', () => {
const router = document.createElement('gr-router');
- sandbox.stub(GerritNav, '_generateWeblinks',
+ sinon.stub(GerritNav, '_generateWeblinks').callsFake(
router._generateWeblinks.bind(router));
element.change = {labels: [], project: ''};
@@ -86,7 +65,7 @@
test('does not relativize web links that begin with scheme', () => {
const router = document.createElement('gr-router');
- sandbox.stub(GerritNav, '_generateWeblinks',
+ sinon.stub(GerritNav, '_generateWeblinks').callsFake(
router._generateWeblinks.bind(router));
element.change = {labels: [], project: ''};
@@ -104,7 +83,7 @@
test('ignore web links that are neither gitweb nor gitiles', () => {
const router = document.createElement('gr-router');
- sandbox.stub(GerritNav, '_generateWeblinks',
+ sinon.stub(GerritNav, '_generateWeblinks').callsFake(
router._generateWeblinks.bind(router));
element.change = {project: 'project-name'};
@@ -136,4 +115,4 @@
element.serverConfig));
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog_test.html b/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog_test.html
deleted file mode 100644
index c1e1165..0000000
--- a/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog_test.html
+++ /dev/null
@@ -1,82 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-confirm-abandon-dialog</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-confirm-abandon-dialog></gr-confirm-abandon-dialog>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-confirm-abandon-dialog.js';
-suite('gr-confirm-abandon-dialog tests', () => {
- let element;
- let sandbox;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('_handleConfirmTap', () => {
- const confirmHandler = sandbox.stub();
- element.addEventListener('confirm', confirmHandler);
- sandbox.spy(element, '_handleConfirmTap');
- sandbox.spy(element, '_confirm');
- element.shadowRoot
- .querySelector('gr-dialog').dispatchEvent(
- new CustomEvent('confirm', {
- composed: true, bubbles: true,
- }));
- assert.isTrue(confirmHandler.called);
- assert.isTrue(confirmHandler.calledOnce);
- assert.isTrue(element._handleConfirmTap.called);
- assert.isTrue(element._confirm.called);
- assert.isTrue(element._confirm.calledOnce);
- });
-
- test('_handleCancelTap', () => {
- const cancelHandler = sandbox.stub();
- element.addEventListener('cancel', cancelHandler);
- sandbox.spy(element, '_handleCancelTap');
- element.shadowRoot
- .querySelector('gr-dialog').dispatchEvent(
- new CustomEvent('cancel', {
- composed: true, bubbles: true,
- }));
- assert.isTrue(cancelHandler.called);
- assert.isTrue(cancelHandler.calledOnce);
- assert.isTrue(element._handleCancelTap.called);
- assert.isTrue(element._handleCancelTap.calledOnce);
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog_test.js b/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog_test.js
new file mode 100644
index 0000000..14d16f5
--- /dev/null
+++ b/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog_test.js
@@ -0,0 +1,62 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-confirm-abandon-dialog.js';
+
+const basicFixture = fixtureFromElement('gr-confirm-abandon-dialog');
+
+suite('gr-confirm-abandon-dialog tests', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ test('_handleConfirmTap', () => {
+ const confirmHandler = sinon.stub();
+ element.addEventListener('confirm', confirmHandler);
+ sinon.spy(element, '_handleConfirmTap');
+ sinon.spy(element, '_confirm');
+ element.shadowRoot
+ .querySelector('gr-dialog').dispatchEvent(
+ new CustomEvent('confirm', {
+ composed: true, bubbles: true,
+ }));
+ assert.isTrue(confirmHandler.called);
+ assert.isTrue(confirmHandler.calledOnce);
+ assert.isTrue(element._handleConfirmTap.called);
+ assert.isTrue(element._confirm.called);
+ assert.isTrue(element._confirm.calledOnce);
+ });
+
+ test('_handleCancelTap', () => {
+ const cancelHandler = sinon.stub();
+ element.addEventListener('cancel', cancelHandler);
+ sinon.spy(element, '_handleCancelTap');
+ element.shadowRoot
+ .querySelector('gr-dialog').dispatchEvent(
+ new CustomEvent('cancel', {
+ composed: true, bubbles: true,
+ }));
+ assert.isTrue(cancelHandler.called);
+ assert.isTrue(cancelHandler.calledOnce);
+ assert.isTrue(element._handleCancelTap.called);
+ assert.isTrue(element._handleCancelTap.calledOnce);
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-conflict-dialog/gr-confirm-cherrypick-conflict-dialog_test.html b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-conflict-dialog/gr-confirm-cherrypick-conflict-dialog_test.html
deleted file mode 100644
index e0016f0..0000000
--- a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-conflict-dialog/gr-confirm-cherrypick-conflict-dialog_test.html
+++ /dev/null
@@ -1,78 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-confirm-cherrypick-conflict-dialog</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-confirm-cherrypick-conflict-dialog></gr-confirm-cherrypick-conflict-dialog>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-confirm-cherrypick-conflict-dialog.js';
-suite('gr-confirm-cherrypick-conflict-dialog tests', () => {
- let element;
- let sandbox;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- });
-
- teardown(() => { sandbox.restore(); });
-
- test('_handleConfirmTap', () => {
- const confirmHandler = sandbox.stub();
- element.addEventListener('confirm', confirmHandler);
- sandbox.spy(element, '_handleConfirmTap');
- element.shadowRoot
- .querySelector('gr-dialog').dispatchEvent(
- new CustomEvent('confirm', {
- composed: true, bubbles: true,
- }));
- assert.isTrue(confirmHandler.called);
- assert.isTrue(confirmHandler.calledOnce);
- assert.isTrue(element._handleConfirmTap.called);
- assert.isTrue(element._handleConfirmTap.calledOnce);
- });
-
- test('_handleCancelTap', () => {
- const cancelHandler = sandbox.stub();
- element.addEventListener('cancel', cancelHandler);
- sandbox.spy(element, '_handleCancelTap');
- element.shadowRoot
- .querySelector('gr-dialog').dispatchEvent(
- new CustomEvent('cancel', {
- composed: true, bubbles: true,
- }));
- assert.isTrue(cancelHandler.called);
- assert.isTrue(cancelHandler.calledOnce);
- assert.isTrue(element._handleCancelTap.called);
- assert.isTrue(element._handleCancelTap.calledOnce);
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-conflict-dialog/gr-confirm-cherrypick-conflict-dialog_test.js b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-conflict-dialog/gr-confirm-cherrypick-conflict-dialog_test.js
new file mode 100644
index 0000000..c98353b
--- /dev/null
+++ b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-conflict-dialog/gr-confirm-cherrypick-conflict-dialog_test.js
@@ -0,0 +1,61 @@
+/**
+ * @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.
+ */
+
+import '../../../test/common-test-setup-karma.js';
+import './gr-confirm-cherrypick-conflict-dialog.js';
+
+const basicFixture =
+ fixtureFromElement('gr-confirm-cherrypick-conflict-dialog');
+
+suite('gr-confirm-cherrypick-conflict-dialog tests', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ test('_handleConfirmTap', () => {
+ const confirmHandler = sinon.stub();
+ element.addEventListener('confirm', confirmHandler);
+ sinon.spy(element, '_handleConfirmTap');
+ element.shadowRoot
+ .querySelector('gr-dialog').dispatchEvent(
+ new CustomEvent('confirm', {
+ composed: true, bubbles: true,
+ }));
+ assert.isTrue(confirmHandler.called);
+ assert.isTrue(confirmHandler.calledOnce);
+ assert.isTrue(element._handleConfirmTap.called);
+ assert.isTrue(element._handleConfirmTap.calledOnce);
+ });
+
+ test('_handleCancelTap', () => {
+ const cancelHandler = sinon.stub();
+ element.addEventListener('cancel', cancelHandler);
+ sinon.spy(element, '_handleCancelTap');
+ element.shadowRoot
+ .querySelector('gr-dialog').dispatchEvent(
+ new CustomEvent('cancel', {
+ composed: true, bubbles: true,
+ }));
+ assert.isTrue(cancelHandler.called);
+ assert.isTrue(cancelHandler.calledOnce);
+ assert.isTrue(element._handleCancelTap.called);
+ assert.isTrue(element._handleCancelTap.calledOnce);
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.js b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.js
index d2dcbca..e6d529c 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.js
+++ b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.js
@@ -202,7 +202,7 @@
changeStatus,
commitNum,
commitMessage,
- ].some(arg => arg === undefined)) {
+ ].includes(undefined)) {
return;
}
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.html b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.js
similarity index 72%
rename from polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.html
rename to polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.js
index 000718b..900412a 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.html
+++ b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.js
@@ -1,50 +1,33 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-confirm-cherrypick-dialog</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-confirm-cherrypick-dialog></gr-confirm-cherrypick-dialog>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-confirm-cherrypick-dialog.js';
+const basicFixture = fixtureFromElement('gr-confirm-cherrypick-dialog');
+
const CHERRY_PICK_TYPES = {
SINGLE_CHANGE: 1,
TOPIC: 2,
};
suite('gr-confirm-cherrypick-dialog tests', () => {
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
stub('gr-rest-api-interface', {
getRepoBranches(input) {
if (input.startsWith('test')) {
@@ -60,12 +43,10 @@
}
},
});
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.project = 'test-project';
});
- teardown(() => { sandbox.restore(); });
-
test('with merged change', () => {
element.changeStatus = 'MERGED';
element.commitMessage = 'message\n';
@@ -132,7 +113,7 @@
test('cherry pick topic submit', done => {
element.branch = 'master';
- const executeChangeActionStub = sandbox.stub(element.$.restAPI,
+ const executeChangeActionStub = sinon.stub(element.$.restAPI,
'executeChangeAction').returns(Promise.resolve([]));
MockInteractions.tap(element.shadowRoot.
querySelector('gr-dialog').$.confirm);
@@ -156,7 +137,6 @@
});
test('submit button is blocked while cherry picks is running', done => {
- console.log(element);
const confirmButton = element.shadowRoot.querySelector('gr-dialog').$
.confirm;
assert.isFalse(confirmButton.hasAttribute('disabled'));
@@ -169,7 +149,7 @@
});
test('resetFocus', () => {
- const focusStub = sandbox.stub(element.$.branchInput, 'focus');
+ const focusStub = sinon.stub(element.$.branchInput, 'focus');
element.resetFocus();
assert.isTrue(focusStub.called);
});
@@ -182,4 +162,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog_test.html b/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog_test.html
deleted file mode 100644
index a8392aa..0000000
--- a/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog_test.html
+++ /dev/null
@@ -1,83 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-confirm-move-dialog</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-confirm-move-dialog></gr-confirm-move-dialog>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-confirm-move-dialog.js';
-suite('gr-confirm-move-dialog tests', () => {
- let element;
-
- setup(() => {
- stub('gr-rest-api-interface', {
- getRepoBranches(input) {
- if (input.startsWith('test')) {
- return Promise.resolve([
- {
- ref: 'refs/heads/test-branch',
- revision: '67ebf73496383c6777035e374d2d664009e2aa5c',
- can_delete: true,
- },
- ]);
- } else {
- return Promise.resolve({});
- }
- },
- });
- element = fixture('basic');
- element.project = 'test-project';
- });
-
- test('with updated commit message', () => {
- element.branch = 'master';
- const myNewMessage = 'updated commit message';
- element.message = myNewMessage;
- flushAsynchronousOperations();
- assert.equal(element.message, myNewMessage);
- });
-
- test('_getProjectBranchesSuggestions empty', done => {
- element._getProjectBranchesSuggestions('nonexistent').then(branches => {
- assert.equal(branches.length, 0);
- done();
- });
- });
-
- test('_getProjectBranchesSuggestions non-empty', done => {
- element._getProjectBranchesSuggestions('test-branch').then(branches => {
- assert.equal(branches.length, 1);
- assert.equal(branches[0].name, 'test-branch');
- done();
- });
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog_test.js b/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog_test.js
new file mode 100644
index 0000000..0241112
--- /dev/null
+++ b/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog_test.js
@@ -0,0 +1,69 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-confirm-move-dialog.js';
+
+const basicFixture = fixtureFromElement('gr-confirm-move-dialog');
+
+suite('gr-confirm-move-dialog tests', () => {
+ let element;
+
+ setup(() => {
+ stub('gr-rest-api-interface', {
+ getRepoBranches(input) {
+ if (input.startsWith('test')) {
+ return Promise.resolve([
+ {
+ ref: 'refs/heads/test-branch',
+ revision: '67ebf73496383c6777035e374d2d664009e2aa5c',
+ can_delete: true,
+ },
+ ]);
+ } else {
+ return Promise.resolve({});
+ }
+ },
+ });
+ element = basicFixture.instantiate();
+ element.project = 'test-project';
+ });
+
+ test('with updated commit message', () => {
+ element.branch = 'master';
+ const myNewMessage = 'updated commit message';
+ element.message = myNewMessage;
+ flushAsynchronousOperations();
+ assert.equal(element.message, myNewMessage);
+ });
+
+ test('_getProjectBranchesSuggestions empty', done => {
+ element._getProjectBranchesSuggestions('nonexistent').then(branches => {
+ assert.equal(branches.length, 0);
+ done();
+ });
+ });
+
+ test('_getProjectBranchesSuggestions non-empty', done => {
+ element._getProjectBranchesSuggestions('test-branch').then(branches => {
+ assert.equal(branches.length, 1);
+ assert.equal(branches[0].name, 'test-branch');
+ done();
+ });
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.js b/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.js
index 0a45de2..bfcc477 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.js
+++ b/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.js
@@ -160,7 +160,7 @@
*/
_updateSelectedOption(rebaseOnCurrent, hasParent) {
// Polymer 2: check for undefined
- if ([rebaseOnCurrent, hasParent].some(arg => arg === undefined)) {
+ if ([rebaseOnCurrent, hasParent].includes(undefined)) {
return;
}
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog_test.html b/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog_test.js
similarity index 77%
rename from polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog_test.html
rename to polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog_test.js
index 080a7e0..498d31c 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog_test.html
+++ b/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog_test.js
@@ -1,50 +1,30 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-confirm-rebase-dialog</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-confirm-rebase-dialog></gr-confirm-rebase-dialog>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-confirm-rebase-dialog.js';
+
+const basicFixture = fixtureFromElement('gr-confirm-rebase-dialog');
+
suite('gr-confirm-rebase-dialog tests', () => {
let element;
- let sandbox;
setup(() => {
- element = fixture('basic');
- sandbox = sinon.sandbox.create();
- });
-
- teardown(() => {
- sandbox.restore();
+ element = basicFixture.instantiate();
});
test('controls with parent and rebase on current available', () => {
@@ -138,7 +118,7 @@
},
];
- sandbox.stub(element.$.restAPI, 'getChanges').returns(Promise.resolve(
+ sinon.stub(element.$.restAPI, 'getChanges').returns(Promise.resolve(
[
{
_number: 123,
@@ -157,7 +137,7 @@
});
test('_getRecentChanges', () => {
- sandbox.spy(element, '_getRecentChanges');
+ sinon.spy(element, '_getRecentChanges');
return element._getRecentChanges()
.then(() => {
assert.deepEqual(element._recentChanges, recentChanges);
@@ -187,7 +167,7 @@
});
test('input text change triggers function', () => {
- sandbox.spy(element, '_getRecentChanges');
+ sinon.spy(element, '_getRecentChanges');
element.$.parentInput.noDebounce = true;
MockInteractions.pressAndReleaseKeyOn(
element.$.parentInput.$.input,
@@ -201,4 +181,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog_test.html b/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog_test.html
deleted file mode 100644
index 3a341c5..0000000
--- a/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog_test.html
+++ /dev/null
@@ -1,101 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-confirm-revert-dialog</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-confirm-revert-dialog></gr-confirm-revert-dialog>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-confirm-revert-dialog.js';
-suite('gr-confirm-revert-dialog tests', () => {
- let element;
- let sandbox;
-
- setup(() => {
- element = fixture('basic');
- sandbox =sinon.sandbox.create();
- });
-
- teardown(() => sandbox.restore());
-
- test('no match', () => {
- assert.isNotOk(element._message);
- const alertStub = sandbox.stub();
- element.addEventListener('show-alert', alertStub);
- element._populateRevertSingleChangeMessage({},
- 'not a commitHash in sight', undefined);
- assert.isTrue(alertStub.calledOnce);
- });
-
- test('single line', () => {
- assert.isNotOk(element._message);
- element._populateRevertSingleChangeMessage({},
- 'one line commit\n\nChange-Id: abcdefg\n',
- 'abcd123');
- const expected = 'Revert "one line commit"\n\n' +
- 'This reverts commit abcd123.\n\n' +
- 'Reason for revert: <INSERT REASONING HERE>\n';
- assert.equal(element._message, expected);
- });
-
- test('multi line', () => {
- assert.isNotOk(element._message);
- element._populateRevertSingleChangeMessage({},
- 'many lines\ncommit\n\nmessage\n\nChange-Id: abcdefg\n',
- 'abcd123');
- const expected = 'Revert "many lines"\n\n' +
- 'This reverts commit abcd123.\n\n' +
- 'Reason for revert: <INSERT REASONING HERE>\n';
- assert.equal(element._message, expected);
- });
-
- test('issue above change id', () => {
- assert.isNotOk(element._message);
- element._populateRevertSingleChangeMessage({},
- 'much lines\nvery\n\ncommit\n\nBug: Issue 42\nChange-Id: abcdefg\n',
- 'abcd123');
- const expected = 'Revert "much lines"\n\n' +
- 'This reverts commit abcd123.\n\n' +
- 'Reason for revert: <INSERT REASONING HERE>\n';
- assert.equal(element._message, expected);
- });
-
- test('revert a revert', () => {
- assert.isNotOk(element._message);
- element._populateRevertSingleChangeMessage({},
- 'Revert "one line commit"\n\nChange-Id: abcdefg\n',
- 'abcd123');
- const expected = 'Revert "Revert "one line commit""\n\n' +
- 'This reverts commit abcd123.\n\n' +
- 'Reason for revert: <INSERT REASONING HERE>\n';
- assert.equal(element._message, expected);
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog_test.js b/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog_test.js
new file mode 100644
index 0000000..7c84043
--- /dev/null
+++ b/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog_test.js
@@ -0,0 +1,83 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-confirm-revert-dialog.js';
+
+const basicFixture = fixtureFromElement('gr-confirm-revert-dialog');
+
+suite('gr-confirm-revert-dialog tests', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ test('no match', () => {
+ assert.isNotOk(element._message);
+ const alertStub = sinon.stub();
+ element.addEventListener('show-alert', alertStub);
+ element._populateRevertSingleChangeMessage({},
+ 'not a commitHash in sight', undefined);
+ assert.isTrue(alertStub.calledOnce);
+ });
+
+ test('single line', () => {
+ assert.isNotOk(element._message);
+ element._populateRevertSingleChangeMessage({},
+ 'one line commit\n\nChange-Id: abcdefg\n',
+ 'abcd123');
+ const expected = 'Revert "one line commit"\n\n' +
+ 'This reverts commit abcd123.\n\n' +
+ 'Reason for revert: <INSERT REASONING HERE>\n';
+ assert.equal(element._message, expected);
+ });
+
+ test('multi line', () => {
+ assert.isNotOk(element._message);
+ element._populateRevertSingleChangeMessage({},
+ 'many lines\ncommit\n\nmessage\n\nChange-Id: abcdefg\n',
+ 'abcd123');
+ const expected = 'Revert "many lines"\n\n' +
+ 'This reverts commit abcd123.\n\n' +
+ 'Reason for revert: <INSERT REASONING HERE>\n';
+ assert.equal(element._message, expected);
+ });
+
+ test('issue above change id', () => {
+ assert.isNotOk(element._message);
+ element._populateRevertSingleChangeMessage({},
+ 'much lines\nvery\n\ncommit\n\nBug: Issue 42\nChange-Id: abcdefg\n',
+ 'abcd123');
+ const expected = 'Revert "much lines"\n\n' +
+ 'This reverts commit abcd123.\n\n' +
+ 'Reason for revert: <INSERT REASONING HERE>\n';
+ assert.equal(element._message, expected);
+ });
+
+ test('revert a revert', () => {
+ assert.isNotOk(element._message);
+ element._populateRevertSingleChangeMessage({},
+ 'Revert "one line commit"\n\nChange-Id: abcdefg\n',
+ 'abcd123');
+ const expected = 'Revert "Revert "one line commit""\n\n' +
+ 'This reverts commit abcd123.\n\n' +
+ 'Reason for revert: <INSERT REASONING HERE>\n';
+ assert.equal(element._message, expected);
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-revert-submission-dialog/gr-confirm-revert-submission-dialog.js b/polygerrit-ui/app/elements/change/gr-confirm-revert-submission-dialog/gr-confirm-revert-submission-dialog.js
index c8e14f7..a639a61 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-revert-submission-dialog/gr-confirm-revert-submission-dialog.js
+++ b/polygerrit-ui/app/elements/change/gr-confirm-revert-submission-dialog/gr-confirm-revert-submission-dialog.js
@@ -65,6 +65,9 @@
}
_populateRevertSubmissionMessage(message, change, changes) {
+ if (change === undefined) {
+ return;
+ }
// Follow the same convention of the revert
const commitHash = change.current_revision;
if (!commitHash) {
@@ -79,12 +82,14 @@
this.changes = changes;
this.message = revertTitle + '\n\n' +
'Reason for revert: <INSERT REASONING HERE>\n';
- this.message += 'Reverted Changes:\n';
changes = changes || [];
- changes.forEach(change => {
- this.message += change.change_id.substring(0, 10) + ': ' +
- this._getTrimmedChangeSubject(change.subject) + '\n';
- });
+ if (changes.length) {
+ this.message += 'Reverted Changes:\n';
+ changes.forEach(change => {
+ this.message += change.change_id.substring(0, 10) + ': ' +
+ this._getTrimmedChangeSubject(change.subject) + '\n';
+ });
+ }
this.message = this._modifyRevertSubmissionMsg(change);
}
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-revert-submission-dialog/gr-confirm-revert-submission-dialog_test.html b/polygerrit-ui/app/elements/change/gr-confirm-revert-submission-dialog/gr-confirm-revert-submission-dialog_test.html
deleted file mode 100644
index c51d635..0000000
--- a/polygerrit-ui/app/elements/change/gr-confirm-revert-submission-dialog/gr-confirm-revert-submission-dialog_test.html
+++ /dev/null
@@ -1,99 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-confirm-revert-submission-dialog</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-confirm-revert-submission-dialog>
- </gr-confirm-revert-submission-dialog>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-confirm-revert-submission-dialog.js';
-suite('gr-confirm-revert-submission-dialog tests', () => {
- let element;
- let sandbox;
-
- setup(() => {
- element = fixture('basic');
- sandbox =sinon.sandbox.create();
- });
-
- teardown(() => sandbox.restore());
-
- test('no match', () => {
- assert.isNotOk(element.message);
- const alertStub = sandbox.stub();
- element.addEventListener('show-alert', alertStub);
- element._populateRevertSubmissionMessage(
- 'not a commitHash in sight'
- );
- assert.isTrue(alertStub.calledOnce);
- });
-
- test('single line', () => {
- assert.isNotOk(element.message);
- element._populateRevertSubmissionMessage(
- 'one line commit\n\nChange-Id: abcdefg\n',
- 'abcd123');
- const expected = 'Revert submission\n\n' +
- 'Reason for revert: <INSERT REASONING HERE>\n';
- assert.equal(element.message, expected);
- });
-
- test('multi line', () => {
- assert.isNotOk(element.message);
- element._populateRevertSubmissionMessage(
- 'many lines\ncommit\n\nmessage\n\nChange-Id: abcdefg\n',
- 'abcd123');
- const expected = 'Revert submission\n\n' +
- 'Reason for revert: <INSERT REASONING HERE>\n';
- assert.equal(element.message, expected);
- });
-
- test('issue above change id', () => {
- assert.isNotOk(element.message);
- element._populateRevertSubmissionMessage(
- 'test \nvery\n\ncommit\n\nBug: Issue 42\nChange-Id: abcdefg\n',
- 'abcd123');
- const expected = 'Revert submission\n\n' +
- 'Reason for revert: <INSERT REASONING HERE>\n';
- assert.equal(element.message, expected);
- });
-
- test('revert a revert', () => {
- assert.isNotOk(element.message);
- element._populateRevertSubmissionMessage(
- 'Revert "one line commit"\n\nChange-Id: abcdefg\n',
- 'abcd123');
- const expected = 'Revert submission\n\n' +
- 'Reason for revert: <INSERT REASONING HERE>\n';
- assert.equal(element.message, expected);
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-revert-submission-dialog/gr-confirm-revert-submission-dialog_test.js b/polygerrit-ui/app/elements/change/gr-confirm-revert-submission-dialog/gr-confirm-revert-submission-dialog_test.js
new file mode 100644
index 0000000..e2f2e9e
--- /dev/null
+++ b/polygerrit-ui/app/elements/change/gr-confirm-revert-submission-dialog/gr-confirm-revert-submission-dialog_test.js
@@ -0,0 +1,80 @@
+/**
+ * @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.
+ */
+
+import '../../../test/common-test-setup-karma.js';
+import './gr-confirm-revert-submission-dialog.js';
+
+const basicFixture = fixtureFromElement('gr-confirm-revert-submission-dialog');
+
+suite('gr-confirm-revert-submission-dialog tests', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ test('no match', () => {
+ assert.isNotOk(element.message);
+ const alertStub = sinon.stub();
+ element.addEventListener('show-alert', alertStub);
+ element._populateRevertSubmissionMessage(
+ 'not a commitHash in sight', {}
+ );
+ assert.isTrue(alertStub.calledOnce);
+ });
+
+ test('single line', () => {
+ assert.isNotOk(element.message);
+ element._populateRevertSubmissionMessage(
+ 'one line commit\n\nChange-Id: abcdefg\n',
+ {current_revision: 'abcd123', submission_id: '111'});
+ const expected = 'Revert submission 111\n\n' +
+ 'Reason for revert: <INSERT REASONING HERE>\n';
+ assert.equal(element.message, expected);
+ });
+
+ test('multi line', () => {
+ assert.isNotOk(element.message);
+ element._populateRevertSubmissionMessage(
+ 'many lines\ncommit\n\nmessage\n\nChange-Id: abcdefg\n',
+ {current_revision: 'abcd123', submission_id: '111'});
+ const expected = 'Revert submission 111\n\n' +
+ 'Reason for revert: <INSERT REASONING HERE>\n';
+ assert.equal(element.message, expected);
+ });
+
+ test('issue above change id', () => {
+ assert.isNotOk(element.message);
+ element._populateRevertSubmissionMessage(
+ 'test \nvery\n\ncommit\n\nBug: Issue 42\nChange-Id: abcdefg\n',
+ {current_revision: 'abcd123', submission_id: '111'});
+ const expected = 'Revert submission 111\n\n' +
+ 'Reason for revert: <INSERT REASONING HERE>\n';
+ assert.equal(element.message, expected);
+ });
+
+ test('revert a revert', () => {
+ assert.isNotOk(element.message);
+ element._populateRevertSubmissionMessage(
+ 'Revert "one line commit"\n\nChange-Id: abcdefg\n',
+ {current_revision: 'abcd123', submission_id: '111'});
+ const expected = 'Revert submission 111\n\n' +
+ 'Reason for revert: <INSERT REASONING HERE>\n';
+ assert.equal(element.message, expected);
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-submit-dialog/gr-confirm-submit-dialog_test.html b/polygerrit-ui/app/elements/change/gr-confirm-submit-dialog/gr-confirm-submit-dialog_test.html
deleted file mode 100644
index 30699d5..0000000
--- a/polygerrit-ui/app/elements/change/gr-confirm-submit-dialog/gr-confirm-submit-dialog_test.html
+++ /dev/null
@@ -1,100 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-confirm-submit-dialog</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<script src="/node_modules/page/page.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-confirm-submit-dialog></gr-confirm-submit-dialog>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-confirm-submit-dialog.js';
-suite('gr-file-list-header tests', () => {
- let element;
- let sandbox;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('display', () => {
- element.action = {label: 'my-label'};
- element.change = {
- subject: 'my-subject',
- revisions: {},
- };
- flushAsynchronousOperations();
- const header = element.shadowRoot
- .querySelector('.header');
- assert.equal(header.textContent.trim(), 'my-label');
-
- const message = element.shadowRoot
- .querySelector('.main p');
- assert.notEqual(message.textContent.length, 0);
- assert.notEqual(message.textContent.indexOf('my-subject'), -1);
- });
-
- test('_computeUnresolvedCommentsWarning', () => {
- const change = {unresolved_comment_count: 1};
- assert.equal(element._computeUnresolvedCommentsWarning(change),
- 'Heads Up! 1 unresolved comment.');
-
- const change2 = {unresolved_comment_count: 2};
- assert.equal(element._computeUnresolvedCommentsWarning(change2),
- 'Heads Up! 2 unresolved comments.');
- });
-
- test('_computeHasChangeEdit', () => {
- const change = {
- revisions: {
- d442ff05d6c4f2a3af0eeca1f67374b39f9dc3d8: {
- _number: 'edit',
- },
- },
- unresolved_comment_count: 0,
- };
-
- assert.equal(element._computeHasChangeEdit(change), true);
-
- const change2 = {
- revisions: {
- d442ff05d6c4f2a3af0eeca1f67374b39f9dc3d8: {
- _number: 2,
- },
- },
- };
- assert.equal(element._computeHasChangeEdit(change2), false);
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-submit-dialog/gr-confirm-submit-dialog_test.js b/polygerrit-ui/app/elements/change/gr-confirm-submit-dialog/gr-confirm-submit-dialog_test.js
new file mode 100644
index 0000000..77331f7
--- /dev/null
+++ b/polygerrit-ui/app/elements/change/gr-confirm-submit-dialog/gr-confirm-submit-dialog_test.js
@@ -0,0 +1,79 @@
+/**
+ * @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.
+ */
+
+import '../../../test/common-test-setup-karma.js';
+import './gr-confirm-submit-dialog.js';
+
+const basicFixture = fixtureFromElement('gr-confirm-submit-dialog');
+
+suite('gr-file-list-header tests', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ test('display', () => {
+ element.action = {label: 'my-label'};
+ element.change = {
+ subject: 'my-subject',
+ revisions: {},
+ };
+ flushAsynchronousOperations();
+ const header = element.shadowRoot
+ .querySelector('.header');
+ assert.equal(header.textContent.trim(), 'my-label');
+
+ const message = element.shadowRoot
+ .querySelector('.main p');
+ assert.notEqual(message.textContent.length, 0);
+ assert.notEqual(message.textContent.indexOf('my-subject'), -1);
+ });
+
+ test('_computeUnresolvedCommentsWarning', () => {
+ const change = {unresolved_comment_count: 1};
+ assert.equal(element._computeUnresolvedCommentsWarning(change),
+ 'Heads Up! 1 unresolved comment.');
+
+ const change2 = {unresolved_comment_count: 2};
+ assert.equal(element._computeUnresolvedCommentsWarning(change2),
+ 'Heads Up! 2 unresolved comments.');
+ });
+
+ test('_computeHasChangeEdit', () => {
+ const change = {
+ revisions: {
+ d442ff05d6c4f2a3af0eeca1f67374b39f9dc3d8: {
+ _number: 'edit',
+ },
+ },
+ unresolved_comment_count: 0,
+ };
+
+ assert.equal(element._computeHasChangeEdit(change), true);
+
+ const change2 = {
+ revisions: {
+ d442ff05d6c4f2a3af0eeca1f67374b39f9dc3d8: {
+ _number: 2,
+ },
+ },
+ };
+ assert.equal(element._computeHasChangeEdit(change2), false);
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.js b/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.js
index 6e22374..42f031e 100644
--- a/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.js
+++ b/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.js
@@ -133,7 +133,7 @@
*/
_computeDownloadLink(change, patchNum, opt_zip) {
// Polymer 2: check for undefined
- if ([change, patchNum].some(arg => arg === undefined)) {
+ if ([change, patchNum].includes(undefined)) {
return '';
}
return this.changeBaseURL(change.project, change._number, patchNum) +
@@ -149,7 +149,7 @@
*/
_computeDownloadFilename(change, patchNum, opt_zip) {
// Polymer 2: check for undefined
- if ([change, patchNum].some(arg => arg === undefined)) {
+ if ([change, patchNum].includes(undefined)) {
return '';
}
@@ -165,7 +165,7 @@
_computeHidePatchFile(change, patchNum) {
// Polymer 2: check for undefined
- if ([change, patchNum].some(arg => arg === undefined)) {
+ if ([change, patchNum].includes(undefined)) {
return false;
}
for (const rev of Object.values(change.revisions || {})) {
@@ -180,7 +180,7 @@
_computeArchiveDownloadLink(change, patchNum, format) {
// Polymer 2: check for undefined
- if ([change, patchNum, format].some(arg => arg === undefined)) {
+ if ([change, patchNum, format].includes(undefined)) {
return '';
}
return this.changeBaseURL(change.project, change._number, patchNum) +
@@ -189,7 +189,7 @@
_computeSchemes(change, patchNum) {
// Polymer 2: check for undefined
- if ([change, patchNum].some(arg => arg === undefined)) {
+ if ([change, patchNum].includes(undefined)) {
return [];
}
diff --git a/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog_test.html b/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog_test.js
similarity index 75%
rename from polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog_test.html
rename to polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog_test.js
index 46c57fe..5dd5de7 100644
--- a/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog_test.html
+++ b/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog_test.js
@@ -1,46 +1,26 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-download-dialog</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-download-dialog></gr-download-dialog>
- </template>
-</test-fixture>
-
-<test-fixture id="loggedIn">
- <template>
- <gr-download-dialog logged-in></gr-download-dialog>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-download-dialog.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+
+const basicFixture = fixtureFromElement('gr-download-dialog');
+
function getChangeObject() {
return {
current_revision: '34685798fe548b6d17d1e8e5edc43a26d055cc72',
@@ -121,12 +101,9 @@
suite('gr-download-dialog', () => {
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
-
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.patchNum = '1';
element.config = {
schemes: {
@@ -141,10 +118,6 @@
flushAsynchronousOperations();
});
- teardown(() => {
- sandbox.restore();
- });
-
test('anchors use download attribute', () => {
const anchors = Array.from(
dom(element.root).querySelectorAll('a'));
@@ -158,7 +131,7 @@
});
test('focuses on first download link if no copy links', () => {
- const focusStub = sandbox.stub(element.$.download, 'focus');
+ const focusStub = sinon.stub(element.$.download, 'focus');
element.focus();
assert.isTrue(focusStub.called);
focusStub.restore();
@@ -219,4 +192,4 @@
assert.isFalse(element._computeHidePatchFile(change2, patchNum));
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.js b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.js
index 1f9ca20..d26f733 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.js
+++ b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.js
@@ -160,7 +160,7 @@
_computeDescriptionReadOnly(loggedIn, change, account) {
// Polymer 2: check for undefined
- if ([loggedIn, change, account].some(arg => arg === undefined)) {
+ if ([loggedIn, change, account].includes(undefined)) {
return undefined;
}
@@ -169,7 +169,7 @@
_computePatchSetDescription(change, patchNum) {
// Polymer 2: check for undefined
- if ([change, patchNum].some(arg => arg === undefined)) {
+ if ([change, patchNum].includes(undefined)) {
return;
}
diff --git a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.html b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.js
similarity index 84%
rename from polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.html
rename to polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.js
index 2a5a302..d756bf3 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.html
+++ b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.js
@@ -1,67 +1,42 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-file-list-header</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<script src="/node_modules/page/page.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-file-list-header></gr-file-list-header>
- </template>
-</test-fixture>
-
-<test-fixture id="blank">
- <template>
- <div></div>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-file-list-header.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {GrFileListConstants} from '../gr-file-list-constants.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
+const basicFixture = fixtureFromElement('gr-file-list-header');
+
suite('gr-file-list-header tests', () => {
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
stub('gr-rest-api-interface', {
getConfig() { return Promise.resolve({test: 'config'}); },
getAccount() { return Promise.resolve(null); },
_fetchSharedCacheURL() { return Promise.resolve({}); },
});
- element = fixture('basic');
+ element = basicFixture.instantiate();
});
teardown(done => {
flush(() => {
- sandbox.restore();
done();
});
});
@@ -102,7 +77,7 @@
});
test('description editing', () => {
- const putDescStub = sandbox.stub(element.$.restAPI, 'setDescription')
+ const putDescStub = sinon.stub(element.$.restAPI, 'setDescription')
.returns(Promise.resolve({ok: true}));
element.changeNum = '42';
@@ -171,7 +146,7 @@
test('expandAllDiffs called when expand button clicked', () => {
element.shownFileCount = 1;
flushAsynchronousOperations();
- sandbox.stub(element, '_expandAllDiffs');
+ sinon.stub(element, '_expandAllDiffs');
MockInteractions.tap(dom(element.root).querySelector(
'#expandBtn'));
assert.isTrue(element._expandAllDiffs.called);
@@ -180,14 +155,14 @@
test('collapseAllDiffs called when expand button clicked', () => {
element.shownFileCount = 1;
flushAsynchronousOperations();
- sandbox.stub(element, '_collapseAllDiffs');
+ sinon.stub(element, '_collapseAllDiffs');
MockInteractions.tap(dom(element.root).querySelector(
'#collapseBtn'));
assert.isTrue(element._collapseAllDiffs.called);
});
test('show/hide diffs disabled for large amounts of files', done => {
- const computeSpy = sandbox.spy(element, '_fileListActionsVisible');
+ const computeSpy = sinon.spy(element, '_fileListActionsVisible');
element._files = [];
element.changeNum = '42';
element.basePatchNum = 'PARENT';
@@ -240,7 +215,7 @@
});
test('navigateToChange called when range select changes', () => {
- const navigateToChangeStub = sandbox.stub(GerritNav, 'navigateToChange');
+ const navigateToChangeStub = sinon.stub(GerritNav, 'navigateToChange');
element.change = {
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
revisions: {
@@ -283,7 +258,7 @@
test('patch specific elements', () => {
element.editMode = true;
- sandbox.stub(element, 'computeLatestPatchNum').returns('2');
+ sinon.stub(element, 'computeLatestPatchNum').returns('2');
flushAsynchronousOperations();
assert.isFalse(isVisible(element.$.diffPrefsContainer));
@@ -329,4 +304,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.js b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.js
index fbae39f..44700e9 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.js
+++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.js
@@ -516,7 +516,7 @@
* @return {string}
*/
_computeCommentsString(changeComments, patchRange, path) {
- if ([changeComments, patchRange, path].some(arg => arg === undefined)) {
+ if ([changeComments, patchRange, path].includes(undefined)) {
return '';
}
const unresolvedCount =
@@ -558,7 +558,7 @@
* @return {string}
*/
_computeDraftsString(changeComments, patchRange, path) {
- if ([changeComments, patchRange, path].some(arg => arg === undefined)) {
+ if ([changeComments, patchRange, path].includes(undefined)) {
return '';
}
const draftCount =
@@ -582,7 +582,7 @@
* @return {string}
*/
_computeDraftsStringMobile(changeComments, patchRange, path) {
- if ([changeComments, patchRange, path].some(arg => arg === undefined)) {
+ if ([changeComments, patchRange, path].includes(undefined)) {
return '';
}
const draftCount =
@@ -606,7 +606,7 @@
* @return {string}
*/
_computeCommentsStringMobile(changeComments, patchRange, path) {
- if ([changeComments, patchRange, path].some(arg => arg === undefined)) {
+ if ([changeComments, patchRange, path].includes(undefined)) {
return '';
}
const commentCount =
@@ -1068,7 +1068,7 @@
patchRange,
reviewed,
loading,
- ].some(arg => arg === undefined)) {
+ ].includes(undefined)) {
return;
}
@@ -1089,7 +1089,7 @@
_computeFilesShown(numFilesShown, files) {
// Polymer 2: check for undefined
- if ([numFilesShown, files].some(arg => arg === undefined)) {
+ if ([numFilesShown, files].includes(undefined)) {
return undefined;
}
@@ -1165,7 +1165,7 @@
_computePatchSetDescription(revisions, patchNum) {
// Polymer 2: check for undefined
- if ([revisions, patchNum].some(arg => arg === undefined)) {
+ if ([revisions, patchNum].includes(undefined)) {
return '';
}
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.html b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.js
similarity index 88%
rename from polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.html
rename to polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.js
index ad0d1cf..051e6b3 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.html
+++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.js
@@ -1,86 +1,81 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2015 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
+import '../../../test/common-test-setup-karma.js';
+import '../../diff/gr-comment-api/gr-comment-api.js';
+import {getMockDiffResponse} from '../../../test/mocks/diff-response.js';
+import './gr-file-list.js';
+import {createCommentApiMockWithTemplateElement} from '../../../test/mocks/comment-api.js';
+import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+import {GrFileListConstants} from '../gr-file-list-constants.js';
+import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
+import {runA11yAudit} from '../../../test/a11y-test-utils.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+import {TestKeyboardShortcutBinder} from '../../../test/test-utils.js';
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-file-list</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<script src="/components/web-component-tester/data/a11ySuite.js"></script>
-<script src="/node_modules/page/page.js"></script>
-
-<dom-module id="comment-api-mock">
- <template>
+const commentApiMock = createCommentApiMockWithTemplateElement(
+ 'gr-file-list-comment-api-mock', html`
<gr-file-list id="fileList"
change-comments="[[_changeComments]]"
on-reload-drafts="_reloadDraftsWithCallback"></gr-file-list>
<gr-comment-api id="commentAPI"></gr-comment-api>
- </template>
- </dom-module>
+`);
-<test-fixture id="basic">
- <template>
- <comment-api-mock></comment-api-mock>
- </template>
-</test-fixture>
+const basicFixture = fixtureFromElement(commentApiMock.is);
-<script type="module">
-import '../../../test/common-test-setup.js';
-import '../../diff/gr-comment-api/gr-comment-api.js';
-import {getMockDiffResponse} from '../../../test/mocks/diff-response.js';
-import './gr-file-list.js';
-import '../../../test/mocks/comment-api.js';
-import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
-import {KeyboardShortcutBinder} from '../../../behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.js';
-import {GrFileListConstants} from '../gr-file-list-constants.js';
-import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
+suite('gr-diff a11y test', () => {
+ test('audit', async () => {
+ await runA11yAudit(basicFixture);
+ });
+});
suite('gr-file-list tests', () => {
- const kb = KeyboardShortcutBinder;
- kb.bindShortcut(kb.Shortcut.LEFT_PANE, 'shift+left');
- kb.bindShortcut(kb.Shortcut.RIGHT_PANE, 'shift+right');
- kb.bindShortcut(kb.Shortcut.TOGGLE_INLINE_DIFF, 'i:keyup');
- kb.bindShortcut(kb.Shortcut.TOGGLE_ALL_INLINE_DIFFS, 'shift+i:keyup');
- kb.bindShortcut(kb.Shortcut.CURSOR_NEXT_FILE, 'j', 'down');
- kb.bindShortcut(kb.Shortcut.CURSOR_PREV_FILE, 'k', 'up');
- kb.bindShortcut(kb.Shortcut.NEXT_LINE, 'j', 'down');
- kb.bindShortcut(kb.Shortcut.PREV_LINE, 'k', 'up');
- kb.bindShortcut(kb.Shortcut.NEW_COMMENT, 'c');
- kb.bindShortcut(kb.Shortcut.OPEN_LAST_FILE, '[');
- kb.bindShortcut(kb.Shortcut.OPEN_FIRST_FILE, ']');
- kb.bindShortcut(kb.Shortcut.OPEN_FILE, 'o');
- kb.bindShortcut(kb.Shortcut.NEXT_CHUNK, 'n');
- kb.bindShortcut(kb.Shortcut.PREV_CHUNK, 'p');
- kb.bindShortcut(kb.Shortcut.TOGGLE_FILE_REVIEWED, 'r');
- kb.bindShortcut(kb.Shortcut.TOGGLE_LEFT_PANE, 'shift+a');
-
let element;
let commentApiWrapper;
- let sandbox;
+
let saveStub;
let loadCommentSpy;
+ suiteSetup(() => {
+ const kb = TestKeyboardShortcutBinder.push();
+ kb.bindShortcut(kb.Shortcut.LEFT_PANE, 'shift+left');
+ kb.bindShortcut(kb.Shortcut.RIGHT_PANE, 'shift+right');
+ kb.bindShortcut(kb.Shortcut.TOGGLE_INLINE_DIFF, 'i:keyup');
+ kb.bindShortcut(kb.Shortcut.TOGGLE_ALL_INLINE_DIFFS, 'shift+i:keyup');
+ kb.bindShortcut(kb.Shortcut.CURSOR_NEXT_FILE, 'j', 'down');
+ kb.bindShortcut(kb.Shortcut.CURSOR_PREV_FILE, 'k', 'up');
+ kb.bindShortcut(kb.Shortcut.NEXT_LINE, 'j', 'down');
+ kb.bindShortcut(kb.Shortcut.PREV_LINE, 'k', 'up');
+ kb.bindShortcut(kb.Shortcut.NEW_COMMENT, 'c');
+ kb.bindShortcut(kb.Shortcut.OPEN_LAST_FILE, '[');
+ kb.bindShortcut(kb.Shortcut.OPEN_FIRST_FILE, ']');
+ kb.bindShortcut(kb.Shortcut.OPEN_FILE, 'o');
+ kb.bindShortcut(kb.Shortcut.NEXT_CHUNK, 'n');
+ kb.bindShortcut(kb.Shortcut.PREV_CHUNK, 'p');
+ kb.bindShortcut(kb.Shortcut.TOGGLE_FILE_REVIEWED, 'r');
+ kb.bindShortcut(kb.Shortcut.TOGGLE_LEFT_PANE, 'shift+a');
+ });
+
+ suiteTeardown(() => {
+ TestKeyboardShortcutBinder.pop();
+ });
+
suite('basic tests', () => {
setup(done => {
- sandbox = sinon.sandbox.create();
stub('gr-rest-api-interface', {
getLoggedIn() { return Promise.resolve(true); },
getPreferences() { return Promise.resolve({}); },
@@ -100,15 +95,15 @@
// Element must be wrapped in an element with direct access to the
// comment API.
- commentApiWrapper = fixture('basic');
+ commentApiWrapper = basicFixture.instantiate();
element = commentApiWrapper.$.fileList;
- loadCommentSpy = sandbox.spy(commentApiWrapper.$.commentAPI, 'loadAll');
+ loadCommentSpy = sinon.spy(commentApiWrapper.$.commentAPI, 'loadAll');
// Stub methods on the changeComments object after changeComments has
// been initialized.
commentApiWrapper.loadComments().then(() => {
- sandbox.stub(element.changeComments, 'getPaths').returns({});
- sandbox.stub(element.changeComments, 'getCommentsBySideForPath')
+ sinon.stub(element.changeComments, 'getPaths').returns({});
+ sinon.stub(element.changeComments, 'getCommentsBySideForPath')
.returns({meta: {}, left: [], right: []});
done();
});
@@ -119,19 +114,15 @@
basePatchNum: 'PARENT',
patchNum: '2',
};
- saveStub = sandbox.stub(element, '_saveReviewedState',
+ saveStub = sinon.stub(element, '_saveReviewedState').callsFake(
() => Promise.resolve());
});
- teardown(() => {
- sandbox.restore();
- });
-
test('correct number of files are shown', () => {
element.fileListIncrement = 300;
- element._filesByPath = _.range(500)
- .reduce((_filesByPath, i) => {
- _filesByPath['/file' + i] = {lines_inserted: 9};
+ element._filesByPath = Array(500).fill(0)
+ .reduce((_filesByPath, _, idx) => {
+ _filesByPath['/file' + idx] = {lines_inserted: 9};
return _filesByPath;
}, {});
@@ -156,10 +147,10 @@
});
test('rendering each row calls the _reportRenderedRow method', () => {
- const renderedStub = sandbox.stub(element, '_reportRenderedRow');
- element._filesByPath = _.range(10)
- .reduce((_filesByPath, i) => {
- _filesByPath['/file' + i] = {lines_inserted: 9};
+ const renderedStub = sinon.stub(element, '_reportRenderedRow');
+ element._filesByPath = Array(10).fill(0)
+ .reduce((_filesByPath, _, idx) => {
+ _filesByPath['/file' + idx] = {lines_inserted: 9};
return _filesByPath;
}, {});
flushAsynchronousOperations();
@@ -606,14 +597,11 @@
});
test('toggle left diff via shortcut', () => {
- const toggleLeftDiffStub = sandbox.stub();
+ const toggleLeftDiffStub = sinon.stub();
// Property getter cannot be stubbed w/ sandbox due to a bug in Sinon.
// https://github.com/sinonjs/sinon/issues/781
- const diffsStub = sinon.stub(element, 'diffs', {
- get() {
- return [{toggleLeftDiff: toggleLeftDiffStub}];
- },
- });
+ const diffsStub = sinon.stub(element, 'diffs')
+ .get(() => [{toggleLeftDiff: toggleLeftDiffStub}]);
MockInteractions.pressAndReleaseKeyOn(element, 65, 'shift', 'a');
assert.isTrue(toggleLeftDiffStub.calledOnce);
diffsStub.restore();
@@ -641,7 +629,7 @@
assert.equal(element.selectedIndex, 1);
MockInteractions.pressAndReleaseKeyOn(element, 74, null, 'j');
- const navStub = sandbox.stub(GerritNav, 'navigateToDiff');
+ const navStub = sinon.stub(GerritNav, 'navigateToDiff');
assert.equal(element.$.fileCursor.index, 2);
assert.equal(element.selectedIndex, 2);
@@ -668,7 +656,7 @@
assert.equal(element.$.fileCursor.index, 0);
assert.equal(element.selectedIndex, 0);
- const createCommentInPlaceStub = sandbox.stub(element.$.diffCursor,
+ const createCommentInPlaceStub = sinon.stub(element.$.diffCursor,
'createCommentInPlace');
MockInteractions.pressAndReleaseKeyOn(element, 67, null, 'c');
assert.isTrue(createCommentInPlaceStub.called);
@@ -676,7 +664,7 @@
test('i key shows/hides selected inline diff', () => {
const paths = Object.keys(element._filesByPath);
- sandbox.stub(element, '_expandedFilesChanged');
+ sinon.stub(element, '_expandedFilesChanged');
flushAsynchronousOperations();
const files = dom(element.root).querySelectorAll('.file-row');
element.$.fileCursor.stops = files;
@@ -744,12 +732,12 @@
let interact;
setup(() => {
- sandbox.stub(element, 'shouldSuppressKeyboardShortcut')
+ sinon.stub(element, 'shouldSuppressKeyboardShortcut')
.returns(false);
- sandbox.stub(element, 'modifierPressed').returns(false);
- const openCursorStub = sandbox.stub(element, '_openCursorFile');
- const openSelectedStub = sandbox.stub(element, '_openSelectedFile');
- const expandStub = sandbox.stub(element, '_toggleFileExpanded');
+ sinon.stub(element, 'modifierPressed').returns(false);
+ const openCursorStub = sinon.stub(element, '_openCursorFile');
+ const openSelectedStub = sinon.stub(element, '_openSelectedFile');
+ const expandStub = sinon.stub(element, '_toggleFileExpanded');
interact = function(opt_payload) {
openCursorStub.reset();
@@ -793,11 +781,12 @@
});
test('shift+left/shift+right', () => {
- const moveLeftStub = sandbox.stub(element.$.diffCursor, 'moveLeft');
- const moveRightStub = sandbox.stub(element.$.diffCursor, 'moveRight');
+ const moveLeftStub = sinon.stub(element.$.diffCursor, 'moveLeft');
+ const moveRightStub = sinon.stub(element.$.diffCursor, 'moveRight');
let noDiffsExpanded = true;
- sandbox.stub(element, '_noDiffsExpanded', () => noDiffsExpanded);
+ sinon.stub(element, '_noDiffsExpanded')
+ .callsFake(() => noDiffsExpanded);
MockInteractions.pressAndReleaseKeyOn(element, 73, 'shift', 'left');
assert.isFalse(moveLeftStub.called);
@@ -837,8 +826,8 @@
patchNum: '2',
};
element.$.fileCursor.setCursorAtIndex(0);
- const reviewSpy = sandbox.spy(element, '_reviewFile');
- const toggleExpandSpy = sandbox.spy(element, '_toggleFileExpanded');
+ const reviewSpy = sinon.spy(element, '_reviewFile');
+ const toggleExpandSpy = sinon.spy(element, '_toggleFileExpanded');
flushAsynchronousOperations();
const fileRows =
@@ -857,7 +846,7 @@
assert.isTrue(commitReviewLabel.classList.contains('isReviewed'));
assert.equal(markReviewLabel.textContent, 'MARK UNREVIEWED');
- const clickSpy = sandbox.spy(element, '_reviewedClick');
+ const clickSpy = sinon.spy(element, '_reviewedClick');
MockInteractions.tap(markReviewLabel);
// assert.isTrue(saveStub.lastCall.calledWithExactly('/COMMIT_MSG', false));
// assert.isFalse(commitReviewLabel.classList.contains('isReviewed'));
@@ -892,9 +881,9 @@
patchNum: '2',
};
- const clickSpy = sandbox.spy(element, '_handleFileListClick');
- const reviewStub = sandbox.stub(element, '_reviewFile');
- const toggleExpandSpy = sandbox.spy(element, '_toggleFileExpanded');
+ const clickSpy = sinon.spy(element, '_handleFileListClick');
+ const reviewStub = sinon.stub(element, '_reviewFile');
+ const toggleExpandSpy = sinon.spy(element, '_toggleFileExpanded');
const row = dom(element.root)
.querySelector(`.row[data-file='{"path":"f1.txt"}']`);
@@ -928,8 +917,8 @@
};
element.editMode = true;
flushAsynchronousOperations();
- const clickSpy = sandbox.spy(element, '_handleFileListClick');
- const toggleExpandSpy = sandbox.spy(element, '_toggleFileExpanded');
+ const clickSpy = sinon.spy(element, '_handleFileListClick');
+ const toggleExpandSpy = sinon.spy(element, '_toggleFileExpanded');
// Tap the edit controls. Should be ignored by _handleFileListClick.
MockInteractions.tap(element.shadowRoot
@@ -969,7 +958,7 @@
patchNum: '2',
};
element.$.fileCursor.setCursorAtIndex(0);
- sandbox.stub(element, '_expandedFilesChanged');
+ sinon.stub(element, '_expandedFilesChanged');
flushAsynchronousOperations();
const fileRows =
dom(element.root).querySelectorAll('.row:not(.header-row)');
@@ -995,7 +984,7 @@
basePatchNum: 'PARENT',
patchNum: '2',
};
- sandbox.spy(element, '_updateDiffPreferences');
+ sinon.spy(element, '_updateDiffPreferences');
element.$.fileCursor.setCursorAtIndex(0);
flushAsynchronousOperations();
@@ -1029,14 +1018,14 @@
basePatchNum: 'PARENT',
patchNum: '2',
};
- sandbox.stub(element, '_expandedFilesChanged');
+ sinon.stub(element, '_expandedFilesChanged');
flushAsynchronousOperations();
const commitMsgFile = dom(element.root)
.querySelectorAll('.row:not(.header-row) a.pathLink')[0];
// Remove href attribute so the app doesn't route to a diff view
commitMsgFile.removeAttribute('href');
- const togglePathSpy = sandbox.spy(element, '_toggleFileExpanded');
+ const togglePathSpy = sinon.spy(element, '_toggleFileExpanded');
MockInteractions.tap(commitMsgFile);
flushAsynchronousOperations();
@@ -1051,8 +1040,8 @@
test('_toggleFileExpanded', () => {
const path = 'path/to/my/file.txt';
element._filesByPath = {[path]: {}};
- const renderSpy = sandbox.spy(element, '_renderInOrder');
- const collapseStub = sandbox.stub(element, '_clearCollapsedDiffs');
+ const renderSpy = sinon.spy(element, '_renderInOrder');
+ const collapseStub = sinon.stub(element, '_clearCollapsedDiffs');
assert.equal(element.shadowRoot
.querySelector('iron-icon').icon, 'gr-icons:expand-more');
@@ -1076,10 +1065,10 @@
});
test('expandAllDiffs and collapseAllDiffs', () => {
- const collapseStub = sandbox.stub(element, '_clearCollapsedDiffs');
- const cursorUpdateStub = sandbox.stub(element.$.diffCursor,
+ const collapseStub = sinon.stub(element, '_clearCollapsedDiffs');
+ const cursorUpdateStub = sinon.stub(element.$.diffCursor,
'handleDiffUpdate');
- const reInitStub = sandbox.stub(element.$.diffCursor,
+ const reInitStub = sinon.stub(element.$.diffCursor,
'reInitAndUpdateStops');
const path = 'path/to/my/file.txt';
@@ -1099,7 +1088,7 @@
});
test('_expandedFilesChanged', done => {
- sandbox.stub(element, '_reviewFile');
+ sinon.stub(element, '_reviewFile');
const path = 'path/to/my/file.txt';
const diffs = [{
path,
@@ -1117,9 +1106,7 @@
}
},
}];
- sinon.stub(element, 'diffs', {
- get() { return diffs; },
- });
+ sinon.stub(element, 'diffs').get(() => diffs);
element.push('_expandedFiles', {path});
});
@@ -1160,7 +1147,7 @@
});
test('_renderInOrder', done => {
- const reviewStub = sandbox.stub(element, '_reviewFile');
+ const reviewStub = sinon.stub(element, '_reviewFile');
let callCount = 0;
const diffs = [{
path: 'p0',
@@ -1199,7 +1186,7 @@
test('_renderInOrder logged in', done => {
element._loggedIn = true;
- const reviewStub = sandbox.stub(element, '_reviewFile');
+ const reviewStub = sinon.stub(element, '_reviewFile');
let callCount = 0;
const diffs = [{
path: 'p0',
@@ -1241,7 +1228,7 @@
test('_renderInOrder respects diffPrefs.manual_review', () => {
element._loggedIn = true;
element.diffPrefs = {manual_review: true};
- const reviewStub = sandbox.stub(element, '_reviewFile');
+ const reviewStub = sinon.stub(element, '_reviewFile');
const diffs = [{
path: 'p',
style: {},
@@ -1260,7 +1247,7 @@
});
test('_loadingChanged fired from reload in debouncer', done => {
- sandbox.stub(element, '_getReviewedFiles').returns(Promise.resolve([]));
+ sinon.stub(element, '_getReviewedFiles').returns(Promise.resolve([]));
element.changeNum = 123;
element.patchRange = {patchNum: 12};
element._filesByPath = {'foo.bar': {}};
@@ -1278,7 +1265,7 @@
});
test('_loadingChanged does not set class when there are no files', () => {
- sandbox.stub(element, '_getReviewedFiles').returns(Promise.resolve([]));
+ sinon.stub(element, '_getReviewedFiles').returns(Promise.resolve([]));
element.changeNum = 123;
element.patchRange = {patchNum: 12};
element.reload();
@@ -1290,7 +1277,7 @@
suite('diff url file list', () => {
test('diff url', () => {
- const diffStub = sandbox.stub(GerritNav, 'getUrlForDiff')
+ const diffStub = sinon.stub(GerritNav, 'getUrlForDiff')
.returns('/c/gerrit/+/1/1/index.php');
const change = {
_number: 1,
@@ -1307,7 +1294,7 @@
});
test('diff url commit msg', () => {
- const diffStub = sandbox.stub(GerritNav, 'getUrlForDiff')
+ const diffStub = sinon.stub(GerritNav, 'getUrlForDiff')
.returns('/c/gerrit/+/1/1//COMMIT_MSG');
const change = {
_number: 1,
@@ -1324,7 +1311,7 @@
});
test('edit url', () => {
- const editStub = sandbox.stub(GerritNav, 'getEditUrlForDiff')
+ const editStub = sinon.stub(GerritNav, 'getEditUrlForDiff')
.returns('/c/gerrit/+/1/edit/index.php,edit');
const change = {
_number: 1,
@@ -1341,7 +1328,7 @@
});
test('edit url commit msg', () => {
- const editStub = sandbox.stub(GerritNav, 'getEditUrlForDiff')
+ const editStub = sinon.stub(GerritNav, 'getEditUrlForDiff')
.returns('/c/gerrit/+/1/edit//COMMIT_MSG,edit');
const change = {
_number: 1,
@@ -1486,7 +1473,6 @@
suite('gr-file-list inline diff tests', () => {
let element;
- let sandbox;
const commitMsgComments = [
{
@@ -1562,7 +1548,6 @@
};
setup(done => {
- sandbox = sinon.sandbox.create();
stub('gr-rest-api-interface', {
getLoggedIn() { return Promise.resolve(true); },
getPreferences() { return Promise.resolve({}); },
@@ -1580,17 +1565,17 @@
// Element must be wrapped in an element with direct access to the
// comment API.
- commentApiWrapper = fixture('basic');
+ commentApiWrapper = basicFixture.instantiate();
element = commentApiWrapper.$.fileList;
- loadCommentSpy = sandbox.spy(commentApiWrapper.$.commentAPI, 'loadAll');
+ loadCommentSpy = sinon.spy(commentApiWrapper.$.commentAPI, 'loadAll');
element.diffPrefs = {};
- sandbox.stub(element, '_reviewFile');
+ sinon.stub(element, '_reviewFile');
// Stub methods on the changeComments object after changeComments has
// been initialized.
commentApiWrapper.loadComments().then(() => {
- sandbox.stub(element.changeComments, 'getPaths').returns({});
- sandbox.stub(element.changeComments, 'getCommentsBySideForPath')
+ sinon.stub(element.changeComments, 'getPaths').returns({});
+ sinon.stub(element.changeComments, 'getCommentsBySideForPath')
.returns({meta: {}, left: [], right: []});
done();
});
@@ -1619,14 +1604,10 @@
basePatchNum: 'PARENT',
patchNum: '2',
};
- sandbox.stub(window, 'fetch', () => Promise.resolve());
+ sinon.stub(window, 'fetch').callsFake(() => Promise.resolve());
flushAsynchronousOperations();
});
- teardown(() => {
- sandbox.restore();
- });
-
test('cursor with individually opened files', () => {
MockInteractions.keyUpOn(element, 73, null, 'i');
flushAsynchronousOperations();
@@ -1705,11 +1686,11 @@
let fileRows;
setup(() => {
- sandbox.stub(element, '_renderInOrder').returns(Promise.resolve());
- nKeySpy = sandbox.spy(element, '_handleNextChunk');
- nextCommentStub = sandbox.stub(element.$.diffCursor,
+ sinon.stub(element, '_renderInOrder').returns(Promise.resolve());
+ nKeySpy = sinon.spy(element, '_handleNextChunk');
+ nextCommentStub = sinon.stub(element.$.diffCursor,
'moveToNextCommentThread');
- nextChunkStub = sandbox.stub(element.$.diffCursor,
+ nextChunkStub = sinon.stub(element.$.diffCursor,
'moveToNextChunk');
fileRows =
dom(element.root).querySelectorAll('.row:not(.header-row)');
@@ -1773,7 +1754,7 @@
test('_openSelectedFile behavior', () => {
const _filesByPath = element._filesByPath;
element.set('_filesByPath', {});
- const navStub = sandbox.stub(GerritNav, 'navigateToDiff');
+ const navStub = sinon.stub(GerritNav, 'navigateToDiff');
// Noop when there are no files.
element._openSelectedFile();
assert.isFalse(navStub.called);
@@ -1786,8 +1767,10 @@
});
test('_displayLine', () => {
- sandbox.stub(element, 'shouldSuppressKeyboardShortcut', () => false);
- sandbox.stub(element, 'modifierPressed', () => false);
+ sinon.stub(element, 'shouldSuppressKeyboardShortcut')
+ .callsFake(() => false);
+ sinon.stub(element, 'modifierPressed')
+ .callsFake(() => false);
element._showInlineDiffs = true;
const mockEvent = {preventDefault() {}};
@@ -1807,7 +1790,7 @@
suite('editMode behavior', () => {
test('reviewed checkbox', () => {
element._reviewFile.restore();
- const saveReviewStub = sandbox.stub(element, '_saveReviewedState');
+ const saveReviewStub = sinon.stub(element, '_saveReviewedState');
element.editMode = false;
MockInteractions.pressAndReleaseKeyOn(element, 82, null, 'r');
@@ -1821,7 +1804,7 @@
});
test('_getReviewedFiles does not call API', () => {
- const apiSpy = sandbox.spy(element.$.restAPI, 'getReviewedFiles');
+ const apiSpy = sinon.spy(element.$.restAPI, 'getReviewedFiles');
element.editMode = true;
return element._getReviewedFiles().then(files => {
assert.equal(files.length, 0);
@@ -1871,7 +1854,7 @@
assert.equal(thread2.comments[0].line, 20);
const commentStub =
- sandbox.stub(element.changeComments, 'getCommentsForThread');
+ sinon.stub(element.changeComments, 'getCommentsForThread');
const commentStubRes1 = [
{
patch_set: 2,
@@ -1930,7 +1913,7 @@
assert.equal(thread2.comments.length, 3);
const commentStubCount = commentStub.callCount;
- const getThreadsSpy = sandbox.spy(diffs[0], 'getThreadEls');
+ const getThreadsSpy = sinon.spy(diffs[0], 'getThreadEls');
// Should not be getting threads when the file is not expanded.
element.reloadCommentsForThreadWithRootId('ecf0b9fa_fe1a5f62',
@@ -1947,6 +1930,5 @@
assert.equal(commentStubCount, commentStub.callCount);
});
});
- a11ySuite('basic');
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog_test.html b/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog_test.html
deleted file mode 100644
index 5d5b1fc..0000000
--- a/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog_test.html
+++ /dev/null
@@ -1,100 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-included-in-dialog</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-included-in-dialog></gr-included-in-dialog>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-included-in-dialog.js';
-suite('gr-included-in-dialog', () => {
- let element;
- let sandbox;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- });
-
- teardown(() => { sandbox.restore(); });
-
- test('_computeGroups', () => {
- const includedIn = {branches: [], tags: []};
- let filterText = '';
- assert.deepEqual(element._computeGroups(includedIn, filterText), []);
-
- includedIn.branches.push('master', 'development', 'stable-2.0');
- includedIn.tags.push('v1.9', 'v2.0', 'v2.1');
- assert.deepEqual(element._computeGroups(includedIn, filterText), [
- {title: 'Branches', items: ['master', 'development', 'stable-2.0']},
- {title: 'Tags', items: ['v1.9', 'v2.0', 'v2.1']},
- ]);
-
- includedIn.external = {};
- assert.deepEqual(element._computeGroups(includedIn, filterText), [
- {title: 'Branches', items: ['master', 'development', 'stable-2.0']},
- {title: 'Tags', items: ['v1.9', 'v2.0', 'v2.1']},
- ]);
-
- includedIn.external.foo = ['abc', 'def', 'ghi'];
- assert.deepEqual(element._computeGroups(includedIn, filterText), [
- {title: 'Branches', items: ['master', 'development', 'stable-2.0']},
- {title: 'Tags', items: ['v1.9', 'v2.0', 'v2.1']},
- {title: 'foo', items: ['abc', 'def', 'ghi']},
- ]);
-
- filterText = 'v2';
- assert.deepEqual(element._computeGroups(includedIn, filterText), [
- {title: 'Tags', items: ['v2.0', 'v2.1']},
- ]);
-
- // Filtering is case-insensitive.
- filterText = 'V2';
- assert.deepEqual(element._computeGroups(includedIn, filterText), [
- {title: 'Tags', items: ['v2.0', 'v2.1']},
- ]);
- });
-
- test('_computeGroups with .bindValue', done => {
- element.$.filterInput.bindValue = 'stable-3.2';
- const includedIn = {branches: [], tags: []};
- includedIn.branches.push('master', 'stable-3.2');
-
- setTimeout(() => {
- const filterText = element._filterText;
- assert.deepEqual(element._computeGroups(includedIn, filterText), [
- {title: 'Branches', items: ['stable-3.2']},
- ]);
-
- done();
- });
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog_test.js b/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog_test.js
new file mode 100644
index 0000000..c109538
--- /dev/null
+++ b/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog_test.js
@@ -0,0 +1,82 @@
+/**
+ * @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.
+ */
+
+import '../../../test/common-test-setup-karma.js';
+import './gr-included-in-dialog.js';
+
+const basicFixture = fixtureFromElement('gr-included-in-dialog');
+
+suite('gr-included-in-dialog', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ test('_computeGroups', () => {
+ const includedIn = {branches: [], tags: []};
+ let filterText = '';
+ assert.deepEqual(element._computeGroups(includedIn, filterText), []);
+
+ includedIn.branches.push('master', 'development', 'stable-2.0');
+ includedIn.tags.push('v1.9', 'v2.0', 'v2.1');
+ assert.deepEqual(element._computeGroups(includedIn, filterText), [
+ {title: 'Branches', items: ['master', 'development', 'stable-2.0']},
+ {title: 'Tags', items: ['v1.9', 'v2.0', 'v2.1']},
+ ]);
+
+ includedIn.external = {};
+ assert.deepEqual(element._computeGroups(includedIn, filterText), [
+ {title: 'Branches', items: ['master', 'development', 'stable-2.0']},
+ {title: 'Tags', items: ['v1.9', 'v2.0', 'v2.1']},
+ ]);
+
+ includedIn.external.foo = ['abc', 'def', 'ghi'];
+ assert.deepEqual(element._computeGroups(includedIn, filterText), [
+ {title: 'Branches', items: ['master', 'development', 'stable-2.0']},
+ {title: 'Tags', items: ['v1.9', 'v2.0', 'v2.1']},
+ {title: 'foo', items: ['abc', 'def', 'ghi']},
+ ]);
+
+ filterText = 'v2';
+ assert.deepEqual(element._computeGroups(includedIn, filterText), [
+ {title: 'Tags', items: ['v2.0', 'v2.1']},
+ ]);
+
+ // Filtering is case-insensitive.
+ filterText = 'V2';
+ assert.deepEqual(element._computeGroups(includedIn, filterText), [
+ {title: 'Tags', items: ['v2.0', 'v2.1']},
+ ]);
+ });
+
+ test('_computeGroups with .bindValue', done => {
+ element.$.filterInput.bindValue = 'stable-3.2';
+ const includedIn = {branches: [], tags: []};
+ includedIn.branches.push('master', 'stable-3.2');
+
+ setTimeout(() => {
+ const filterText = element._filterText;
+ assert.deepEqual(element._computeGroups(includedIn, filterText), [
+ {title: 'Branches', items: ['stable-3.2']},
+ ]);
+
+ done();
+ });
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row.js b/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row.js
index f5742ea..fe88e4e 100644
--- a/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row.js
+++ b/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row.js
@@ -128,7 +128,7 @@
}
_computeLabelValue(labels, permittedLabels, label) {
- if ([labels, permittedLabels, label].some(arg => arg === undefined)) {
+ if ([labels, permittedLabels, label].includes(undefined)) {
return null;
}
if (!labels[label.name]) { return null; }
@@ -177,7 +177,7 @@
_computePermittedLabelValues(permittedLabels, label) {
// Polymer 2: check for undefined
- if ([permittedLabels, label].some(arg => arg === undefined)) {
+ if ([permittedLabels, label].includes(undefined)) {
return undefined;
}
diff --git a/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row_test.html b/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row_test.js
similarity index 85%
rename from polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row_test.html
rename to polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row_test.js
index ca4fac3..0739f73 100644
--- a/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row_test.html
+++ b/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row_test.js
@@ -1,47 +1,31 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-label-score-row</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-label-score-row></gr-label-score-row>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-label-score-row.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+
+const basicFixture = fixtureFromElement('gr-label-score-row');
+
suite('gr-label-row-score tests', () => {
let element;
- let sandbox;
setup(done => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.labels = {
'Code-Review': {
values: {
@@ -100,10 +84,6 @@
flush(done);
});
- teardown(() => {
- sandbox.restore();
- });
-
function checkAriaCheckedValid() {
const items = element.$.labelSelector.items;
const selectedItem = element.selectedItem;
@@ -119,7 +99,7 @@
}
test('label picker', () => {
- const labelsChangedHandler = sandbox.stub();
+ const labelsChangedHandler = sinon.stub();
element.addEventListener('labels-changed', labelsChangedHandler);
assert.ok(element.$.labelSelector);
MockInteractions.tap(element.shadowRoot
@@ -387,4 +367,4 @@
assert.isNull(element.selectedValue);
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores.js b/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores.js
index 35ccc3c..aa01b01 100644
--- a/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores.js
+++ b/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores.js
@@ -100,7 +100,7 @@
_computeLabels(labelRecord, account) {
// Polymer 2: check for undefined
- if ([labelRecord, account].some(arg => arg === undefined)) {
+ if ([labelRecord, account].includes(undefined)) {
return undefined;
}
diff --git a/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores_test.html b/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores_test.js
similarity index 73%
rename from polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores_test.html
rename to polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores_test.js
index 7ee86d6..ffc17cd 100644
--- a/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores_test.html
+++ b/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores_test.js
@@ -1,49 +1,33 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-label-scores</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-label-scores></gr-label-scores>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-label-scores.js';
+
+const basicFixture = fixtureFromElement('gr-label-scores');
+
suite('gr-label-scores tests', () => {
let element;
- let sandbox;
setup(done => {
- sandbox = sinon.sandbox.create();
stub('gr-rest-api-interface', {
getLoggedIn() { return Promise.resolve(false); },
});
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.change = {
_number: '123',
labels: {
@@ -101,10 +85,6 @@
flush(done);
});
- teardown(() => {
- sandbox.restore();
- });
-
test('get and set label scores', () => {
for (const label in element.permittedLabels) {
if (element.permittedLabels.hasOwnProperty(label)) {
@@ -193,4 +173,4 @@
]);
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/change/gr-message/gr-message.js b/polygerrit-ui/app/elements/change/gr-message/gr-message.js
index e065008..7163952 100644
--- a/polygerrit-ui/app/elements/change/gr-message/gr-message.js
+++ b/polygerrit-ui/app/elements/change/gr-message/gr-message.js
@@ -233,7 +233,9 @@
// or gerrit level events
// emit the event so change-view can also get updated with latest changes
- this.fire('comment-refresh');
+ this.dispatchEvent(new CustomEvent('comment-refresh', {
+ composed: true, bubbles: true,
+ }));
}
_computeMessageContentExpanded(content, tag) {
@@ -376,7 +378,7 @@
_computeScoreClass(score, labelExtremes) {
// Polymer 2: check for undefined
- if ([score, labelExtremes].some(arg => arg === undefined)) {
+ if ([score, labelExtremes].includes(undefined)) {
return '';
}
if (score.value === 'removed') {
diff --git a/polygerrit-ui/app/elements/change/gr-message/gr-message_test.html b/polygerrit-ui/app/elements/change/gr-message/gr-message_test.js
similarity index 91%
rename from polygerrit-ui/app/elements/change/gr-message/gr-message_test.html
rename to polygerrit-ui/app/elements/change/gr-message/gr-message_test.js
index 332ca52..d425398 100644
--- a/polygerrit-ui/app/elements/change/gr-message/gr-message_test.html
+++ b/polygerrit-ui/app/elements/change/gr-message/gr-message_test.js
@@ -1,40 +1,26 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-message</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-message></gr-message>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-message.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+
+const basicFixture = fixtureFromElement('gr-message');
+
suite('gr-message tests', () => {
let element;
@@ -47,7 +33,7 @@
getIsAdmin() { return Promise.resolve(true); },
deleteChangeCommitMessage() { return Promise.resolve({}); },
});
- element = fixture('basic');
+ element = basicFixture.instantiate();
flush(done);
});
@@ -369,7 +355,7 @@
getIsAdmin() { return Promise.resolve(false); },
deleteChangeCommitMessage() { return Promise.resolve({}); },
});
- element = fixture('basic');
+ element = basicFixture.instantiate();
flush(done);
});
@@ -399,7 +385,7 @@
suite('patchset comment summary', () => {
setup(() => {
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.message = {id: '6a07f64a82f96e7337ca5f7f84cfc73abf8ac2a3'};
});
@@ -467,7 +453,7 @@
getIsAdmin() { return Promise.resolve(false); },
deleteChangeCommitMessage() { return Promise.resolve({}); },
});
- element = fixture('basic');
+ element = basicFixture.instantiate();
flush(done);
});
@@ -521,4 +507,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental.js b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental.js
index ae3a7d2..ee5f0b9 100644
--- a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental.js
+++ b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental.js
@@ -46,7 +46,7 @@
* straightforward.
*/
function computeThreads(message, allMessages, changeComments) {
- if ([message, allMessages, changeComments].some(arg => arg === undefined)) {
+ if ([message, allMessages, changeComments].includes(undefined)) {
return [];
}
if (message._index === undefined) {
@@ -420,6 +420,13 @@
}
return extremes;
}
+
+ /**
+ * Work around a issue on iOS when clicking turns into double tap
+ */
+ _onTapShowAllActivityToggle(e) {
+ e.preventDefault();
+ }
}
customElements.define(GrMessagesListExperimental.is,
diff --git a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental_html.js b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental_html.js
index 56cb960..212de59 100644
--- a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental_html.js
+++ b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental_html.js
@@ -74,6 +74,7 @@
checked="{{_showAllActivity}}"
aria-labelledby="showAllEntriesLabel"
role="switch"
+ on-tap="_onTapShowAllActivityToggle"
></paper-toggle-button>
<div id="showAllEntriesLabel">
<span>Show all entries</span>
@@ -84,16 +85,6 @@
<span class="transparent separator"></span>
</template>
</div>
- <div class="experimentMessage">
- <iron-icon icon="gr-icons:pets"></iron-icon>
- <span>You're currently viewing an experimental Change Log view.</span>
- <a
- target="_blank"
- href="https://www.gerritcodereview.com/2020-05-06-change-log-experiment.html"
- >
- Learn more
- </a>
- </div>
<gr-button
id="collapse-messages"
link=""
diff --git a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental_test.html b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental_test.js
similarity index 86%
rename from polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental_test.html
rename to polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental_test.js
index c520b05..1a0969f 100644
--- a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental_test.html
+++ b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental_test.js
@@ -1,55 +1,42 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2020 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-messages-list-experimental</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<dom-module id="comment-api-mock">
- <template>
- <gr-messages-list-experimental
- id="messagesList"
- change-comments="[[_changeComments]]"></gr-messages-list-experimental>
- <gr-comment-api id="commentAPI"></gr-comment-api>
- </template>
- </dom-module>
-
-<test-fixture id="basic">
- <template>
- <comment-api-mock>
- <gr-messages-list-experimental></gr-messages-list-experimental>
- </comment-api-mock>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import '../../diff/gr-comment-api/gr-comment-api.js';
import './gr-messages-list-experimental.js';
-import '../../../test/mocks/comment-api.js';
+import {createCommentApiMockWithTemplateElement} from '../../../test/mocks/comment-api.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {TEST_ONLY} from './gr-messages-list-experimental.js';
import {MessageTag} from '../../../constants/constants.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+createCommentApiMockWithTemplateElement(
+ 'gr-messages-list-experimental-comment-mock-api', html`
+ <gr-messages-list-experimental
+ id="messagesList"
+ change-comments="[[_changeComments]]"></gr-messages-list-experimental>
+ <gr-comment-api id="commentAPI"></gr-comment-api>
+`);
+
+const basicFixture = fixtureFromTemplate(html`
+<gr-messages-list-experimental-comment-mock-api>
+ <gr-messages-list-experimental></gr-messages-list-experimental>
+</gr-messages-list-experimental-comment-mock-api>
+`);
const randomMessage = function(opt_params) {
const params = opt_params || {};
@@ -68,10 +55,15 @@
};
};
+function generateRandomMessages(count) {
+ return new Array(count).fill()
+ .map(() => randomMessage());
+}
+
suite('gr-messages-list-experimental tests', () => {
let element;
let messages;
- let sandbox;
+
let commentApiWrapper;
const getMessages = function() {
@@ -148,11 +140,11 @@
getDiffRobotComments() { return Promise.resolve({}); },
getDiffDrafts() { return Promise.resolve({}); },
});
- sandbox = sinon.sandbox.create();
- messages = _.times(3, randomMessage);
+
+ messages = generateRandomMessages(3);
// Element must be wrapped in an element with direct access to the
// comment API.
- commentApiWrapper = fixture('basic');
+ commentApiWrapper = basicFixture.instantiate();
element = commentApiWrapper.$.messagesList;
element.messages = messages;
@@ -161,10 +153,6 @@
return commentApiWrapper.loadComments();
});
- teardown(() => {
- sandbox.restore();
- });
-
test('expand/collapse all', () => {
let allMessageEls = getMessages();
for (const message of allMessageEls) {
@@ -219,8 +207,8 @@
message.set('message.expanded', false);
}
- const scrollToStub = sandbox.stub(window, 'scrollTo');
- const highlightStub = sandbox.stub(element, '_highlightEl');
+ const scrollToStub = sinon.stub(window, 'scrollTo');
+ const highlightStub = sinon.stub(element, '_highlightEl');
element.scrollToMessage('invalid');
@@ -241,9 +229,9 @@
});
test('scroll to message offscreen', () => {
- const scrollToStub = sandbox.stub(window, 'scrollTo');
- const highlightStub = sandbox.stub(element, '_highlightEl');
- element.messages = _.times(25, randomMessage);
+ const scrollToStub = sinon.stub(window, 'scrollTo');
+ const highlightStub = sinon.stub(element, '_highlightEl');
+ element.messages = generateRandomMessages(25);
flushAsynchronousOperations();
assert.isFalse(scrollToStub.called);
assert.isFalse(highlightStub.called);
@@ -450,7 +438,7 @@
suite('gr-messages-list-experimental automate tests', () => {
let element;
let messages;
- let sandbox;
+
let commentApiWrapper;
setup(() => {
@@ -462,7 +450,6 @@
getDiffDrafts() { return Promise.resolve({}); },
});
- sandbox = sinon.sandbox.create();
messages = [
randomMessage(),
randomMessage({tag: 'auto', _revision_number: 2}),
@@ -471,9 +458,9 @@
// Element must be wrapped in an element with direct access to the
// comment API.
- commentApiWrapper = fixture('basic');
+ commentApiWrapper = basicFixture.instantiate();
element = commentApiWrapper.$.messagesList;
- sandbox.spy(commentApiWrapper.$.commentAPI, 'loadAll');
+ sinon.spy(commentApiWrapper.$.commentAPI, 'loadAll');
element.messages = messages;
// Stub methods on the changeComments object after changeComments has
@@ -481,10 +468,6 @@
return commentApiWrapper.loadComments();
});
- teardown(() => {
- sandbox.restore();
- });
-
test('hide autogenerated button is not hidden', () => {
const toggle = dom(element.root).querySelector('.showAllActivityToggle');
assert.isOk(toggle);
@@ -516,7 +499,7 @@
});
test('_computeLabelExtremes', () => {
- const computeSpy = sandbox.spy(element, '_computeLabelExtremes');
+ const computeSpy = sinon.spy(element, '_computeLabelExtremes');
element.labels = null;
assert.isTrue(computeSpy.calledOnce);
@@ -558,4 +541,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.js b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.js
index adf9fd3..30482e2 100644
--- a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.js
+++ b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.js
@@ -167,7 +167,7 @@
_computeItems(messages, reviewerUpdates) {
// Polymer 2: check for undefined
- if ([messages, reviewerUpdates].some(arg => arg === undefined)) {
+ if ([messages, reviewerUpdates].includes(undefined)) {
return [];
}
@@ -293,7 +293,7 @@
* @return {!Object} Hash of arrays of comments, filename as key.
*/
_computeCommentsForMessage(changeComments, message) {
- if ([changeComments, message].some(arg => arg === undefined)) {
+ if ([changeComments, message].includes(undefined)) {
return {};
}
const comments = changeComments.getAllPublishedComments();
@@ -344,7 +344,7 @@
* more visible messages in the list.
*/
_getDelta(visibleMessages, messages, hideAutomated) {
- if ([visibleMessages, messages].some(arg => arg === undefined)) {
+ if ([visibleMessages, messages].includes(undefined)) {
return 0;
}
@@ -367,7 +367,7 @@
* exist in _visibleMessages.
*/
_numRemaining(visibleMessages, messages, hideAutomated) {
- if ([visibleMessages, messages].some(arg => arg === undefined)) {
+ if ([visibleMessages, messages].includes(undefined)) {
return 0;
}
@@ -391,7 +391,7 @@
_computeShowHideTextHidden(visibleMessages, messages,
hideAutomated) {
- if ([visibleMessages, messages].some(arg => arg === undefined)) {
+ if ([visibleMessages, messages].includes(undefined)) {
return 0;
}
@@ -464,6 +464,13 @@
}
return extremes;
}
+
+ /**
+ * Work around a issue on iOS when clicking turns into double tap
+ */
+ _onTapHideAutomated(e) {
+ e.preventDefault();
+ }
}
customElements.define(GrMessagesList.is, GrMessagesList);
diff --git a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list_html.js b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list_html.js
index 5adfc53..2636a54 100644
--- a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list_html.js
+++ b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list_html.js
@@ -81,8 +81,9 @@
checked="{{_hideAutomated}}"
aria-labelledby="onlyCommentsLabel"
role="switch"
- ></paper-toggle-button
- ><span id="onlyCommentsLabel">Only comments</span>
+ on-tap="_onTapHideAutomated"
+ ></paper-toggle-button>
+ <span id="onlyCommentsLabel">Only comments</span>
<span class="transparent separator"></span>
</span>
<gr-button
diff --git a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list_test.html b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list_test.js
similarity index 81%
rename from polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list_test.html
rename to polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list_test.js
index 4a0f3f1..4f05dfc 100644
--- a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list_test.html
+++ b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list_test.js
@@ -1,53 +1,42 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+import {createCommentApiMockWithTemplateElement} from '../../../test/mocks/comment-api';
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-messages-list</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<dom-module id="comment-api-mock">
- <template>
- <gr-messages-list
- id="messagesList"
- change-comments="[[_changeComments]]"></gr-messages-list>
- <gr-comment-api id="commentAPI"></gr-comment-api>
- </template>
- </dom-module>
-
-<test-fixture id="basic">
- <template>
- <comment-api-mock>
- <gr-messages-list></gr-messages-list>
- </comment-api-mock>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import '../../diff/gr-comment-api/gr-comment-api.js';
import './gr-messages-list.js';
import '../../../test/mocks/comment-api.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+createCommentApiMockWithTemplateElement(
+ 'gr-messages-list-comment-mock-api', html`
+ <gr-messages-list
+ id="messagesList"
+ change-comments="[[_changeComments]]"></gr-messages-list>
+ <gr-comment-api id="commentAPI"></gr-comment-api>
+`);
+
+const basicFixture = fixtureFromTemplate(html`
+<gr-messages-list-comment-mock-api>
+ <gr-messages-list></gr-messages-list>
+</gr-messages-list-comment-mock-api>
+`);
+
const randomMessage = function(opt_params) {
const params = opt_params || {};
const author1 = {
@@ -69,10 +58,36 @@
randomMessage(opt_params));
};
+function generateRandomMessages(count) {
+ return new Array(count).fill()
+ .map(() => randomMessage());
+}
+
+function generateRandomAutomatedMessages(count) {
+ return new Array(count).fill()
+ .map(() => randomAutomated());
+}
+
+// Returns a shuffled copy of array
+export function shuffle(arr) {
+ const result = [];
+ for (const item of arr) {
+ // Random number in the interval [0..array.length]
+ const j = Math.floor(Math.random() * (arr.length + 1));
+ if (j < result.length) {
+ result.push(result[j]);
+ result[j] = item;
+ } else {
+ result.push(item);
+ }
+ }
+ return result;
+}
+
suite('gr-messages-list tests', () => {
let element;
let messages;
- let sandbox;
+
let commentApiWrapper;
const getMessages = function() {
@@ -140,11 +155,11 @@
getDiffRobotComments() { return Promise.resolve({}); },
getDiffDrafts() { return Promise.resolve({}); },
});
- sandbox = sinon.sandbox.create();
- messages = _.times(3, randomMessage);
+
+ messages = generateRandomMessages(3);
// Element must be wrapped in an element with direct access to the
// comment API.
- commentApiWrapper = fixture('basic');
+ commentApiWrapper = basicFixture.instantiate();
element = commentApiWrapper.$.messagesList;
element.messages = messages;
@@ -153,13 +168,9 @@
return commentApiWrapper.loadComments();
});
- teardown(() => {
- sandbox.restore();
- });
-
test('show some old messages', () => {
assert.isTrue(element.$.messageControlsContainer.hasAttribute('hidden'));
- element.messages = _.times(26, randomMessage);
+ element.messages = generateRandomMessages(26);
flushAsynchronousOperations();
assert.isFalse(element.$.messageControlsContainer.hasAttribute('hidden'));
@@ -181,7 +192,7 @@
test('show all old messages', () => {
assert.isTrue(element.$.messageControlsContainer.hasAttribute('hidden'));
- element.messages = _.times(26, randomMessage);
+ element.messages = generateRandomMessages(26);
flushAsynchronousOperations();
assert.isFalse(element.$.messageControlsContainer.hasAttribute('hidden'));
@@ -196,8 +207,8 @@
});
test('message count respects automated', () => {
- element.messages = _.times(10, randomAutomated)
- .concat(_.times(11, randomMessage));
+ element.messages = generateRandomAutomatedMessages(10)
+ .concat(generateRandomMessages(11));
flushAsynchronousOperations();
assert.equal(element.$.oldMessagesBtn.innerText.toUpperCase(),
@@ -210,8 +221,8 @@
});
test('message count still respects non-automated on toggle', () => {
- element.messages = _.times(10, randomMessage)
- .concat(_.times(11, randomAutomated));
+ element.messages = generateRandomMessages(10)
+ .concat(generateRandomAutomatedMessages(11));
flushAsynchronousOperations();
assert.equal(element.$.oldMessagesBtn.innerText.toUpperCase(),
@@ -226,8 +237,8 @@
});
test('show all messages respects expand', () => {
- element.messages = _.times(10, randomAutomated)
- .concat(_.times(11, randomMessage));
+ element.messages = generateRandomAutomatedMessages(10)
+ .concat(generateRandomMessages(11));
flushAsynchronousOperations();
MockInteractions.tap(element.shadowRoot
@@ -251,8 +262,8 @@
});
test('show all messages respects collapse', () => {
- element.messages = _.times(10, randomAutomated)
- .concat(_.times(11, randomMessage));
+ element.messages = generateRandomAutomatedMessages(10)
+ .concat(generateRandomMessages(11));
flushAsynchronousOperations();
MockInteractions.tap(element.shadowRoot
@@ -329,8 +340,8 @@
message.set('message.expanded', false);
}
- const scrollToStub = sandbox.stub(window, 'scrollTo');
- const highlightStub = sandbox.stub(element, '_highlightEl');
+ const scrollToStub = sinon.stub(window, 'scrollTo');
+ const highlightStub = sinon.stub(element, '_highlightEl');
element.scrollToMessage('invalid');
@@ -351,9 +362,9 @@
});
test('scroll to message offscreen', () => {
- const scrollToStub = sandbox.stub(window, 'scrollTo');
- const highlightStub = sandbox.stub(element, '_highlightEl');
- element.messages = _.times(25, randomMessage);
+ const scrollToStub = sinon.stub(window, 'scrollTo');
+ const highlightStub = sinon.stub(element, '_highlightEl');
+ element.messages = generateRandomMessages(25);
flushAsynchronousOperations();
assert.isFalse(scrollToStub.called);
assert.isFalse(highlightStub.called);
@@ -430,12 +441,12 @@
test('hide increment text if increment >= total remaining', () => {
// Test with stubbed return values, as _numRemaining and _getDelta have
// their own tests.
- sandbox.stub(element, '_getDelta').returns(5);
- const remainingStub = sandbox.stub(element, '_numRemaining').returns(6);
+ sinon.stub(element, '_getDelta').returns(5);
+ const remainingStub = sinon.stub(element, '_numRemaining').returns(6);
assert.isFalse(element._computeIncrementHidden(null, null, null));
remainingStub.restore();
- sandbox.stub(element, '_numRemaining').returns(4);
+ sinon.stub(element, '_numRemaining').returns(4);
assert.isTrue(element._computeIncrementHidden(null, null, null));
});
});
@@ -443,7 +454,7 @@
suite('gr-messages-list automate tests', () => {
let element;
let messages;
- let sandbox;
+
let commentApiWrapper;
const getMessages = function() {
@@ -467,15 +478,14 @@
getDiffDrafts() { return Promise.resolve({}); },
});
- sandbox = sinon.sandbox.create();
- messages = _.times(2, randomAutomated);
+ messages = generateRandomAutomatedMessages(2);
messages.push(randomMessageReviewer);
// Element must be wrapped in an element with direct access to the
// comment API.
- commentApiWrapper = fixture('basic');
+ commentApiWrapper = basicFixture.instantiate();
element = commentApiWrapper.$.messagesList;
- sandbox.spy(commentApiWrapper.$.commentAPI, 'loadAll');
+ sinon.spy(commentApiWrapper.$.commentAPI, 'loadAll');
element.messages = messages;
// Stub methods on the changeComments object after changeComments has
@@ -483,10 +493,6 @@
return commentApiWrapper.loadComments();
});
- teardown(() => {
- sandbox.restore();
- });
-
test('hide autogenerated button is not hidden', () => {
assert.isNotOk(element.shadowRoot
.querySelector('#automatedMessageToggle[hidden]'));
@@ -529,34 +535,35 @@
assert.equal(element._getDelta([], messages, false), 1);
assert.equal(element._getDelta([], messages, true), 1);
- messages = _.times(7, randomMessage);
+ messages = generateRandomMessages(7);
assert.equal(element._getDelta([], messages, false), 5);
assert.equal(element._getDelta([], messages, true), 5);
- messages = _.times(4, randomMessage)
- .concat(_.times(2, randomAutomated))
- .concat(_.times(3, randomMessage));
+ messages = generateRandomMessages(4)
+ .concat(generateRandomAutomatedMessages(2))
+ .concat(generateRandomMessages(3));
- const dummyArr = _.times(2, randomMessage);
+ const dummyArr = generateRandomMessages(2);
assert.equal(element._getDelta(dummyArr, messages, false), 5);
assert.equal(element._getDelta(dummyArr, messages, true), 7);
});
test('_getHumanMessages', () => {
assert.equal(
- element._getHumanMessages(_.times(5, randomAutomated)).length, 0);
+ element._getHumanMessages(
+ generateRandomAutomatedMessages(5)).length, 0);
assert.equal(
- element._getHumanMessages(_.times(5, randomMessage)).length, 5);
+ element._getHumanMessages(generateRandomMessages(5)).length, 5);
- let messages = _.shuffle(_.times(5, randomMessage)
- .concat(_.times(5, randomAutomated)));
+ let messages = shuffle(generateRandomMessages(5)
+ .concat(generateRandomAutomatedMessages(5)));
messages = element._getHumanMessages(messages);
assert.equal(messages.length, 5);
assert.isFalse(element._hasAutomatedMessages(messages));
});
test('initially show only 20 messages', () => {
- sandbox.stub(element.reporting, 'reportInteraction',
+ sinon.stub(element.reporting, 'reportInteraction').callsFake(
(eventName, details) => {
assert.equal(typeof(eventName), 'string');
if (details) {
@@ -573,7 +580,7 @@
});
test('_computeLabelExtremes', () => {
- const computeSpy = sandbox.spy(element, '_computeLabelExtremes');
+ const computeSpy = sinon.spy(element, '_computeLabelExtremes');
element.labels = null;
assert.isTrue(computeSpy.calledOnce);
@@ -615,4 +622,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list.js b/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list.js
index 8d72d21..bddb15a 100644
--- a/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list.js
+++ b/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list.js
@@ -16,6 +16,9 @@
*/
import '../../shared/gr-rest-api-interface/gr-rest-api-interface.js';
import '../../../styles/shared-styles.js';
+import '../../plugins/gr-endpoint-decorator/gr-endpoint-decorator.js';
+import '../../plugins/gr-endpoint-param/gr-endpoint-param.js';
+import '../../plugins/gr-endpoint-slot/gr-endpoint-slot.js';
import {flush} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {mixinBehaviors} from '@polymer/polymer/lib/legacy/class.js';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
@@ -225,7 +228,7 @@
_computeChangeContainerClass(currentChange, relatedChange) {
const classes = ['changeContainer'];
- if ([relatedChange, currentChange].some(arg => arg === undefined)) {
+ if ([relatedChange, currentChange].includes(undefined)) {
return classes;
}
if (this._changesEqual(relatedChange, currentChange)) {
@@ -324,13 +327,16 @@
conflicts,
cherryPicks,
sameTopic,
- ].some(arg => arg === undefined)) {
+ ].includes(undefined)) {
return;
}
const results = [
related && related.changes,
- submittedTogether && submittedTogether.changes,
+ // If there are either visible or non-visible changes, we need a
+ // non-empty list to fire the event and set visibility.
+ submittedTogether && ((submittedTogether.changes || [])
+ + (submittedTogether.non_visible_changes ? [{}] : [])),
conflicts,
cherryPicks,
sameTopic,
@@ -353,7 +359,7 @@
_computeConnectedRevisions(change, patchNum, relatedChanges) {
// Polymer 2: check for undefined
- if ([change, patchNum, relatedChanges].some(arg => arg === undefined)) {
+ if ([change, patchNum, relatedChanges].includes(undefined)) {
return undefined;
}
diff --git a/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list_html.js b/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list_html.js
index 2321deb..2721b2e2 100644
--- a/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list_html.js
+++ b/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list_html.js
@@ -93,107 +93,112 @@
}
</style>
<div>
- <section
- class="relatedChanges"
- hidden$="[[!_relatedResponse.changes.length]]"
- hidden=""
- >
- <h4>Relation chain</h4>
- <template
- is="dom-repeat"
- items="[[_relatedResponse.changes]]"
- as="related"
+ <gr-endpoint-decorator name="related-changes-section">
+ <gr-endpoint-param name="change" value="[[change]]"></gr-endpoint-param>
+ <gr-endpoint-slot name="top"></gr-endpoint-slot>
+ <section
+ class="relatedChanges"
+ hidden$="[[!_relatedResponse.changes.length]]"
+ hidden=""
>
- <div
- class$="rightIndent [[_computeChangeContainerClass(change, related)]]"
+ <h4>Relation chain</h4>
+ <template
+ is="dom-repeat"
+ items="[[_relatedResponse.changes]]"
+ as="related"
>
- <a
- href$="[[_computeChangeURL(related._change_number, related.project, related._revision_number)]]"
- class$="[[_computeLinkClass(related)]]"
- title$="[[related.commit.subject]]"
+ <div
+ class$="rightIndent [[_computeChangeContainerClass(change, related)]]"
>
- [[related.commit.subject]]
- </a>
- <span class$="[[_computeChangeStatusClass(related)]]">
- ([[_computeChangeStatus(related)]])
- </span>
- </div>
- </template>
- </section>
- <section
- id="submittedTogether"
- class$="[[_computeSubmittedTogetherClass(_submittedTogether)]]"
- >
- <h4>Submitted together</h4>
- <template
- is="dom-repeat"
- items="[[_submittedTogether.changes]]"
- as="related"
+ <a
+ href$="[[_computeChangeURL(related._change_number, related.project, related._revision_number)]]"
+ class$="[[_computeLinkClass(related)]]"
+ title$="[[related.commit.subject]]"
+ >
+ [[related.commit.subject]]
+ </a>
+ <span class$="[[_computeChangeStatusClass(related)]]">
+ ([[_computeChangeStatus(related)]])
+ </span>
+ </div>
+ </template>
+ </section>
+ <section
+ id="submittedTogether"
+ class$="[[_computeSubmittedTogetherClass(_submittedTogether)]]"
>
- <div class$="[[_computeChangeContainerClass(change, related)]]">
- <a
- href$="[[_computeChangeURL(related._number, related.project)]]"
- class$="[[_computeLinkClass(related)]]"
- title$="[[related.project]]: [[related.branch]]: [[related.subject]]"
- >
- [[related.project]]: [[related.branch]]: [[related.subject]]
- </a>
- <span
- tabindex="-1"
- title="Submittable"
- class$="submittableCheck [[_computeLinkClass(related)]]"
- >✓</span
- >
- </div>
- </template>
- <template is="dom-if" if="[[_submittedTogether.non_visible_changes]]">
- <div class="note">
- [[_computeNonVisibleChangesNote(_submittedTogether.non_visible_changes)]]
- </div>
- </template>
- </section>
- <section hidden$="[[!_sameTopic.length]]" hidden="">
- <h4>Same topic</h4>
- <template is="dom-repeat" items="[[_sameTopic]]" as="change">
- <div>
- <a
- href$="[[_computeChangeURL(change._number, change.project)]]"
- class$="[[_computeLinkClass(change)]]"
- title$="[[change.project]]: [[change.branch]]: [[change.subject]]"
- >
- [[change.project]]: [[change.branch]]: [[change.subject]]
- </a>
- </div>
- </template>
- </section>
- <section hidden$="[[!_conflicts.length]]" hidden="">
- <h4>Merge conflicts</h4>
- <template is="dom-repeat" items="[[_conflicts]]" as="change">
- <div>
- <a
- href$="[[_computeChangeURL(change._number, change.project)]]"
- class$="[[_computeLinkClass(change)]]"
- title$="[[change.subject]]"
- >
- [[change.subject]]
- </a>
- </div>
- </template>
- </section>
- <section hidden$="[[!_cherryPicks.length]]" hidden="">
- <h4>Cherry picks</h4>
- <template is="dom-repeat" items="[[_cherryPicks]]" as="change">
- <div>
- <a
- href$="[[_computeChangeURL(change._number, change.project)]]"
- class$="[[_computeLinkClass(change)]]"
- title$="[[change.branch]]: [[change.subject]]"
- >
- [[change.branch]]: [[change.subject]]
- </a>
- </div>
- </template>
- </section>
+ <h4>Submitted together</h4>
+ <template
+ is="dom-repeat"
+ items="[[_submittedTogether.changes]]"
+ as="related"
+ >
+ <div class$="[[_computeChangeContainerClass(change, related)]]">
+ <a
+ href$="[[_computeChangeURL(related._number, related.project)]]"
+ class$="[[_computeLinkClass(related)]]"
+ title$="[[related.project]]: [[related.branch]]: [[related.subject]]"
+ >
+ [[related.project]]: [[related.branch]]: [[related.subject]]
+ </a>
+ <span
+ tabindex="-1"
+ title="Submittable"
+ class$="submittableCheck [[_computeLinkClass(related)]]"
+ >✓</span
+ >
+ </div>
+ </template>
+ <template is="dom-if" if="[[_submittedTogether.non_visible_changes]]">
+ <div class="note">
+ [[_computeNonVisibleChangesNote(_submittedTogether.non_visible_changes)]]
+ </div>
+ </template>
+ </section>
+ <section hidden$="[[!_sameTopic.length]]" hidden="">
+ <h4>Same topic</h4>
+ <template is="dom-repeat" items="[[_sameTopic]]" as="change">
+ <div>
+ <a
+ href$="[[_computeChangeURL(change._number, change.project)]]"
+ class$="[[_computeLinkClass(change)]]"
+ title$="[[change.project]]: [[change.branch]]: [[change.subject]]"
+ >
+ [[change.project]]: [[change.branch]]: [[change.subject]]
+ </a>
+ </div>
+ </template>
+ </section>
+ <section hidden$="[[!_conflicts.length]]" hidden="">
+ <h4>Merge conflicts</h4>
+ <template is="dom-repeat" items="[[_conflicts]]" as="change">
+ <div>
+ <a
+ href$="[[_computeChangeURL(change._number, change.project)]]"
+ class$="[[_computeLinkClass(change)]]"
+ title$="[[change.subject]]"
+ >
+ [[change.subject]]
+ </a>
+ </div>
+ </template>
+ </section>
+ <section hidden$="[[!_cherryPicks.length]]" hidden="">
+ <h4>Cherry picks</h4>
+ <template is="dom-repeat" items="[[_cherryPicks]]" as="change">
+ <div>
+ <a
+ href$="[[_computeChangeURL(change._number, change.project)]]"
+ class$="[[_computeLinkClass(change)]]"
+ title$="[[change.branch]]: [[change.subject]]"
+ >
+ [[change.branch]]: [[change.subject]]
+ </a>
+ </div>
+ </template>
+ </section>
+ <gr-endpoint-slot name="bottom"></gr-endpoint-slot>
+ </gr-endpoint-decorator>
</div>
<div hidden$="[[!loading]]">Loading...</div>
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
diff --git a/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list_test.html b/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list_test.js
similarity index 81%
rename from polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list_test.html
rename to polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list_test.js
index 763a6da..4c164ba 100644
--- a/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list_test.html
+++ b/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list_test.js
@@ -1,52 +1,35 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-related-changes-list</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-related-changes-list></gr-related-changes-list>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-related-changes-list.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
+import {pluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
+import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit.js';
+
+const pluginApi = _testOnly_initGerritPluginApi();
+
+const basicFixture = fixtureFromElement('gr-related-changes-list');
suite('gr-related-changes-list tests', () => {
let element;
- let sandbox;
setup(() => {
- element = fixture('basic');
- sandbox = sinon.sandbox.create();
- });
-
- teardown(() => {
- sandbox.restore();
+ element = basicFixture.instantiate();
});
test('connected revisions', () => {
@@ -258,7 +241,7 @@
});
test('event for section loaded fires for each section ', () => {
- const loadedStub = sandbox.stub();
+ const loadedStub = sinon.stub();
element.patchNum = 7;
element.change = {
change_id: 123,
@@ -266,13 +249,13 @@
};
element.mergeable = true;
element.addEventListener('new-section-loaded', loadedStub);
- sandbox.stub(element, '_getRelatedChanges')
+ sinon.stub(element, '_getRelatedChanges')
.returns(Promise.resolve({changes: []}));
- sandbox.stub(element, '_getSubmittedTogether')
+ sinon.stub(element, '_getSubmittedTogether')
.returns(Promise.resolve());
- sandbox.stub(element, '_getCherryPicks')
+ sinon.stub(element, '_getCherryPicks')
.returns(Promise.resolve());
- sandbox.stub(element, '_getConflicts')
+ sinon.stub(element, '_getConflicts')
.returns(Promise.resolve());
return element.reload().then(() => {
@@ -284,15 +267,15 @@
let element;
setup(() => {
- element = fixture('basic');
+ element = basicFixture.instantiate();
- sandbox.stub(element, '_getRelatedChanges')
+ sinon.stub(element, '_getRelatedChanges')
.returns(Promise.resolve({changes: []}));
- sandbox.stub(element, '_getSubmittedTogether')
+ sinon.stub(element, '_getSubmittedTogether')
.returns(Promise.resolve());
- sandbox.stub(element, '_getCherryPicks')
+ sinon.stub(element, '_getCherryPicks')
.returns(Promise.resolve());
- sandbox.stub(element, '_getConflicts')
+ sinon.stub(element, '_getConflicts')
.returns(Promise.resolve());
});
@@ -313,15 +296,15 @@
let conflictsStub;
setup(() => {
- element = fixture('basic');
+ element = basicFixture.instantiate();
- sandbox.stub(element, '_getRelatedChanges')
+ sinon.stub(element, '_getRelatedChanges')
.returns(Promise.resolve({changes: []}));
- sandbox.stub(element, '_getSubmittedTogether')
+ sinon.stub(element, '_getSubmittedTogether')
.returns(Promise.resolve());
- sandbox.stub(element, '_getCherryPicks')
+ sinon.stub(element, '_getCherryPicks')
.returns(Promise.resolve());
- conflictsStub = sandbox.stub(element, '_getConflicts')
+ conflictsStub = sinon.stub(element, '_getConflicts')
.returns(Promise.resolve());
});
@@ -419,7 +402,7 @@
});
test('update fires', () => {
- const updateHandler = sandbox.stub();
+ const updateHandler = sinon.stub();
element.addEventListener('update', updateHandler);
element._resultsChanged({}, {}, [], [], []);
@@ -429,6 +412,23 @@
element._resultsChanged({}, {}, [], [], ['test']);
assert.isFalse(element.hidden);
assert.isTrue(updateHandler.called);
+ updateHandler.reset();
+
+ element._resultsChanged(
+ {}, {changes: [], non_visible_changes: 0}, [], [], []);
+ assert.isTrue(element.hidden);
+ assert.isFalse(updateHandler.called);
+
+ element._resultsChanged(
+ {}, {changes: ['test'], non_visible_changes: 0}, [], [], []);
+ assert.isFalse(element.hidden);
+ assert.isTrue(updateHandler.called);
+ updateHandler.reset();
+
+ element._resultsChanged(
+ {}, {changes: [], non_visible_changes: 1}, [], [], []);
+ assert.isFalse(element.hidden);
+ assert.isTrue(updateHandler.called);
});
suite('hiding and unhiding', () => {
@@ -465,7 +465,7 @@
});
test('_computeChangeURL uses GerritNav', () => {
- const getUrlStub = sandbox.stub(GerritNav, 'getUrlForChangeById');
+ const getUrlStub = sinon.stub(GerritNav, 'getUrlForChangeById');
element._computeChangeURL(123, 'abc/def', 12);
assert.isTrue(getUrlStub.called);
});
@@ -538,7 +538,8 @@
.querySelector('.note'));
assert.strictEqual(
element.shadowRoot
- .querySelector('.note').innerText, '(+ 1 non-visible change)');
+ .querySelector('.note').innerText.trim(),
+ '(+ 1 non-visible change)');
});
test('visible and non-visible submitted together changes', () => {
@@ -549,8 +550,31 @@
.querySelector('.note'));
assert.strictEqual(
element.shadowRoot
- .querySelector('.note').innerText, '(+ 2 non-visible changes)');
+ .querySelector('.note').innerText.trim(),
+ '(+ 2 non-visible changes)');
+ });
+ });
+
+ suite('plugin endpoints', () => {
+ test('endpoint params', done => {
+ element.change = {labels: {}};
+ let hookEl;
+ let plugin;
+ pluginApi.install(
+ p => {
+ plugin = p;
+ plugin.hook('related-changes-section').getLastAttached()
+ .then(el => hookEl = el);
+ },
+ '0.1',
+ 'http://some/plugins/url.html');
+ pluginLoader.loadPlugins([]);
+ flush(() => {
+ assert.strictEqual(hookEl.plugin, plugin);
+ assert.strictEqual(hookEl.change, element.change);
+ done();
+ });
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog-it_test.html b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog-it_test.html
deleted file mode 100644
index d3232e9..0000000
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog-it_test.html
+++ /dev/null
@@ -1,175 +0,0 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2015 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-reply-dialog</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-reply-dialog></gr-reply-dialog>
- </template>
-</test-fixture>
-
-<test-fixture id="plugin-host">
- <template>
- <gr-plugin-host></gr-plugin-host>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import '../../plugins/gr-plugin-host/gr-plugin-host.js';
-import './gr-reply-dialog.js';
-import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
-import {resetPlugins} from '../../../test/test-utils.js';
-import {pluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
-import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit.js';
-
-_testOnly_initGerritPluginApi();
-
-suite('gr-reply-dialog tests', () => {
- let element;
- let changeNum;
- let patchNum;
-
- let sandbox;
-
- const setupElement = element => {
- element.change = {
- _number: changeNum,
- labels: {
- 'Verified': {
- values: {
- '-1': 'Fails',
- ' 0': 'No score',
- '+1': 'Verified',
- },
- default_value: 0,
- },
- 'Code-Review': {
- values: {
- '-2': 'Do not submit',
- '-1': 'I would prefer that you didn\'t submit this',
- ' 0': 'No score',
- '+1': 'Looks good to me, but someone else must approve',
- '+2': 'Looks good to me, approved',
- },
- all: [{_account_id: 42, value: 0}],
- default_value: 0,
- },
- },
- };
- element.patchNum = patchNum;
- element.permittedLabels = {
- 'Code-Review': [
- '-1',
- ' 0',
- '+1',
- ],
- 'Verified': [
- '-1',
- ' 0',
- '+1',
- ],
- };
- sandbox.stub(element, 'fetchChangeUpdates')
- .returns(Promise.resolve({isLatest: true}));
- };
-
- setup(() => {
- sandbox = sinon.sandbox.create();
-
- changeNum = 42;
- patchNum = 1;
-
- stub('gr-rest-api-interface', {
- getConfig() { return Promise.resolve({}); },
- getAccount() { return Promise.resolve({_account_id: 42}); },
- });
-
- element = fixture('basic');
- setupElement(element);
-
- // Allow the elements created by dom-repeat to be stamped.
- flushAsynchronousOperations();
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('_submit blocked when invalid email is supplied to ccs', () => {
- const sendStub = sandbox.stub(element, 'send').returns(Promise.resolve());
- // Stub the below function to avoid side effects from the send promise
- // resolving.
- sandbox.stub(element, '_purgeReviewersPendingRemove');
-
- element.$.ccs.$.entry.setText('test');
- MockInteractions.tap(element.shadowRoot
- .querySelector('gr-button.send'));
- assert.isFalse(sendStub.called);
- flushAsynchronousOperations();
-
- element.$.ccs.$.entry.setText('test@test.test');
- MockInteractions.tap(element.shadowRoot
- .querySelector('gr-button.send'));
- assert.isTrue(sendStub.called);
- });
-
- test('lgtm plugin', done => {
- resetPlugins();
- const pluginHost = fixture('plugin-host');
- pluginHost.config = {
- plugin: {
- js_resource_paths: [],
- html_resource_paths: [
- new URL('test/plugin.html?' + Math.random(),
- window.location.href).toString(),
- ],
- },
- };
- element = fixture('basic');
- setupElement(element);
- const importSpy =
- sandbox.spy(element.shadowRoot
- .querySelector('gr-endpoint-decorator'), '_import');
- pluginLoader.awaitPluginsLoaded().then(() => {
- Promise.all(importSpy.returnValues).then(() => {
- flush(() => {
- const textarea = element.$.textarea.getNativeTextarea();
- textarea.value = 'LGTM';
- textarea.dispatchEvent(new CustomEvent(
- 'input', {bubbles: true, composed: true}));
- const labelScoreRows = dom(element.$.labelScores.root)
- .querySelector('gr-label-score-row[name="Code-Review"]');
- const selectedBtn = dom(labelScoreRows.root)
- .querySelector('gr-button[data-value="+1"].iron-selected');
- assert.isOk(selectedBtn);
- done();
- });
- });
- });
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog-it_test.js b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog-it_test.js
new file mode 100644
index 0000000..9a94d27
--- /dev/null
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog-it_test.js
@@ -0,0 +1,147 @@
+/**
+ * @license
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import '../../../test/common-test-setup-karma.js';
+import {resetPlugins} from '../../../test/test-utils.js';
+import './gr-reply-dialog.js';
+import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+import {pluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
+import {pluginEndpoints} from '../../shared/gr-js-api-interface/gr-plugin-endpoints.js';
+import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit.js';
+const basicFixture = fixtureFromElement('gr-reply-dialog');
+const pluginApi = _testOnly_initGerritPluginApi();
+
+suite('gr-reply-dialog tests', () => {
+ let element;
+ let changeNum;
+ let patchNum;
+
+ const setupElement = element => {
+ element.change = {
+ _number: changeNum,
+ labels: {
+ 'Verified': {
+ values: {
+ '-1': 'Fails',
+ ' 0': 'No score',
+ '+1': 'Verified',
+ },
+ default_value: 0,
+ },
+ 'Code-Review': {
+ values: {
+ '-2': 'Do not submit',
+ '-1': 'I would prefer that you didn\'t submit this',
+ ' 0': 'No score',
+ '+1': 'Looks good to me, but someone else must approve',
+ '+2': 'Looks good to me, approved',
+ },
+ all: [{_account_id: 42, value: 0}],
+ default_value: 0,
+ },
+ },
+ };
+ element.patchNum = patchNum;
+ element.permittedLabels = {
+ 'Code-Review': [
+ '-1',
+ ' 0',
+ '+1',
+ ],
+ 'Verified': [
+ '-1',
+ ' 0',
+ '+1',
+ ],
+ };
+ sinon.stub(element, 'fetchChangeUpdates')
+ .returns(Promise.resolve({isLatest: true}));
+ };
+
+ setup(() => {
+ changeNum = 42;
+ patchNum = 1;
+
+ stub('gr-rest-api-interface', {
+ getConfig() { return Promise.resolve({}); },
+ getAccount() { return Promise.resolve({_account_id: 42}); },
+ });
+
+ element = basicFixture.instantiate();
+ setupElement(element);
+
+ // Allow the elements created by dom-repeat to be stamped.
+ flushAsynchronousOperations();
+ });
+
+ teardown(() => {
+ resetPlugins();
+ });
+
+ test('_submit blocked when invalid email is supplied to ccs', () => {
+ const sendStub = sinon.stub(element, 'send').returns(Promise.resolve());
+ // Stub the below function to avoid side effects from the send promise
+ // resolving.
+ sinon.stub(element, '_purgeReviewersPendingRemove');
+
+ element.$.ccs.$.entry.setText('test');
+ MockInteractions.tap(element.shadowRoot
+ .querySelector('gr-button.send'));
+ assert.isFalse(sendStub.called);
+ flushAsynchronousOperations();
+
+ element.$.ccs.$.entry.setText('test@test.test');
+ MockInteractions.tap(element.shadowRoot
+ .querySelector('gr-button.send'));
+ assert.isTrue(sendStub.called);
+ });
+
+ test('lgtm plugin', done => {
+ resetPlugins();
+ pluginApi.install(plugin => {
+ const replyApi = plugin.changeReply();
+ replyApi.addReplyTextChangedCallback(text => {
+ const label = 'Code-Review';
+ const labelValue = replyApi.getLabelValue(label);
+ if (labelValue &&
+ labelValue === ' 0' &&
+ text.indexOf('LGTM') === 0) {
+ replyApi.setLabelValue(label, '+1');
+ }
+ });
+ }, null, 'http://test.com/plugins/lgtm.js');
+ element = basicFixture.instantiate();
+ setupElement(element);
+ sinon.stub(pluginEndpoints, 'importUrl')
+ .callsFake( url => Promise.resolve());
+ pluginLoader.loadPlugins([]);
+ pluginLoader.awaitPluginsLoaded().then(() => {
+ flush(() => {
+ const textarea = element.$.textarea.getNativeTextarea();
+ textarea.value = 'LGTM';
+ textarea.dispatchEvent(new CustomEvent(
+ 'input', {bubbles: true, composed: true}));
+ const labelScoreRows = dom(element.$.labelScores.root)
+ .querySelector('gr-label-score-row[name="Code-Review"]');
+ const selectedBtn = dom(labelScoreRows.root)
+ .querySelector('gr-button[data-value="+1"].iron-selected');
+ assert.isOk(selectedBtn);
+ done();
+ });
+ });
+ });
+});
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js
index e37c84a..f3c31aa 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js
@@ -182,6 +182,7 @@
* @type {{ commentlinks: Array }}
*/
projectConfig: Object,
+ serverConfig: Object,
knownLatestState: String,
underReview: {
type: Boolean,
@@ -250,6 +251,33 @@
type: Boolean,
value: false,
},
+ /**
+ * Is the UI in the state where the user individually modifies attention
+ * set entries?
+ */
+ _attentionModified: {
+ type: Boolean,
+ value: false,
+ },
+ /**
+ * Set of account IDs that currently constitutes the attention set, read
+ * from change.attention_set. Will be updated by the
+ * _computeNewAttention() observer.
+ */
+ _currentAttentionSet: {
+ type: Object,
+ value: () => new Set(),
+ },
+ /**
+ * Set of account IDs that should constitute the attention set after
+ * publishing the votes/comments. Will be initialized with a default (that
+ * matches the default rules that the backend would also apply) by the
+ * _computeNewAttention(_account, _reviewers, change) observer.
+ */
+ _newAttentionSet: {
+ type: Object,
+ value: () => new Set(),
+ },
_sendDisabled: {
type: Boolean,
computed: '_computeSendButtonDisabled(canBeStarted, ' +
@@ -282,6 +310,7 @@
'_changeUpdated(change.reviewers.*, change.owner)',
'_ccsChanged(_ccs.splices)',
'_reviewersChanged(_reviewers.splices)',
+ '_computeNewAttention(_account, _reviewers, change)',
];
}
@@ -503,13 +532,29 @@
this.reporting.time(SEND_REPLY_TIMING_LABEL);
const labels = this.$.labelScores.getLabelValues();
- const obj = {
+ const reviewInput = {
drafts: includeComments ? 'PUBLISH_ALL_REVISIONS' : 'KEEP',
labels,
};
if (startReview) {
- obj.ready = true;
+ reviewInput.ready = true;
+ }
+
+ if (this._attentionModified) {
+ reviewInput.ignore_default_attention_set_rules = true;
+ reviewInput.add_to_attention_set = [];
+ for (const user of this._newAttentionSet) {
+ if (!this._currentAttentionSet.has(user)) {
+ reviewInput.add_to_attention_set.push(user);
+ }
+ }
+ reviewInput.remove_from_attention_set = [];
+ for (const user of this._currentAttentionSet) {
+ if (!this._newAttentionSet.has(user)) {
+ reviewInput.remove_from_attention_set.push(user);
+ }
+ }
}
if (this.draft != null) {
@@ -518,16 +563,16 @@
message: this.draft,
unresolved: !this._isResolvedPatchsetLevelComment,
};
- obj.comments = {
+ reviewInput.comments = {
[SpecialFilePath.PATCHSET_LEVEL_COMMENTS]: [comment],
};
} else {
- obj.message = this.draft;
+ reviewInput.message = this.draft;
}
}
const accountAdditions = {};
- obj.reviewers = this.$.reviewers.additions().map(reviewer => {
+ reviewInput.reviewers = this.$.reviewers.additions().map(reviewer => {
if (reviewer.account) {
accountAdditions[reviewer.account._account_id] = true;
}
@@ -541,14 +586,14 @@
}
reviewer = this._mapReviewer(reviewer);
reviewer.state = 'CC';
- obj.reviewers.push(reviewer);
+ reviewInput.reviewers.push(reviewer);
}
}
this.disabled = true;
const errFn = this._handle400Error.bind(this);
- return this._saveReview(obj, errFn)
+ return this._saveReview(reviewInput, errFn)
.then(response => {
if (!response) {
// Null or undefined response indicates that an error handler
@@ -610,6 +655,11 @@
return FocusTarget.BODY;
}
+ _isOwner(account, change) {
+ if (!account || !change || !change.owner) return false;
+ return account._account_id === change.owner._account_id;
+ }
+
_handle400Error(response) {
// A call to _saveReview could fail with a server error if erroneous
// reviewers were requested. This is signalled with a 400 Bad Request
@@ -674,7 +724,7 @@
_changeUpdated(changeRecord, owner) {
// Polymer 2: check for undefined
- if ([changeRecord, owner].some(arg => arg === undefined)) {
+ if ([changeRecord, owner].includes(undefined)) {
return;
}
@@ -713,6 +763,58 @@
this._reviewers = reviewers;
}
+ _handleAttentionModify() {
+ this._attentionModified = true;
+ }
+
+ _showAttentionSummary(config, attentionModified) {
+ return this._isAttentionSetEnabled(config) && !attentionModified;
+ }
+
+ _showAttentionDetails(config, attentionModified) {
+ return this._isAttentionSetEnabled(config) && attentionModified;
+ }
+
+ _isAttentionSetEnabled(config) {
+ return !!config && !!config.change && config.change.enable_attention_set;
+ }
+
+ _handleAttentionClick(e) {
+ const id = e.target.account._account_id;
+ if (!id) return;
+ if (this._newAttentionSet.has(id)) {
+ this._newAttentionSet.delete(id);
+ } else {
+ this._newAttentionSet.add(id);
+ }
+ // Ensure that Polymer picks up the change.
+ this._newAttentionSet = new Set(this._newAttentionSet);
+ }
+
+ _computeHasNewAttention(account, newAttention) {
+ return newAttention && account && newAttention.has(account._account_id);
+ }
+
+ _computeNewAttention(user, reviewers, change) {
+ if ([user, reviewers, change].includes(undefined)) {
+ return;
+ }
+ this._attentionModified = false;
+ this._currentAttentionSet =
+ new Set(Object.keys(change.attention_set || {})
+ .map(id => parseInt(id)));
+ const newAttention = new Set(this._currentAttentionSet);
+ if (this._isOwner(user, change)) {
+ reviewers.forEach(r => newAttention.add(r._account_id));
+ } else {
+ if (change.owner) {
+ newAttention.add(change.owner._account_id);
+ }
+ }
+ if (user) newAttention.delete(user._account_id);
+ this._newAttentionSet = newAttention;
+ }
+
_accountOrGroupKey(entry) {
return entry.id || entry._account_id;
}
@@ -929,7 +1031,7 @@
includeComments,
disabled,
commentEditing,
- ].some(arg => arg === undefined)) {
+ ].includes(undefined)) {
return undefined;
}
@@ -942,7 +1044,7 @@
_computePatchSetWarning(patchNum, labelsChanged) {
let str = `Patch ${patchNum} is not latest.`;
if (labelsChanged) {
- str += ' Voting on a non-latest patch will have no effect.';
+ str += ' Voting will have no effect.';
}
return str;
}
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_html.js b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_html.js
index 79f38a6..b611e41 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_html.js
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_html.js
@@ -134,6 +134,45 @@
.preview-formatting {
margin-left: var(--spacing-m);
}
+ .attention-icon {
+ width: 14px;
+ height: 14px;
+ vertical-align: top;
+ position: relative;
+ top: 3px;
+ --iron-icon-height: 24px;
+ --iron-icon-width: 24px;
+ }
+ .attention .edit-attention-button {
+ vertical-align: top;
+ --padding: 0px 4px;
+ }
+ .attention .edit-attention-button iron-icon {
+ color: inherit;
+ }
+ .attention-detail .peopleList {
+ margin-top: var(--spacing-s);
+ }
+ .attention-detail gr-account-label {
+ background-color: var(--background-color-tertiary);
+ border-radius: 10px;
+ padding: 0 var(--spacing-m) 0 var(--spacing-s);
+ margin-right: var(--spacing-m);
+ user-select: none;
+ }
+ .attention-detail gr-account-label:focus {
+ outline: none;
+ }
+ .attention-detail gr-account-label:hover {
+ box-shadow: var(--elevation-level-1);
+ cursor: pointer;
+ }
+ .attention-detail .attentionDetailsTitle {
+ margin-bottom: var(--spacing-s);
+ }
+ .attention-detail .selectUsers {
+ color: var(--deemphasized-text-color);
+ }
</style>
<div class="container" tabindex="-1">
<section class="peopleContainer">
@@ -276,6 +315,82 @@
Saving comments...
</span>
</section>
+ <section
+ hidden$="[[!_showAttentionSummary(serverConfig, _attentionModified)]]"
+ class="attention"
+ >
+ <div>
+ <iron-icon class="attention-icon" icon="gr-icons:attention"></iron-icon>
+ <span hidden$="[[_isOwner(_account, change)]]"
+ >Bring to owner's attention.</span
+ >
+ <span hidden$="[[!_isOwner(_account, change)]]"
+ >Bring to all reviewer's attention.</span
+ >
+ <gr-button
+ class="edit-attention-button"
+ on-click="_handleAttentionModify"
+ link=""
+ position-below=""
+ data-label="Edit"
+ data-action-type="change"
+ data-action-key="edit"
+ title="Edit attention set changes"
+ role="button"
+ tabindex="0"
+ >
+ <iron-icon icon="gr-icons:edit" class=""></iron-icon>
+ Modify
+ </gr-button>
+ </div>
+ </section>
+ <section
+ hidden$="[[!_showAttentionDetails(serverConfig, _attentionModified)]]"
+ class="attention-detail"
+ >
+ <div class="attentionDetailsTitle">
+ <iron-icon class="attention-icon" icon="gr-icons:attention"></iron-icon>
+ <span>Bring to attention of ...</span>
+ <span class="selectUsers">(select users)</span>
+ </div>
+ <div class="peopleList">
+ <div class="peopleListLabel">Owner</div>
+ <gr-account-label
+ account="[[_owner]]"
+ show-attention="[[_computeHasNewAttention(_owner, _newAttentionSet)]]"
+ blurred="[[!_computeHasNewAttention(_owner, _newAttentionSet)]]"
+ hide-hovercard=""
+ on-click="_handleAttentionClick"
+ >
+ </gr-account-label>
+ </div>
+ <div class="peopleList">
+ <div class="peopleListLabel">Reviewers</div>
+ <template is="dom-repeat" items="[[_reviewers]]" as="account">
+ <gr-account-label
+ account="[[account]]"
+ show-attention="[[_computeHasNewAttention(account, _newAttentionSet)]]"
+ blurred="[[!_computeHasNewAttention(account, _newAttentionSet)]]"
+ hide-hovercard=""
+ on-click="_handleAttentionClick"
+ >
+ </gr-account-label>
+ </template>
+ </div>
+ <div class="peopleList">
+ <div class="peopleListLabel">CC</div>
+ <template is="dom-repeat" items="[[_ccs]]" as="account">
+ <gr-account-label
+ account="[[account]]"
+ show-attention="[[_computeHasNewAttention(account, _newAttentionSet)]]"
+ blurred="[[!_computeHasNewAttention(account, _newAttentionSet)]]"
+ hide-hovercard=""
+ on-click="_handleAttentionClick"
+ >
+ </gr-account-label>
+ </template>
+ </div>
+ </section>
<section class="actions">
<div class="left">
<span
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.js
similarity index 90%
rename from polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html
rename to polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.js
index 576ee3e..4c65298 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.js
@@ -1,44 +1,29 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2015 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-reply-dialog</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-reply-dialog></gr-reply-dialog>
- </template>
-</test-fixture>
-
-<script type="module">
+import '../../../test/common-test-setup-karma.js';
import {IronOverlayManager} from '@polymer/iron-overlay-behavior/iron-overlay-manager.js';
-import '../../../test/common-test-setup.js';
import './gr-reply-dialog.js';
import {mockPromise} from '../../../test/test-utils.js';
import {SpecialFilePath} from '../../../constants/constants.js';
import {appContext} from '../../../services/app-context.js';
+const basicFixture = fixtureFromElement('gr-reply-dialog');
+
function cloneableResponse(status, text) {
return {
ok: false,
@@ -63,7 +48,6 @@
let changeNum;
let patchNum;
- let sandbox;
let getDraftCommentStub;
let setDraftCommentStub;
let eraseDraftCommentStub;
@@ -73,8 +57,6 @@
const makeGroup = function() { return {id: lastId++}; };
setup(() => {
- sandbox = sinon.sandbox.create();
-
changeNum = 42;
patchNum = 1;
@@ -85,11 +67,14 @@
getChangeSuggestedReviewers() { return Promise.resolve([]); },
});
- sandbox.stub(appContext.flagsService, 'isEnabled').returns(true);
+ sinon.stub(appContext.flagsService, 'isEnabled').returns(true);
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.change = {
_number: changeNum,
+ owner: {
+ _account_id: 999,
+ },
labels: {
'Verified': {
values: {
@@ -125,27 +110,23 @@
],
};
- getDraftCommentStub = sandbox.stub(element.$.storage, 'getDraftComment');
- setDraftCommentStub = sandbox.stub(element.$.storage, 'setDraftComment');
- eraseDraftCommentStub = sandbox.stub(element.$.storage,
+ getDraftCommentStub = sinon.stub(element.$.storage, 'getDraftComment');
+ setDraftCommentStub = sinon.stub(element.$.storage, 'setDraftComment');
+ eraseDraftCommentStub = sinon.stub(element.$.storage,
'eraseDraftComment');
- sandbox.stub(element, 'fetchChangeUpdates')
+ sinon.stub(element, 'fetchChangeUpdates')
.returns(Promise.resolve({isLatest: true}));
// Allow the elements created by dom-repeat to be stamped.
flushAsynchronousOperations();
});
- teardown(() => {
- sandbox.restore();
- });
-
function stubSaveReview(jsonResponseProducer) {
- return sandbox.stub(
+ return sinon.stub(
element,
- '_saveReview',
- review => new Promise((resolve, reject) => {
+ '_saveReview')
+ .callsFake(review => new Promise((resolve, reject) => {
try {
const result = jsonResponseProducer(review) || {};
const resultStr =
@@ -199,6 +180,48 @@
});
});
+ test('modified attention set', done => {
+ const buttonEl = element.shadowRoot.querySelector('.edit-attention-button');
+ MockInteractions.tap(buttonEl);
+ flushAsynchronousOperations();
+
+ stubSaveReview(review => {
+ assert.isTrue(review.ignore_default_attention_set_rules);
+ assert.deepEqual(review.add_to_attention_set, []);
+ assert.deepEqual(review.remove_from_attention_set, []);
+ done();
+ });
+ MockInteractions.tap(element.shadowRoot.querySelector('.send'));
+ });
+
+ function checkComputeAttention(
+ userId, reviewerIds, ownerId, attSetIds, expectedIds) {
+ const user = {_account_id: userId};
+ const reviewers = reviewerIds.map(id => {
+ return {_account_id: id};
+ });
+ const change = {
+ owner: {_account_id: ownerId},
+ attention_set: {},
+ };
+ attSetIds.forEach(id => change.attention_set[id] = {});
+ element._computeNewAttention(user, reviewers, change);
+ assert.deepEqual(element._newAttentionSet, new Set(expectedIds));
+ }
+
+ test('computeNewAttention', () => {
+ checkComputeAttention(null, [], 999, [], [999]);
+ checkComputeAttention(1, [], 999, [], [999]);
+ checkComputeAttention(1, [], 999, [1], [999]);
+ checkComputeAttention(1, [22], 999, [], [999]);
+ checkComputeAttention(1, [22], 999, [22], [22, 999]);
+ checkComputeAttention(1, [], 1, [], []);
+ checkComputeAttention(1, [], 1, [1], []);
+ checkComputeAttention(1, [22], 1, [], [22]);
+ checkComputeAttention(1, [22, 33], 1, [], [22, 33]);
+ checkComputeAttention(1, [22, 33], 1, [22, 33], [22, 33]);
+ });
+
test('toggle resolved checkbox', done => {
// Async tick is needed because iron-selector content is distributed and
// distributed content requires an observer to be set up.
@@ -297,7 +320,7 @@
});
});
- sandbox.stub(element.$.labelScores, 'getLabelValues', () => {
+ sinon.stub(element.$.labelScores, 'getLabelValues').callsFake( () => {
return {
'Code-Review': -1,
'Verified': -1,
@@ -605,7 +628,7 @@
});
test('400 converts to human-readable server-error', done => {
- sandbox.stub(window, 'fetch', () => {
+ sinon.stub(window, 'fetch').callsFake(() => {
const text = '....{"reviewers":{"id1":{"error":"first error"}},' +
'"ccs":{"id2":{"error":"second error"}}}';
return Promise.resolve(cloneableResponse(400, text));
@@ -627,7 +650,7 @@
});
test('non-json 400 is treated as a normal server-error', done => {
- sandbox.stub(window, 'fetch', () => {
+ sinon.stub(window, 'fetch').callsFake(() => {
const text = 'Comment validation error!';
return Promise.resolve(cloneableResponse(400, text));
});
@@ -677,12 +700,12 @@
});
test('_focusOn', () => {
- sandbox.spy(element, '_chooseFocusTarget');
+ sinon.spy(element, '_chooseFocusTarget');
flushAsynchronousOperations();
- const textareaStub = sandbox.stub(element.$.textarea, 'async');
- const reviewerEntryStub = sandbox.stub(element.$.reviewers.focusStart,
+ const textareaStub = sinon.stub(element.$.textarea, 'async');
+ const reviewerEntryStub = sinon.stub(element.$.reviewers.focusStart,
'async');
- const ccStub = sandbox.stub(element.$.ccs.focusStart, 'async');
+ const ccStub = sinon.stub(element.$.ccs.focusStart, 'async');
element._focusOn();
assert.equal(element._chooseFocusTarget.callCount, 1);
assert.deepEqual(textareaStub.callCount, 1);
@@ -781,7 +804,7 @@
});
test('_purgeReviewersPendingRemove', () => {
- const removeStub = sandbox.stub(element, '_removeAccount');
+ const removeStub = sinon.stub(element, '_removeAccount');
const mock = function() {
element._reviewersPendingRemove = {
test: [makeAccount()],
@@ -806,7 +829,7 @@
});
test('_removeAccount', done => {
- sandbox.stub(element.$.restAPI, 'removeChangeReviewer')
+ sinon.stub(element.$.restAPI, 'removeChangeReviewer')
.returns(Promise.resolve({ok: true}));
const arr = [makeAccount(), makeAccount()];
element.change.reviewers = {
@@ -907,7 +930,7 @@
stubSaveReview(review => mutations.push(...review.reviewers));
- sandbox.stub(element, '_removeAccount', (account, type) => {
+ sinon.stub(element, '_removeAccount').callsFake((account, type) => {
mutations.push({state: 'REMOVED', account});
return Promise.resolve();
});
@@ -977,7 +1000,7 @@
});
test('emits cancel on esc key', () => {
- const cancelHandler = sandbox.spy();
+ const cancelHandler = sinon.spy();
element.addEventListener('cancel', cancelHandler);
MockInteractions.pressAndReleaseKeyOn(element, 27, null, 'esc');
flushAsynchronousOperations();
@@ -1085,10 +1108,10 @@
let startReviewStub;
setup(() => {
- startReviewStub = sandbox.stub(
+ startReviewStub = sinon.stub(
element.$.restAPI,
- 'startReview',
- () => Promise.resolve());
+ 'startReview')
+ .callsFake(() => Promise.resolve());
});
test('ready property in review input on start review', () => {
@@ -1115,7 +1138,7 @@
let sendStub;
setup(() => {
- sendStub = sandbox.stub(element, 'send', () => Promise.resolve());
+ sendStub = sinon.stub(element, 'send').callsFake(() => Promise.resolve());
element.canBeStarted = true;
// Flush to make both Start/Save buttons appear in DOM.
flushAsynchronousOperations();
@@ -1171,10 +1194,10 @@
suite('pending diff drafts?', () => {
test('yes', () => {
const promise = mockPromise();
- const refreshHandler = sandbox.stub();
+ const refreshHandler = sinon.stub();
element.addEventListener('comment-refresh', refreshHandler);
- sandbox.stub(element.$.restAPI, 'hasPendingDiffDrafts').returns(true);
+ sinon.stub(element.$.restAPI, 'hasPendingDiffDrafts').returns(true);
element.$.restAPI._pendingRequests.sendDiffDraft = [promise];
element.open();
@@ -1190,7 +1213,7 @@
});
test('no', () => {
- sandbox.stub(element.$.restAPI, 'hasPendingDiffDrafts').returns(false);
+ sinon.stub(element.$.restAPI, 'hasPendingDiffDrafts').returns(false);
element.open();
assert.notOk(element._savingComments);
});
@@ -1328,10 +1351,10 @@
});
test('_submit blocked when no mutations exist', () => {
- const sendStub = sandbox.stub(element, 'send').returns(Promise.resolve());
+ const sendStub = sinon.stub(element, 'send').returns(Promise.resolve());
// Stub the below function to avoid side effects from the send promise
// resolving.
- sandbox.stub(element, '_purgeReviewersPendingRemove');
+ sinon.stub(element, '_purgeReviewersPendingRemove');
element.draftCommentThreads = [];
flushAsynchronousOperations();
@@ -1361,4 +1384,4 @@
assert.equal(element.$.pluginMessage.textContent, 'foo');
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/test/plugin.html b/polygerrit-ui/app/elements/change/gr-reply-dialog/test/plugin.html
deleted file mode 100644
index 94787e6..0000000
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/test/plugin.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-<dom-module id="my-plugin">
- <script>
- Gerrit.install(plugin => {
- const replyApi = plugin.changeReply();
- replyApi.addReplyTextChangedCallback(text => {
- const label = 'Code-Review';
- const labelValue = replyApi.getLabelValue(label);
- if (labelValue &&
- labelValue === ' 0' &&
- text.indexOf('LGTM') === 0) {
- replyApi.setLabelValue(label, '+1');
- }
- });
- });
- </script>
-</dom-module>
diff --git a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.js b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.js
index 88e3160..0c48aca 100644
--- a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.js
+++ b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.js
@@ -178,7 +178,7 @@
_reviewersChanged(changeRecord, owner, serverConfig) {
// Polymer 2: check for undefined
- if ([changeRecord, owner, serverConfig].some(arg => arg === undefined)) {
+ if ([changeRecord, owner, serverConfig].includes(undefined)) {
return;
}
@@ -212,7 +212,7 @@
_computeHiddenCount(reviewers, displayedReviewers) {
// Polymer 2: check for undefined
- if ([reviewers, displayedReviewers].some(arg => arg === undefined)) {
+ if ([reviewers, displayedReviewers].includes(undefined)) {
return undefined;
}
diff --git a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_html.js b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_html.js
index 93926cf..13a41ed 100644
--- a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_html.js
+++ b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_html.js
@@ -43,7 +43,9 @@
<gr-account-chip
class="reviewer"
account="[[reviewer]]"
+ change="[[change]]"
on-remove="_handleRemove"
+ highlight-attention
voteable-text="[[_computeVoteableText(reviewer, change)]]"
removable="[[_computeCanRemoveReviewer(reviewer, mutable)]]"
>
diff --git a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.html b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.js
similarity index 83%
rename from polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.html
rename to polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.js
index 6949afc..809a768 100644
--- a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.html
+++ b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.js
@@ -1,48 +1,33 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2015 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-reviewer-list</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-reviewer-list></gr-reviewer-list>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-reviewer-list.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+
+const basicFixture = fixtureFromElement('gr-reviewer-list');
+
suite('gr-reviewer-list tests', () => {
let element;
- let sandbox;
setup(() => {
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.serverConfig = {};
- sandbox = sinon.sandbox.create();
+
stub('gr-rest-api-interface', {
getConfig() { return Promise.resolve({}); },
removeChangeReviewer() {
@@ -51,10 +36,6 @@
});
});
- teardown(() => {
- sandbox.restore();
- });
-
test('controls hidden on immutable element', () => {
element.mutable = false;
assert.isTrue(element.shadowRoot
@@ -176,7 +157,7 @@
});
test('_handleAddTap passes mode with event', () => {
- const fireStub = sandbox.stub(element, 'dispatchEvent');
+ const fireStub = sinon.stub(element, 'dispatchEvent');
const e = {preventDefault() {}};
element.ccsOnly = false;
@@ -320,4 +301,4 @@
element._computeVoteableText({_account_id: 1}, change), '');
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list.js b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list.js
index bd91990..28a8d9a 100644
--- a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list.js
+++ b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list.js
@@ -296,6 +296,13 @@
_isOnParent(side) {
return !!side;
}
+
+ /**
+ * Work around a issue on iOS when clicking turns into double tap
+ */
+ _onTapUnresolvedToggle(e) {
+ e.preventDefault();
+ }
}
customElements.define(GrThreadList.is, GrThreadList);
diff --git a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_html.js b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_html.js
index bb87db8..80983ca 100644
--- a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_html.js
+++ b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_html.js
@@ -61,14 +61,20 @@
<template is="dom-if" if="[[!hideToggleButtons]]">
<div class="header">
<div class="toggleItem">
- <paper-toggle-button id="unresolvedToggle" checked="{{_unresolvedOnly}}"
+ <paper-toggle-button
+ id="unresolvedToggle"
+ checked="{{_unresolvedOnly}}"
+ on-tap="_onTapUnresolvedToggle"
>Only unresolved threads</paper-toggle-button
>
</div>
<div
class$="toggleItem draftToggle [[_computeShowDraftToggle(loggedIn)]]"
>
- <paper-toggle-button id="draftToggle" checked="{{_draftsOnly}}"
+ <paper-toggle-button
+ id="draftToggle"
+ checked="{{_draftsOnly}}"
+ on-tap="_onTapUnresolvedToggle"
>Only threads with drafts</paper-toggle-button
>
</div>
diff --git a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_test.html b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_test.js
similarity index 93%
rename from polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_test.html
rename to polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_test.js
index 3b29ea7..df4850c 100644
--- a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_test.html
+++ b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_test.js
@@ -1,46 +1,31 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2018 The Android Open Source Project
+/**
+ * @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.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-thread-list</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-thread-list></gr-thread-list>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-thread-list.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {NO_THREADS_MSG} from '../../../constants/messages.js';
import {SpecialFilePath} from '../../../constants/constants.js';
+const basicFixture = fixtureFromElement('gr-thread-list');
+
suite('gr-thread-list tests', () => {
let element;
- let sandbox;
+
let threadElements;
function getVisibleThreads() {
@@ -50,8 +35,7 @@
}
setup(done => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.threads = [
{
comments: [
@@ -283,10 +267,6 @@
});
});
- teardown(() => {
- sandbox.restore();
- });
-
test('draft toggle only appears when logged in', () => {
assert.equal(getComputedStyle(element.shadowRoot
.querySelector('.draftToggle')).display,
@@ -594,8 +574,8 @@
});
test('modification events are consumed and displatched', () => {
- sandbox.spy(element, '_handleCommentsChanged');
- const dispatchSpy = sandbox.stub();
+ sinon.spy(element, '_handleCommentsChanged');
+ const dispatchSpy = sinon.stub();
element.addEventListener('thread-list-modified', dispatchSpy);
threadElements[0].dispatchEvent(
new CustomEvent('thread-changed', {
@@ -648,4 +628,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/change/gr-upload-help-dialog/gr-upload-help-dialog.js b/polygerrit-ui/app/elements/change/gr-upload-help-dialog/gr-upload-help-dialog.js
index 0658996..15319e6 100644
--- a/polygerrit-ui/app/elements/change/gr-upload-help-dialog/gr-upload-help-dialog.js
+++ b/polygerrit-ui/app/elements/change/gr-upload-help-dialog/gr-upload-help-dialog.js
@@ -102,7 +102,7 @@
revision,
preferredDownloadCommand,
preferredDownloadScheme,
- ].some(arg => arg === undefined)) {
+ ].includes(undefined)) {
return undefined;
}
diff --git a/polygerrit-ui/app/elements/change/gr-upload-help-dialog/gr-upload-help-dialog_test.html b/polygerrit-ui/app/elements/change/gr-upload-help-dialog/gr-upload-help-dialog_test.js
similarity index 67%
rename from polygerrit-ui/app/elements/change/gr-upload-help-dialog/gr-upload-help-dialog_test.html
rename to polygerrit-ui/app/elements/change/gr-upload-help-dialog/gr-upload-help-dialog_test.js
index 164c483..d1af425 100644
--- a/polygerrit-ui/app/elements/change/gr-upload-help-dialog/gr-upload-help-dialog_test.html
+++ b/polygerrit-ui/app/elements/change/gr-upload-help-dialog/gr-upload-help-dialog_test.js
@@ -1,44 +1,30 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2018 The Android Open Source Project
+/**
+ * @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.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-upload-help-dialog</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-upload-help-dialog></gr-upload-help-dialog>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-upload-help-dialog.js';
+
+const basicFixture = fixtureFromElement('gr-upload-help-dialog');
+
suite('gr-upload-help-dialog tests', () => {
let element;
setup(() => {
- element = fixture('basic');
+ element = basicFixture.instantiate();
});
test('constructs push command from branch', () => {
@@ -121,4 +107,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.js b/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.js
index 23a4c55..f06cfe9 100644
--- a/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.js
+++ b/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.js
@@ -86,7 +86,7 @@
_getLinks(switchAccountUrl, path) {
// Polymer 2: check for undefined
- if ([switchAccountUrl, path].some(arg => arg === undefined)) {
+ if ([switchAccountUrl, path].includes(undefined)) {
return undefined;
}
diff --git a/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown_test.html b/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown_test.js
similarity index 65%
rename from polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown_test.html
rename to polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown_test.js
index a366d09..a8f206c 100644
--- a/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown_test.html
+++ b/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown_test.js
@@ -1,39 +1,25 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2015 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-account-dropdown</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-account-dropdown></gr-account-dropdown>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-account-dropdown.js';
+
+const basicFixture = fixtureFromElement('gr-account-dropdown');
+
suite('gr-account-dropdown tests', () => {
let element;
@@ -41,7 +27,7 @@
stub('gr-rest-api-interface', {
getConfig() { return Promise.resolve({}); },
});
- element = fixture('basic');
+ element = basicFixture.instantiate();
});
test('account information', () => {
@@ -121,4 +107,4 @@
'${}, TEST, , bar');
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/core/gr-error-dialog/gr-error-dialog_test.html b/polygerrit-ui/app/elements/core/gr-error-dialog/gr-error-dialog_test.html
deleted file mode 100644
index bd4991f..0000000
--- a/polygerrit-ui/app/elements/core/gr-error-dialog/gr-error-dialog_test.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-error-dialog</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-error-dialog></gr-error-dialog>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-error-dialog.js';
-suite('gr-error-dialog tests', () => {
- let element;
-
- setup(() => {
- element = fixture('basic');
- });
-
- test('dismiss tap fires event', done => {
- element.addEventListener('dismiss', () => { done(); });
- MockInteractions.tap(element.$.dialog.$.confirm);
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/core/gr-error-dialog/gr-error-dialog_test.js b/polygerrit-ui/app/elements/core/gr-error-dialog/gr-error-dialog_test.js
new file mode 100644
index 0000000..ea8f7c5
--- /dev/null
+++ b/polygerrit-ui/app/elements/core/gr-error-dialog/gr-error-dialog_test.js
@@ -0,0 +1,35 @@
+/**
+ * @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.
+ */
+
+import '../../../test/common-test-setup-karma.js';
+import './gr-error-dialog.js';
+
+const basicFixture = fixtureFromElement('gr-error-dialog');
+
+suite('gr-error-dialog tests', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ test('dismiss tap fires event', done => {
+ element.addEventListener('dismiss', () => { done(); });
+ MockInteractions.tap(element.$.dialog.$.confirm);
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.js b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.js
index 6cd2491..a6aef95 100644
--- a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.js
+++ b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.js
@@ -118,9 +118,10 @@
this._clearHideAlertHandle();
this.unlisten(document, 'server-error', '_handleServerError');
this.unlisten(document, 'network-error', '_handleNetworkError');
- this.unlisten(document, 'show-auth-required', '_handleAuthRequired');
- this.unlisten(document, 'visibilitychange', '_handleVisibilityChange');
+ this.unlisten(document, 'show-alert', '_handleShowAlert');
this.unlisten(document, 'show-error', '_handleShowErrorDialog');
+ this.unlisten(document, 'visibilitychange', '_handleVisibilityChange');
+ this.unlisten(document, 'show-auth-required', '_handleAuthRequired');
this._authErrorHandlerDeregistrationHook();
}
diff --git a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.html b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.js
similarity index 68%
rename from polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.html
rename to polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.js
index b52bb7d..934f244 100644
--- a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.html
+++ b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.js
@@ -1,66 +1,53 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-error-manager</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-error-manager></gr-error-manager>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-error-manager.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit.js';
+const basicFixture = fixtureFromElement('gr-error-manager');
+
_testOnly_initGerritPluginApi();
suite('gr-error-manager tests', () => {
let element;
- let sandbox;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- });
-
- teardown(() => {
- sandbox.restore();
- });
suite('when authed', () => {
+ let toastSpy;
+ let openOverlaySpy;
+
setup(() => {
- sandbox.stub(window, 'fetch')
+ sinon.stub(window, 'fetch')
.returns(Promise.resolve({ok: true, status: 204}));
- element = fixture('basic');
+ element = basicFixture.instantiate();
element._authService.clearCache();
+ toastSpy = sinon.spy(element, '_createToastAlert');
+ openOverlaySpy = sinon.spy(element.$.noInteractionOverlay, 'open');
+ });
+
+ teardown(() => {
+ toastSpy.getCalls().forEach(call => {
+ call.returnValue.remove();
+ });
});
test('does not show auth error on 403 by default', done => {
- const showAuthErrorStub = sandbox.stub(element, '_showAuthErrorAlert');
+ const showAuthErrorStub = sinon.stub(element, '_showAuthErrorAlert');
const responseText = Promise.resolve('server says no.');
element.dispatchEvent(
new CustomEvent('server-error', {
@@ -76,7 +63,7 @@
test('show auth required for 403 with auth error and not authed before',
done => {
- const showAuthErrorStub = sandbox.stub(
+ const showAuthErrorStub = sinon.stub(
element, '_showAuthErrorAlert'
);
const responseText = Promise.resolve('Authentication required\n');
@@ -113,7 +100,7 @@
});
test('show logged in error', () => {
- sandbox.stub(element, '_showAuthErrorAlert');
+ sinon.stub(element, '_showAuthErrorAlert');
element.dispatchEvent(
new CustomEvent('show-auth-required', {
composed: true, bubbles: true,
@@ -123,8 +110,8 @@
});
test('show normal Error', done => {
- const showErrorStub = sandbox.stub(element, '_showErrorDialog');
- const textSpy = sandbox.spy(() => Promise.resolve('ZOMG'));
+ const showErrorStub = sinon.stub(element, '_showErrorDialog');
+ const textSpy = sinon.spy(() => Promise.resolve('ZOMG'));
element.dispatchEvent(
new CustomEvent('server-error', {
detail: {response: {status: 500, text: textSpy}},
@@ -171,7 +158,7 @@
});
test('extract trace id from headers if exists', done => {
- const textSpy = sandbox.spy(
+ const textSpy = sinon.spy(
() => Promise.resolve('500')
);
const headers = new Headers();
@@ -197,8 +184,8 @@
});
test('suppress TOO_MANY_FILES error', done => {
- const showAlertStub = sandbox.stub(element, '_showAlert');
- const textSpy = sandbox.spy(
+ const showAlertStub = sinon.stub(element, '_showAlert');
+ const textSpy = sinon.spy(
() => Promise.resolve('too many files to find conflicts')
);
element.dispatchEvent(
@@ -215,8 +202,8 @@
});
test('show network error', done => {
- const consoleErrorStub = sandbox.stub(console, 'error');
- const showAlertStub = sandbox.stub(element, '_showAlert');
+ const consoleErrorStub = sinon.stub(console, 'error');
+ const showAlertStub = sinon.stub(element, '_showAlert');
element.dispatchEvent(
new CustomEvent('network-error', {
detail: {error: new Error('ZOMG')},
@@ -232,13 +219,12 @@
});
});
- test('show auth refresh toast', done => {
+ test('show auth refresh toast', async () => {
// starts with authed state
element.$.restAPI.getLoggedIn();
- const refreshStub = sandbox.stub(element.$.restAPI, 'getAccount',
+ const refreshStub = sinon.stub(element.$.restAPI, 'getAccount').callsFake(
() => Promise.resolve({}));
- const toastSpy = sandbox.spy(element, '_createToastAlert');
- const windowOpen = sandbox.stub(window, 'open');
+ const windowOpen = sinon.stub(window, 'open');
const responseText = Promise.resolve('Authentication required\n');
// fake failed auth
window.fetch.returns(Promise.resolve({status: 403}));
@@ -249,67 +235,65 @@
composed: true, bubbles: true,
}));
assert.equal(window.fetch.callCount, 1);
- flush(() => {
- // here needs two flush as there are two chanined
- // promises on server-error handler and flush only flushes one
- assert.equal(window.fetch.callCount, 2);
- flush(() => {
- // auth-error fired
- assert.isTrue(toastSpy.called);
+ await flush();
- // toast
- let toast = toastSpy.lastCall.returnValue;
- assert.isOk(toast);
- assert.include(
- dom(toast.root).textContent, 'Credentials expired.');
- assert.include(
- dom(toast.root).textContent, 'Refresh credentials');
+ // here needs two flush as there are two chanined
+ // promises on server-error handler and flush only flushes one
+ assert.equal(window.fetch.callCount, 2);
+ await flush();
+ // Sometime overlay opens with delay, waiting while open is complete
+ await openOverlaySpy.lastCall.returnValue;
+ // auth-error fired
+ assert.isTrue(toastSpy.called);
- // noInteractionOverlay
- const noInteractionOverlay = element.$.noInteractionOverlay;
- assert.isOk(noInteractionOverlay);
- sinon.spy(noInteractionOverlay, 'close');
- assert.equal(
- noInteractionOverlay.backdropElement.getAttribute('opened'),
- '');
- assert.isFalse(windowOpen.called);
- MockInteractions.tap(toast.shadowRoot
- .querySelector('gr-button.action'));
- assert.isTrue(windowOpen.called);
+ // toast
+ let toast = toastSpy.lastCall.returnValue;
+ assert.isOk(toast);
+ assert.include(
+ dom(toast.root).textContent, 'Credentials expired.');
+ assert.include(
+ dom(toast.root).textContent, 'Refresh credentials');
- // @see Issue 5822: noopener breaks closeAfterLogin
- assert.equal(windowOpen.lastCall.args[2].indexOf('noopener=yes'),
- -1);
+ // noInteractionOverlay
+ const noInteractionOverlay = element.$.noInteractionOverlay;
+ assert.isOk(noInteractionOverlay);
+ sinon.spy(noInteractionOverlay, 'close');
+ assert.equal(
+ noInteractionOverlay.backdropElement.getAttribute('opened'),
+ '');
+ assert.isFalse(windowOpen.called);
+ MockInteractions.tap(toast.shadowRoot
+ .querySelector('gr-button.action'));
+ assert.isTrue(windowOpen.called);
- const hideToastSpy = sandbox.spy(toast, 'hide');
+ // @see Issue 5822: noopener breaks closeAfterLogin
+ assert.equal(windowOpen.lastCall.args[2].indexOf('noopener=yes'),
+ -1);
- // now fake authed
- window.fetch.returns(Promise.resolve({status: 204}));
- element._handleWindowFocus();
- element.flushDebouncer('checkLoggedIn');
- flush(() => {
- assert.isTrue(refreshStub.called);
- assert.isTrue(hideToastSpy.called);
+ const hideToastSpy = sinon.spy(toast, 'hide');
- // toast update
- assert.notStrictEqual(toastSpy.lastCall.returnValue, toast);
- toast = toastSpy.lastCall.returnValue;
- assert.isOk(toast);
- assert.include(
- dom(toast.root).textContent, 'Credentials refreshed');
+ // now fake authed
+ window.fetch.returns(Promise.resolve({status: 204}));
+ element._handleWindowFocus();
+ element.flushDebouncer('checkLoggedIn');
+ await flush();
+ assert.isTrue(refreshStub.called);
+ assert.isTrue(hideToastSpy.called);
- // close overlay
- assert.isTrue(noInteractionOverlay.close.called);
- done();
- });
- });
- });
+ // toast update
+ assert.notStrictEqual(toastSpy.lastCall.returnValue, toast);
+ toast = toastSpy.lastCall.returnValue;
+ assert.isOk(toast);
+ assert.include(
+ dom(toast.root).textContent, 'Credentials refreshed');
+
+ // close overlay
+ assert.isTrue(noInteractionOverlay.close.called);
});
- test('auth toast should dismiss existing toast', done => {
+ test('auth toast should dismiss existing toast', async () => {
// starts with authed state
element.$.restAPI.getLoggedIn();
- const toastSpy = sandbox.spy(element, '_createToastAlert');
const responseText = Promise.resolve('Authentication required\n');
// fake an alert
@@ -318,7 +302,7 @@
detail: {message: 'test reload', action: 'reload'},
composed: true, bubbles: true,
}));
- const toast = toastSpy.lastCall.returnValue;
+ let toast = toastSpy.lastCall.returnValue;
assert.isOk(toast);
assert.include(
dom(toast.root).textContent, 'test reload');
@@ -332,26 +316,24 @@
composed: true, bubbles: true,
}));
assert.equal(window.fetch.callCount, 1);
- flush(() => {
- // here needs two flush as there are two chained
- // promises on server-error handler and flush only flushes one
- assert.equal(window.fetch.callCount, 2);
- flush(() => {
- // toast
- const toast = toastSpy.lastCall.returnValue;
- assert.include(
- dom(toast.root).textContent, 'Credentials expired.');
- assert.include(
- dom(toast.root).textContent, 'Refresh credentials');
- done();
- });
- });
+ await flush();
+ // here needs two flush as there are two chained
+ // promises on server-error handler and flush only flushes one
+ assert.equal(window.fetch.callCount, 2);
+ await flush();
+ // Sometime overlay opens with delay, waiting while open is complete
+ await openOverlaySpy.lastCall.returnValue;
+ // toast
+ toast = toastSpy.lastCall.returnValue;
+ assert.include(
+ dom(toast.root).textContent, 'Credentials expired.');
+ assert.include(
+ dom(toast.root).textContent, 'Refresh credentials');
});
test('regular toast should dismiss regular toast', () => {
// starts with authed state
element.$.restAPI.getLoggedIn();
- const toastSpy = sandbox.spy(element, '_createToastAlert');
// fake an alert
element.dispatchEvent(
@@ -378,7 +360,6 @@
test('regular toast should not dismiss auth toast', done => {
// starts with authed state
element.$.restAPI.getLoggedIn();
- const toastSpy = sandbox.spy(element, '_createToastAlert');
const responseText = Promise.resolve('Authentication required\n');
// fake auth
@@ -422,7 +403,7 @@
test('show alert', () => {
const alertObj = {message: 'foo'};
- sandbox.stub(element, '_showAlert');
+ sinon.stub(element, '_showAlert');
element.dispatchEvent(
new CustomEvent('show-alert', {
detail: alertObj,
@@ -435,9 +416,9 @@
});
test('checks stale credentials on visibility change', () => {
- const refreshStub = sandbox.stub(element,
+ const refreshStub = sinon.stub(element,
'_checkSignedIn');
- sandbox.stub(Date, 'now').returns(999999);
+ sinon.stub(Date, 'now').returns(999999);
element._lastCredentialCheck = 0;
element._handleVisibilityChange();
@@ -455,12 +436,12 @@
test('refreshes with same credentials', done => {
const accountPromise = Promise.resolve({_account_id: 1234});
- sandbox.stub(element.$.restAPI, 'getAccount')
+ sinon.stub(element.$.restAPI, 'getAccount')
.returns(accountPromise);
- const requestCheckStub = sandbox.stub(element, '_requestCheckLoggedIn');
- const handleRefreshStub = sandbox.stub(element,
+ const requestCheckStub = sinon.stub(element, '_requestCheckLoggedIn');
+ const handleRefreshStub = sinon.stub(element,
'_handleCredentialRefreshed');
- const reloadStub = sandbox.stub(element, '_reloadPage');
+ const reloadStub = sinon.stub(element, '_reloadPage');
element.knownAccountId = 1234;
element._refreshingCredentials = true;
@@ -476,15 +457,15 @@
test('_showAlert hides existing alerts', () => {
element._alertElement = element._createToastAlert();
- const hideStub = sandbox.stub(element, '_hideAlert');
+ const hideStub = sinon.stub(element, '_hideAlert');
element._showAlert();
assert.isTrue(hideStub.calledOnce);
});
test('show-error', () => {
- const openStub = sandbox.stub(element.$.errorOverlay, 'open');
- const closeStub = sandbox.stub(element.$.errorOverlay, 'close');
- const reportStub = sandbox.stub(
+ const openStub = sinon.stub(element.$.errorOverlay, 'open');
+ const closeStub = sinon.stub(element.$.errorOverlay, 'close');
+ const reportStub = sinon.stub(
element.reporting,
'reportErrorDialog'
);
@@ -512,14 +493,14 @@
test('reloads when refreshed credentials differ', done => {
const accountPromise = Promise.resolve({_account_id: 1234});
- sandbox.stub(element.$.restAPI, 'getAccount')
+ sinon.stub(element.$.restAPI, 'getAccount')
.returns(accountPromise);
- const requestCheckStub = sandbox.stub(
+ const requestCheckStub = sinon.stub(
element,
'_requestCheckLoggedIn');
- const handleRefreshStub = sandbox.stub(element,
+ const handleRefreshStub = sinon.stub(element,
'_handleCredentialRefreshed');
- const reloadStub = sandbox.stub(element, '_reloadPage');
+ const reloadStub = sinon.stub(element, '_reloadPage');
element.knownAccountId = 4321; // Different from 1234
element._refreshingCredentials = true;
@@ -535,20 +516,28 @@
});
suite('when not authed', () => {
+ let toastSpy;
setup(() => {
stub('gr-rest-api-interface', {
getLoggedIn() { return Promise.resolve(false); },
});
- element = fixture('basic');
+ element = basicFixture.instantiate();
+ toastSpy = sinon.spy(element, '_createToastAlert');
+ });
+
+ teardown(() => {
+ toastSpy.getCalls().forEach(call => {
+ call.returnValue.remove();
+ });
});
test('refresh loop continues on credential fail', done => {
- const requestCheckStub = sandbox.stub(
+ const requestCheckStub = sinon.stub(
element,
'_requestCheckLoggedIn');
- const handleRefreshStub = sandbox.stub(element,
+ const handleRefreshStub = sinon.stub(element,
'_handleCredentialRefreshed');
- const reloadStub = sandbox.stub(element, '_reloadPage');
+ const reloadStub = sinon.stub(element, '_reloadPage');
element._refreshingCredentials = true;
element._checkSignedIn();
@@ -562,4 +551,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/core/gr-key-binding-display/gr-key-binding-display.js b/polygerrit-ui/app/elements/core/gr-key-binding-display/gr-key-binding-display.js
index 5c54011..b8b414d 100644
--- a/polygerrit-ui/app/elements/core/gr-key-binding-display/gr-key-binding-display.js
+++ b/polygerrit-ui/app/elements/core/gr-key-binding-display/gr-key-binding-display.js
@@ -30,7 +30,10 @@
static get properties() {
return {
- /** @type {Array<string>} */
+ /** @type {Array<Array<string>>}
+ * Each entry in the binding represents an array that is a keyboard
+ * shortcut containing [modifier, combination]
+ */
binding: Array,
};
}
diff --git a/polygerrit-ui/app/elements/core/gr-key-binding-display/gr-key-binding-display_test.html b/polygerrit-ui/app/elements/core/gr-key-binding-display/gr-key-binding-display_test.html
deleted file mode 100644
index 8ae0f69..0000000
--- a/polygerrit-ui/app/elements/core/gr-key-binding-display/gr-key-binding-display_test.html
+++ /dev/null
@@ -1,67 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-key-binding-display</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-key-binding-display></gr-key-binding-display>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-key-binding-display.js';
-suite('gr-key-binding-display tests', () => {
- let element;
-
- setup(() => {
- element = fixture('basic');
- });
-
- suite('_computeKey', () => {
- test('unmodified key', () => {
- assert.strictEqual(element._computeKey(['x']), 'x');
- });
-
- test('key with modifiers', () => {
- assert.strictEqual(element._computeKey(['Ctrl', 'x']), 'x');
- assert.strictEqual(element._computeKey(['Shift', 'Meta', 'x']), 'x');
- });
- });
-
- suite('_computeModifiers', () => {
- test('single unmodified key', () => {
- assert.deepEqual(element._computeModifiers(['x']), []);
- });
-
- test('key with modifiers', () => {
- assert.deepEqual(element._computeModifiers(['Ctrl', 'x']), ['Ctrl']);
- assert.deepEqual(
- element._computeModifiers(['Shift', 'Meta', 'x']),
- ['Shift', 'Meta']);
- });
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/core/gr-key-binding-display/gr-key-binding-display_test.js b/polygerrit-ui/app/elements/core/gr-key-binding-display/gr-key-binding-display_test.js
new file mode 100644
index 0000000..0c25e6e
--- /dev/null
+++ b/polygerrit-ui/app/elements/core/gr-key-binding-display/gr-key-binding-display_test.js
@@ -0,0 +1,54 @@
+/**
+ * @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.
+ */
+
+import '../../../test/common-test-setup-karma.js';
+import './gr-key-binding-display.js';
+
+const basicFixture = fixtureFromElement('gr-key-binding-display');
+
+suite('gr-key-binding-display tests', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ suite('_computeKey', () => {
+ test('unmodified key', () => {
+ assert.strictEqual(element._computeKey(['x']), 'x');
+ });
+
+ test('key with modifiers', () => {
+ assert.strictEqual(element._computeKey(['Ctrl', 'x']), 'x');
+ assert.strictEqual(element._computeKey(['Shift', 'Meta', 'x']), 'x');
+ });
+ });
+
+ suite('_computeModifiers', () => {
+ test('single unmodified key', () => {
+ assert.deepEqual(element._computeModifiers(['x']), []);
+ });
+
+ test('key with modifiers', () => {
+ assert.deepEqual(element._computeModifiers(['Ctrl', 'x']), ['Ctrl']);
+ assert.deepEqual(
+ element._computeModifiers(['Shift', 'Meta', 'x']),
+ ['Shift', 'Meta']);
+ });
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog.js b/polygerrit-ui/app/elements/core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog.js
index 0c0daea..eeeb86b 100644
--- a/polygerrit-ui/app/elements/core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog.js
+++ b/polygerrit-ui/app/elements/core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog.js
@@ -47,22 +47,6 @@
return {
_left: Array,
_right: Array,
-
- _propertyBySection: {
- type: Object,
- value() {
- return {
- [ShortcutSection.EVERYWHERE]: '_everywhere',
- [ShortcutSection.NAVIGATION]: '_navigation',
- [ShortcutSection.DASHBOARD]: '_dashboard',
- [ShortcutSection.CHANGE_LIST]: '_changeList',
- [ShortcutSection.ACTIONS]: '_actions',
- [ShortcutSection.REPLY_DIALOG]: '_replyDialog',
- [ShortcutSection.FILE_LIST]: '_fileList',
- [ShortcutSection.DIFFS]: '_diffs',
- };
- },
- },
};
}
@@ -75,15 +59,17 @@
/** @override */
attached() {
super.attached();
+ this.keyboardShortcutDirectoryListener =
+ this._onDirectoryUpdated.bind(this);
this.addKeyboardShortcutDirectoryListener(
- this._onDirectoryUpdated.bind(this));
+ this.keyboardShortcutDirectoryListener);
}
/** @override */
detached() {
super.detached();
this.removeKeyboardShortcutDirectoryListener(
- this._onDirectoryUpdated.bind(this));
+ this.keyboardShortcutDirectoryListener);
}
_handleCloseTap(e) {
diff --git a/polygerrit-ui/app/elements/core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog_test.html b/polygerrit-ui/app/elements/core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog_test.js
similarity index 75%
rename from polygerrit-ui/app/elements/core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog_test.html
rename to polygerrit-ui/app/elements/core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog_test.js
index 1b5cd0f..2e6f5d3 100644
--- a/polygerrit-ui/app/elements/core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog_test.html
+++ b/polygerrit-ui/app/elements/core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog_test.js
@@ -1,45 +1,32 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2018 The Android Open Source Project
+/**
+ * @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.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-key-binding-display</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-keyboard-shortcuts-dialog></gr-keyboard-shortcuts-dialog>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-keyboard-shortcuts-dialog.js';
import {KeyboardShortcutBinder} from '../../../behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.js';
+
+const basicFixture = fixtureFromElement('gr-keyboard-shortcuts-dialog');
+
suite('gr-keyboard-shortcuts-dialog tests', () => {
const kb = KeyboardShortcutBinder;
let element;
setup(() => {
- element = fixture('basic');
+ element = basicFixture.instantiate();
});
function update(directory) {
@@ -177,5 +164,4 @@
});
});
});
-</script>
diff --git a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.js b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.js
index 684b472..8bc1870 100644
--- a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.js
+++ b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.js
@@ -196,7 +196,7 @@
adminLinks,
topMenus,
docBaseUrl,
- ].some(arg => arg === undefined)) {
+ ].includes(undefined)) {
return undefined;
}
diff --git a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header_test.html b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header_test.js
similarity index 87%
rename from polygerrit-ui/app/elements/core/gr-main-header/gr-main-header_test.html
rename to polygerrit-ui/app/elements/core/gr-main-header/gr-main-header_test.js
index 336d873..b3ac40f 100644
--- a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header_test.html
+++ b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header_test.js
@@ -1,45 +1,29 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-main-header</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-main-header></gr-main-header>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-main-header.js';
+
+const basicFixture = fixtureFromElement('gr-main-header');
+
suite('gr-main-header tests', () => {
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
stub('gr-rest-api-interface', {
getConfig() { return Promise.resolve({}); },
probePath(path) { return Promise.resolve(false); },
@@ -47,11 +31,7 @@
stub('gr-main-header', {
_loadAccount() {},
});
- element = fixture('basic');
- });
-
- teardown(() => {
- sandbox.restore();
+ element = basicFixture.instantiate();
});
test('link visibility', () => {
@@ -407,4 +387,4 @@
assert.equal(element._registerText, 'Sign up');
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.js b/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.js
index 69e2989..2f32706 100644
--- a/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.js
+++ b/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.js
@@ -102,12 +102,21 @@
suffixForDashboard: 'limit:10',
},
{
+ // Changes where the user is in the attention set.
+ name: 'Your Turn',
+ query: 'attention:${user}',
+ hideIfEmpty: false,
+ suffixForDashboard: 'limit:25',
+ attentionSetOnly: true,
+ },
+ {
// Changes that are assigned to the viewed user.
name: 'Assigned reviews',
query: 'assignee:${user} (-is:wip OR owner:self OR assignee:self) ' +
'is:open -is:ignored',
hideIfEmpty: true,
suffixForDashboard: 'limit:25',
+ assigneeOnly: true,
},
{
// WIP open changes owned by viewing user. This section is omitted when
@@ -462,11 +471,12 @@
* @param {{ _number: number, project: string }} change The change object.
* @param {string} path The file path.
* @param {number=} opt_patchNum
+ * @param {number=} opt_lineNum
* @return {string}
*/
- getEditUrlForDiff(change, path, opt_patchNum) {
+ getEditUrlForDiff(change, path, opt_patchNum, opt_lineNum) {
return this.getEditUrlForDiffById(change._number, change.project, path,
- opt_patchNum);
+ opt_patchNum, opt_lineNum);
},
/**
@@ -475,15 +485,17 @@
* @param {string} path The file path.
* @param {number|string=} opt_patchNum The patchNum the file content
* should be based on, or ${EDIT_PATCHNUM} if left undefined.
+ * @param {number=} opt_lineNum The line number to pass to the inline editor.
* @return {string}
*/
- getEditUrlForDiffById(changeNum, project, path, opt_patchNum) {
+ getEditUrlForDiffById(changeNum, project, path, opt_patchNum, opt_lineNum) {
return this._getUrlFor({
view: GerritNav.View.EDIT,
changeNum,
project,
path,
patchNum: opt_patchNum || EDIT_PATCHNUM,
+ lineNum: opt_lineNum,
});
},
@@ -730,8 +742,14 @@
},
getUserDashboard(user = 'self', sections = DEFAULT_SECTIONS,
- title = '') {
+ title = '', config = {}) {
+ const attentionEnabled =
+ config.change && !!config.change.enable_attention_set;
+ const assigneeEnabled =
+ config.change && !!config.change.enable_assignee;
sections = sections
+ .filter(section => (attentionEnabled || !section.attentionSetOnly))
+ .filter(section => (assigneeEnabled || !section.assigneeOnly))
.filter(section => (user === 'self' || !section.selfOnly))
.map(section => Object.assign({}, section, {
name: section.name,
diff --git a/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation_test.html b/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation_test.js
similarity index 62%
rename from polygerrit-ui/app/elements/core/gr-navigation/gr-navigation_test.html
rename to polygerrit-ui/app/elements/core/gr-navigation/gr-navigation_test.js
index 8fc4c75..93a1e9e 100644
--- a/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation_test.html
+++ b/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation_test.js
@@ -1,31 +1,21 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-navigation</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import {GerritNav} from './gr-navigation.js';
suite('gr-navigation tests', () => {
@@ -85,4 +75,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/core/gr-router/gr-router.js b/polygerrit-ui/app/elements/core/gr-router/gr-router.js
index c1cf169..b60f47e 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router.js
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router.js
@@ -331,7 +331,7 @@
}
_firstCodeBrowserWeblink(weblinks) {
- // This is an ordered whitelist of web link types that provide direct
+ // This is an ordered allowed list of web link types that provide direct
// links to the commit in the url property.
const codeBrowserLinks = ['gitiles', 'browse', 'gitweb'];
for (let i = 0; i < codeBrowserLinks.length; i++) {
diff --git a/polygerrit-ui/app/elements/core/gr-router/gr-router_test.html b/polygerrit-ui/app/elements/core/gr-router/gr-router_test.js
similarity index 91%
rename from polygerrit-ui/app/elements/core/gr-router/gr-router_test.html
rename to polygerrit-ui/app/elements/core/gr-router/gr-router_test.js
index b5bfd4e..b53b269 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router_test.html
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router_test.js
@@ -1,53 +1,34 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-router</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-router></gr-router>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-router.js';
import page from 'page/page.mjs';
import {GerritNav} from '../gr-navigation/gr-navigation.js';
+const basicFixture = fixtureFromElement('gr-router');
+
suite('gr-router tests', () => {
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
+ element = basicFixture.instantiate();
});
- teardown(() => { sandbox.restore(); });
-
test('_firstCodeBrowserWeblink', () => {
assert.deepEqual(element._firstCodeBrowserWeblink([
{name: 'gitweb'},
@@ -65,7 +46,7 @@
const link = {name: 'test', url: 'test/url'};
const weblinks = [browserLink, link];
const config = {gerrit: {primary_weblink_name: browserLink.name}};
- sandbox.stub(element, '_firstCodeBrowserWeblink').returns(link);
+ sinon.stub(element, '_firstCodeBrowserWeblink').returns(link);
assert.deepEqual(element._getBrowseCommitWeblink(weblinks, config),
browserLink);
@@ -77,7 +58,7 @@
const link = {name: 'test', url: 'test/url'};
const browserLink = {name: 'browser', url: 'browser/url'};
const mapLinksToConfig = weblinks => { return {options: {weblinks}}; };
- sandbox.stub(element, '_getBrowseCommitWeblink').returns(browserLink);
+ sinon.stub(element, '_getBrowseCommitWeblink').returns(browserLink);
assert.deepEqual(
element._getChangeWeblinks(mapLinksToConfig([link, browserLink]))[0],
@@ -152,16 +133,17 @@
const requiresAuth = {};
const doesNotRequireAuth = {};
- sandbox.stub(GerritNav, 'setup');
- sandbox.stub(page, 'start');
- sandbox.stub(page, 'base');
- sandbox.stub(element, '_mapRoute', (pattern, methodName, usesAuth) => {
- if (usesAuth) {
- requiresAuth[methodName] = true;
- } else {
- doesNotRequireAuth[methodName] = true;
- }
- });
+ sinon.stub(GerritNav, 'setup');
+ sinon.stub(page, 'start');
+ sinon.stub(page, 'base');
+ sinon.stub(element, '_mapRoute').callsFake(
+ (pattern, methodName, usesAuth) => {
+ if (usesAuth) {
+ requiresAuth[methodName] = true;
+ } else {
+ doesNotRequireAuth[methodName] = true;
+ }
+ });
element._startRouter();
const actualRequiresAuth = Object.keys(requiresAuth);
@@ -242,19 +224,19 @@
});
test('_redirectIfNotLoggedIn while logged in', () => {
- sandbox.stub(element.$.restAPI, 'getLoggedIn')
+ sinon.stub(element.$.restAPI, 'getLoggedIn')
.returns(Promise.resolve(true));
const data = {canonicalPath: ''};
- const redirectStub = sandbox.stub(element, '_redirectToLogin');
+ const redirectStub = sinon.stub(element, '_redirectToLogin');
return element._redirectIfNotLoggedIn(data).then(() => {
assert.isFalse(redirectStub.called);
});
});
test('_redirectIfNotLoggedIn while logged out', () => {
- sandbox.stub(element.$.restAPI, 'getLoggedIn')
+ sinon.stub(element.$.restAPI, 'getLoggedIn')
.returns(Promise.resolve(false));
- const redirectStub = sandbox.stub(element, '_redirectToLogin');
+ const redirectStub = sinon.stub(element, '_redirectToLogin');
const data = {canonicalPath: ''};
return new Promise(resolve => {
element._redirectIfNotLoggedIn(data)
@@ -535,9 +517,9 @@
let projectLookupStub;
setup(() => {
- projectLookupStub = sandbox
+ projectLookupStub = sinon
.stub(element.$.restAPI, 'getFromProjectLookup');
- sandbox.stub(element, '_generateUrl');
+ sinon.stub(element, '_generateUrl');
});
suite('_normalizeLegacyRouteParams', () => {
@@ -546,10 +528,10 @@
let show404Stub;
setup(() => {
- rangeStub = sandbox.stub(element, '_normalizePatchRangeParams')
+ rangeStub = sinon.stub(element, '_normalizePatchRangeParams')
.returns(Promise.resolve());
- redirectStub = sandbox.stub(element, '_redirect');
- show404Stub = sandbox.stub(element, '_show404');
+ redirectStub = sinon.stub(element, '_redirect');
+ show404Stub = sinon.stub(element, '_show404');
});
test('w/o changeNum', () => {
@@ -622,9 +604,9 @@
}
setup(() => {
- redirectStub = sandbox.stub(element, '_redirect');
- setParamsStub = sandbox.stub(element, '_setParams');
- handlePassThroughRoute = sandbox.stub(element, '_handlePassThroughRoute');
+ redirectStub = sinon.stub(element, '_redirect');
+ setParamsStub = sinon.stub(element, '_setParams');
+ handlePassThroughRoute = sinon.stub(element, '_handlePassThroughRoute');
});
test('_handleAgreementsRoute', () => {
@@ -679,10 +661,10 @@
const onRegisteringExit = (match, _onExit) => {
onExit = _onExit;
};
- sandbox.stub(page, 'exit', onRegisteringExit);
- sandbox.stub(GerritNav, 'setup');
- sandbox.stub(page, 'start');
- sandbox.stub(page, 'base');
+ sinon.stub(page, 'exit').callsFake( onRegisteringExit);
+ sinon.stub(GerritNav, 'setup');
+ sinon.stub(page, 'start');
+ sinon.stub(page, 'base');
element._startRouter();
const appElementStub = {dispatchEvent: sinon.stub()};
@@ -704,7 +686,7 @@
redirectStub.lastCall.args[0],
'/c/test/+/42');
- sandbox.stub(element, '_getHashFromCanonicalPath').returns('foo');
+ sinon.stub(element, '_getHashFromCanonicalPath').returns('foo');
element._handleImproperlyEncodedPlusRoute(
{canonicalPath: '/c/test/%20/42', params: ['test', '42']});
assert.equal(
@@ -779,7 +761,7 @@
suite('_handleRootRoute', () => {
test('closes for closeAfterLogin', () => {
const data = {querystring: 'closeAfterLogin', canonicalPath: ''};
- const closeStub = sandbox.stub(window, 'close');
+ const closeStub = sinon.stub(window, 'close');
const result = element._handleRootRoute(data);
assert.isNotOk(result);
assert.isTrue(closeStub.called);
@@ -787,7 +769,7 @@
});
test('redirects to dashboard if logged in', () => {
- sandbox.stub(element.$.restAPI, 'getLoggedIn')
+ sinon.stub(element.$.restAPI, 'getLoggedIn')
.returns(Promise.resolve(true));
const data = {
canonicalPath: '/', path: '/', querystring: '', hash: '',
@@ -800,7 +782,7 @@
});
test('redirects to open changes if not logged in', () => {
- sandbox.stub(element.$.restAPI, 'getLoggedIn')
+ sinon.stub(element.$.restAPI, 'getLoggedIn')
.returns(Promise.resolve(false));
const data = {
canonicalPath: '/', path: '/', querystring: '', hash: '',
@@ -856,7 +838,7 @@
querystring: '',
hash: '/foo/bar',
};
- sandbox.stub(element, 'getBaseUrl').returns('/baz');
+ sinon.stub(element, 'getBaseUrl').returns('/baz');
const result = element._handleRootRoute(data);
assert.isNotOk(result);
assert.isTrue(redirectStub.called);
@@ -894,11 +876,11 @@
let redirectToLoginStub;
setup(() => {
- redirectToLoginStub = sandbox.stub(element, '_redirectToLogin');
+ redirectToLoginStub = sinon.stub(element, '_redirectToLogin');
});
test('own dashboard but signed out redirects to login', () => {
- sandbox.stub(element.$.restAPI, 'getLoggedIn')
+ sinon.stub(element.$.restAPI, 'getLoggedIn')
.returns(Promise.resolve(false));
const data = {canonicalPath: '/dashboard/', params: {0: 'seLF'}};
return element._handleDashboardRoute(data, '').then(() => {
@@ -909,7 +891,7 @@
});
test('non-self dashboard but signed out does not redirect', () => {
- sandbox.stub(element.$.restAPI, 'getLoggedIn')
+ sinon.stub(element.$.restAPI, 'getLoggedIn')
.returns(Promise.resolve(false));
const data = {canonicalPath: '/dashboard/', params: {0: 'foo'}};
return element._handleDashboardRoute(data, '').then(() => {
@@ -921,7 +903,7 @@
});
test('dashboard while signed in sets params', () => {
- sandbox.stub(element.$.restAPI, 'getLoggedIn')
+ sinon.stub(element.$.restAPI, 'getLoggedIn')
.returns(Promise.resolve(true));
const data = {canonicalPath: '/dashboard/', params: {0: 'foo'}};
return element._handleDashboardRoute(data, '').then(() => {
@@ -940,7 +922,7 @@
let redirectToLoginStub;
setup(() => {
- redirectToLoginStub = sandbox.stub(element, '_redirectToLogin');
+ redirectToLoginStub = sinon.stub(element, '_redirectToLogin');
});
test('no user specified', () => {
@@ -1347,7 +1329,7 @@
});
test('_handleChangeLegacyRoute', () => {
- const normalizeRouteStub = sandbox.stub(element,
+ const normalizeRouteStub = sinon.stub(element,
'_normalizeLegacyRouteParams');
const ctx = {
params: [
@@ -1372,7 +1354,7 @@
});
test('_handleDiffLegacyRoute', () => {
- const normalizeRouteStub = sandbox.stub(element,
+ const normalizeRouteStub = sinon.stub(element,
'_normalizeLegacyRouteParams');
const ctx = {
params: [
@@ -1435,14 +1417,14 @@
}
setup(() => {
- normalizeRangeStub = sandbox.stub(element,
+ normalizeRangeStub = sinon.stub(element,
'_normalizePatchRangeParams');
- sandbox.stub(element.$.restAPI, 'setInProjectLookup');
+ sinon.stub(element.$.restAPI, 'setInProjectLookup');
});
test('needs redirect', () => {
normalizeRangeStub.returns(true);
- sandbox.stub(element, '_generateUrl').returns('foo');
+ sinon.stub(element, '_generateUrl').returns('foo');
const ctx = makeParams(null, '');
element._handleChangeRoute(ctx);
assert.isTrue(normalizeRangeStub.called);
@@ -1453,7 +1435,7 @@
test('change view', () => {
normalizeRangeStub.returns(false);
- sandbox.stub(element, '_generateUrl').returns('foo');
+ sinon.stub(element, '_generateUrl').returns('foo');
const ctx = makeParams(null, '');
assertDataToParams(ctx, '_handleChangeRoute', {
view: GerritNav.View.CHANGE,
@@ -1489,14 +1471,14 @@
}
setup(() => {
- normalizeRangeStub = sandbox.stub(element,
+ normalizeRangeStub = sinon.stub(element,
'_normalizePatchRangeParams');
- sandbox.stub(element.$.restAPI, 'setInProjectLookup');
+ sinon.stub(element.$.restAPI, 'setInProjectLookup');
});
test('needs redirect', () => {
normalizeRangeStub.returns(true);
- sandbox.stub(element, '_generateUrl').returns('foo');
+ sinon.stub(element, '_generateUrl').returns('foo');
const ctx = makeParams(null, '');
element._handleDiffRoute(ctx);
assert.isTrue(normalizeRangeStub.called);
@@ -1507,7 +1489,7 @@
test('diff view', () => {
normalizeRangeStub.returns(false);
- sandbox.stub(element, '_generateUrl').returns('foo');
+ sinon.stub(element, '_generateUrl').returns('foo');
const ctx = makeParams('foo/bar/baz', 'b44');
assertDataToParams(ctx, '_handleDiffRoute', {
view: GerritNav.View.DIFF,
@@ -1526,8 +1508,8 @@
test('_handleDiffEditRoute', () => {
const normalizeRangeSpy =
- sandbox.spy(element, '_normalizePatchRangeParams');
- sandbox.stub(element.$.restAPI, 'setInProjectLookup');
+ sinon.spy(element, '_normalizePatchRangeParams');
+ sinon.stub(element.$.restAPI, 'setInProjectLookup');
const ctx = {
params: [
'foo/bar', // 0 Project
@@ -1555,8 +1537,8 @@
test('_handleDiffEditRoute with lineNum', () => {
const normalizeRangeSpy =
- sandbox.spy(element, '_normalizePatchRangeParams');
- sandbox.stub(element.$.restAPI, 'setInProjectLookup');
+ sinon.spy(element, '_normalizePatchRangeParams');
+ sinon.stub(element.$.restAPI, 'setInProjectLookup');
const ctx = {
params: [
'foo/bar', // 0 Project
@@ -1585,8 +1567,8 @@
test('_handleChangeEditRoute', () => {
const normalizeRangeSpy =
- sandbox.spy(element, '_normalizePatchRangeParams');
- sandbox.stub(element.$.restAPI, 'setInProjectLookup');
+ sinon.spy(element, '_normalizePatchRangeParams');
+ sinon.stub(element.$.restAPI, 'setInProjectLookup');
const ctx = {
params: [
'foo/bar', // 0 Project
@@ -1649,4 +1631,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar_test.html b/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar_test.js
similarity index 70%
rename from polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar_test.html
rename to polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar_test.js
index 9e5fdfe..9529f9b 100644
--- a/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar_test.html
+++ b/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar_test.js
@@ -1,57 +1,42 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2015 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-search-bar</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<script src="/node_modules/page/page.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-search-bar></gr-search-bar>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-search-bar.js';
import '../../../scripts/util.js';
-import {KeyboardShortcutBinder} from '../../../behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.js';
+import {TestKeyboardShortcutBinder} from '../../../test/test-utils.js';
+
+const basicFixture = fixtureFromElement('gr-search-bar');
+
suite('gr-search-bar tests', () => {
- const kb = KeyboardShortcutBinder;
- kb.bindShortcut(kb.Shortcut.SEARCH, '/');
-
let element;
- let sandbox;
- setup(done => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- flush(done);
+ suiteSetup(() => {
+ const kb = TestKeyboardShortcutBinder.push();
+ kb.bindShortcut(kb.Shortcut.SEARCH, '/');
});
- teardown(() => {
- sandbox.restore();
+ suiteTeardown(() => {
+ TestKeyboardShortcutBinder.pop();
+ });
+
+ setup(done => {
+ element = basicFixture.instantiate();
+ flush(done);
});
test('value is propagated to _inputVal', () => {
@@ -75,7 +60,7 @@
});
test('input blurred after commit', () => {
- const blurSpy = sandbox.spy(element.$.searchInput.$.input, 'blur');
+ const blurSpy = sinon.spy(element.$.searchInput.$.input, 'blur');
element.$.searchInput.text = 'fate/stay';
MockInteractions.pressAndReleaseKeyOn(element.$.searchInput.$.input, 13,
null, 'enter');
@@ -83,7 +68,7 @@
});
test('empty search query does not trigger nav', () => {
- const searchSpy = sandbox.spy();
+ const searchSpy = sinon.spy();
element.addEventListener('handle-search', searchSpy);
element.value = '';
MockInteractions.pressAndReleaseKeyOn(element.$.searchInput.$.input, 13,
@@ -92,7 +77,7 @@
});
test('Predefined query op with no predication doesnt trigger nav', () => {
- const searchSpy = sandbox.spy();
+ const searchSpy = sinon.spy();
element.addEventListener('handle-search', searchSpy);
element.value = 'added:';
MockInteractions.pressAndReleaseKeyOn(element.$.searchInput.$.input, 13,
@@ -101,7 +86,7 @@
});
test('predefined predicate query triggers nav', () => {
- const searchSpy = sandbox.spy();
+ const searchSpy = sinon.spy();
element.addEventListener('handle-search', searchSpy);
element.value = 'age:1week';
MockInteractions.pressAndReleaseKeyOn(element.$.searchInput.$.input, 13,
@@ -110,7 +95,7 @@
});
test('undefined predicate query triggers nav', () => {
- const searchSpy = sandbox.spy();
+ const searchSpy = sinon.spy();
element.addEventListener('handle-search', searchSpy);
element.value = 'random:1week';
MockInteractions.pressAndReleaseKeyOn(element.$.searchInput.$.input, 13,
@@ -119,7 +104,7 @@
});
test('empty undefined predicate query triggers nav', () => {
- const searchSpy = sandbox.spy();
+ const searchSpy = sinon.spy();
element.addEventListener('handle-search', searchSpy);
element.value = 'random:';
MockInteractions.pressAndReleaseKeyOn(element.$.searchInput.$.input, 13,
@@ -128,8 +113,8 @@
});
test('keyboard shortcuts', () => {
- const focusSpy = sandbox.spy(element.$.searchInput, 'focus');
- const selectAllSpy = sandbox.spy(element.$.searchInput, 'selectAll');
+ const focusSpy = sinon.spy(element.$.searchInput, 'focus');
+ const selectAllSpy = sinon.spy(element.$.searchInput, 'selectAll');
MockInteractions.pressAndReleaseKeyOn(document.body, 191, null, '/');
assert.isTrue(focusSpy.called);
assert.isTrue(selectAllSpy.called);
@@ -137,7 +122,7 @@
suite('_getSearchSuggestions', () => {
test('Autocompletes accounts', () => {
- sandbox.stub(element, 'accountSuggestions', () =>
+ sinon.stub(element, 'accountSuggestions').callsFake(() =>
Promise.resolve([{text: 'owner:fred@goog.co'}])
);
return element._getSearchSuggestions('owner:fr').then(s => {
@@ -146,7 +131,7 @@
});
test('Autocompletes groups', done => {
- sandbox.stub(element, 'groupSuggestions', () =>
+ sinon.stub(element, 'groupSuggestions').callsFake(() =>
Promise.resolve([
{text: 'ownerin:Polygerrit'},
{text: 'ownerin:gerrit'},
@@ -159,7 +144,7 @@
});
test('Autocompletes projects', done => {
- sandbox.stub(element, 'projectSuggestions', () =>
+ sinon.stub(element, 'projectSuggestions').callsFake(() =>
Promise.resolve([
{text: 'project:Polygerrit'},
{text: 'project:gerrit'},
@@ -213,7 +198,7 @@
},
});
- element = fixture('basic');
+ element = basicFixture.instantiate();
flush(done);
});
@@ -230,4 +215,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/core/gr-smart-search/gr-smart-search_test.html b/polygerrit-ui/app/elements/core/gr-smart-search/gr-smart-search_test.js
similarity index 60%
rename from polygerrit-ui/app/elements/core/gr-smart-search/gr-smart-search_test.html
rename to polygerrit-ui/app/elements/core/gr-smart-search/gr-smart-search_test.js
index 87dfaf4..dc7bf0e 100644
--- a/polygerrit-ui/app/elements/core/gr-smart-search/gr-smart-search_test.html
+++ b/polygerrit-ui/app/elements/core/gr-smart-search/gr-smart-search_test.js
@@ -1,54 +1,34 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-smart-search</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-smart-search></gr-smart-search>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-smart-search.js';
+
+const basicFixture = fixtureFromElement('gr-smart-search');
+
suite('gr-smart-search tests', () => {
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- });
-
- teardown(() => {
- sandbox.restore();
+ element = basicFixture.instantiate();
});
test('Autocompletes accounts', () => {
- sandbox.stub(element.$.restAPI, 'getSuggestedAccounts', () =>
+ sinon.stub(element.$.restAPI, 'getSuggestedAccounts').callsFake(() =>
Promise.resolve([
{
name: 'fred',
@@ -62,7 +42,7 @@
});
test('Inserts self as option when valid', () => {
- sandbox.stub(element.$.restAPI, 'getSuggestedAccounts', () =>
+ sinon.stub(element.$.restAPI, 'getSuggestedAccounts').callsFake( () =>
Promise.resolve([
{
name: 'fred',
@@ -82,7 +62,7 @@
});
test('Inserts me as option when valid', () => {
- sandbox.stub(element.$.restAPI, 'getSuggestedAccounts', () =>
+ sinon.stub(element.$.restAPI, 'getSuggestedAccounts').callsFake( () =>
Promise.resolve([
{
name: 'fred',
@@ -102,7 +82,7 @@
});
test('Autocompletes groups', () => {
- sandbox.stub(element.$.restAPI, 'getSuggestedGroups', () =>
+ sinon.stub(element.$.restAPI, 'getSuggestedGroups').callsFake( () =>
Promise.resolve({
Polygerrit: 0,
gerrit: 0,
@@ -115,7 +95,7 @@
});
test('Autocompletes projects', () => {
- sandbox.stub(element.$.restAPI, 'getSuggestedProjects', () =>
+ sinon.stub(element.$.restAPI, 'getSuggestedProjects').callsFake( () =>
Promise.resolve({Polygerrit: 0}));
return element._fetchProjects('project', 'pol').then(s => {
assert.deepEqual(s[0], {text: 'project:Polygerrit'});
@@ -123,7 +103,7 @@
});
test('Autocomplete doesnt override exact matches to input', () => {
- sandbox.stub(element.$.restAPI, 'getSuggestedGroups', () =>
+ sinon.stub(element.$.restAPI, 'getSuggestedGroups').callsFake( () =>
Promise.resolve({
Polygerrit: 0,
gerrit: 0,
@@ -138,7 +118,7 @@
});
test('Autocompletes accounts with no email', () => {
- sandbox.stub(element.$.restAPI, 'getSuggestedAccounts', () =>
+ sinon.stub(element.$.restAPI, 'getSuggestedAccounts').callsFake( () =>
Promise.resolve([{name: 'fred'}]));
return element._fetchAccounts('owner', 'fr').then(s => {
assert.deepEqual(s[0], {text: 'owner:"fred"', label: 'fred'});
@@ -146,11 +126,11 @@
});
test('Autocompletes accounts with email', () => {
- sandbox.stub(element.$.restAPI, 'getSuggestedAccounts', () =>
+ sinon.stub(element.$.restAPI, 'getSuggestedAccounts').callsFake( () =>
Promise.resolve([{email: 'fred@goog.co'}]));
return element._fetchAccounts('owner', 'fr').then(s => {
assert.deepEqual(s[0], {text: 'owner:fred@goog.co', label: ''});
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/custom-dark-theme_test.html b/polygerrit-ui/app/elements/custom-dark-theme_test.html
deleted file mode 100644
index 6ac9c20..0000000
--- a/polygerrit-ui/app/elements/custom-dark-theme_test.html
+++ /dev/null
@@ -1,103 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-app-it_test</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="element">
- <template>
- <gr-app id="app"></gr-app>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../test/common-test-setup.js';
-import './gr-app.js';
-import {util} from '../scripts/util.js';
-import {pluginLoader} from './shared/gr-js-api-interface/gr-plugin-loader.js';
-
-suite('gr-app custom dark theme tests', () => {
- let sandbox;
- let element;
-
- setup(done => {
- sandbox = sinon.sandbox.create();
- stub('gr-reporting', {
- appStarted: sandbox.stub(),
- });
- stub('gr-account-dropdown', {
- _getTopContent: sinon.stub(),
- });
- stub('gr-rest-api-interface', {
- getAccount() { return Promise.resolve(null); },
- getAccountCapabilities() { return Promise.resolve({}); },
- getConfig() {
- return Promise.resolve({
- plugin: {
- js_resource_paths: [],
- html_resource_paths: [
- new URL('test/plugin.html', window.location.href).toString(),
- ],
- },
- });
- },
- getVersion() { return Promise.resolve(42); },
- getLoggedIn() { return Promise.resolve(false); },
- });
-
- window.localStorage.setItem('dark-theme', 'true');
-
- element = fixture('element');
-
- const importSpy = sandbox.spy(
- element.$['app-element'].$.externalStyleForAll,
- '_import');
- const importForThemeSpy = sandbox.spy(
- element.$['app-element'].$.externalStyleForTheme,
- '_import');
- pluginLoader.awaitPluginsLoaded().then(() => {
- Promise.all(importSpy.returnValues.concat(importForThemeSpy.returnValues))
- .then(() => {
- flush(done);
- });
- });
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('applies the right theme', () => {
- assert.equal(
- util.getComputedStyleValue('--primary-text-color', element),
- 'red');
- assert.equal(
- util.getComputedStyleValue('--header-background-color', element),
- 'black');
- assert.equal(
- util.getComputedStyleValue('--footer-background-color', element),
- 'yellow');
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/custom-dark-theme_test.js b/polygerrit-ui/app/elements/custom-dark-theme_test.js
new file mode 100644
index 0000000..d4f790f
--- /dev/null
+++ b/polygerrit-ui/app/elements/custom-dark-theme_test.js
@@ -0,0 +1,63 @@
+/**
+ * @license
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import '../test/common-test-setup-karma.js';
+import {getComputedStyleValue} from '../utils/dom-util.js';
+import './shared/gr-rest-api-interface/gr-rest-api-interface.js';
+import './gr-app.js';
+import {pluginLoader} from './shared/gr-js-api-interface/gr-plugin-loader.js';
+import {removeTheme} from '../styles/themes/dark-theme.js';
+
+const basicFixture = fixtureFromElement('gr-app');
+
+suite('gr-app custom dark theme tests', () => {
+ let element;
+ setup(done => {
+ window.localStorage.setItem('dark-theme', 'true');
+
+ element = basicFixture.instantiate();
+ pluginLoader.loadPlugins([]);
+ pluginLoader.awaitPluginsLoaded().then(() => flush(done));
+ });
+
+ teardown(() => {
+ window.localStorage.removeItem('dark-theme');
+ removeTheme();
+ // The app sends requests to server. This can lead to
+ // unexpected gr-alert elements in document.body
+ document.body.querySelectorAll('gr-alert').forEach(grAlert => {
+ grAlert.remove();
+ });
+ });
+
+ test('should tried to load dark theme', () => {
+ assert.isTrue(
+ !!document.head.querySelector('#dark-theme')
+ );
+ });
+
+ test('applies the right theme', () => {
+ assert.equal(
+ getComputedStyleValue('--header-background-color', element)
+ .toLowerCase(),
+ '#3b3d3f');
+ assert.equal(
+ getComputedStyleValue('--footer-background-color', element)
+ .toLowerCase(),
+ '#3b3d3f');
+ });
+});
diff --git a/polygerrit-ui/app/elements/custom-light-theme_test.html b/polygerrit-ui/app/elements/custom-light-theme_test.html
deleted file mode 100644
index f8a749c..0000000
--- a/polygerrit-ui/app/elements/custom-light-theme_test.html
+++ /dev/null
@@ -1,103 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-app-it_test</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="element">
- <template>
- <gr-app id="app"></gr-app>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../test/common-test-setup.js';
-import './gr-app.js';
-import {util} from '../scripts/util.js';
-import {pluginLoader} from './shared/gr-js-api-interface/gr-plugin-loader.js';
-
-suite('gr-app custom light theme tests', () => {
- let sandbox;
- let element;
-
- setup(done => {
- sandbox = sinon.sandbox.create();
- stub('gr-reporting', {
- appStarted: sandbox.stub(),
- });
- stub('gr-account-dropdown', {
- _getTopContent: sinon.stub(),
- });
- stub('gr-rest-api-interface', {
- getAccount() { return Promise.resolve(null); },
- getAccountCapabilities() { return Promise.resolve({}); },
- getConfig() {
- return Promise.resolve({
- plugin: {
- js_resource_paths: [],
- html_resource_paths: [
- new URL('test/plugin.html', window.location.href).toString(),
- ],
- },
- });
- },
- getVersion() { return Promise.resolve(42); },
- getLoggedIn() { return Promise.resolve(false); },
- });
-
- window.localStorage.removeItem('dark-theme');
-
- element = fixture('element');
-
- const importSpy = sandbox.spy(
- element.$['app-element'].$.externalStyleForAll,
- '_import');
- const importForThemeSpy = sandbox.spy(
- element.$['app-element'].$.externalStyleForTheme,
- '_import');
- pluginLoader.awaitPluginsLoaded().then(() => {
- Promise.all(importSpy.returnValues.concat(importForThemeSpy.returnValues))
- .then(() => {
- flush(done);
- });
- });
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('applies the right theme', () => {
- assert.equal(
- util.getComputedStyleValue('--primary-text-color', element),
- '#F00BAA');
- assert.equal(
- util.getComputedStyleValue('--header-background-color', element),
- '#F01BAA');
- assert.equal(
- util.getComputedStyleValue('--footer-background-color', element),
- '#F02BAA');
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/custom-light-theme_test.js b/polygerrit-ui/app/elements/custom-light-theme_test.js
new file mode 100644
index 0000000..5c0cf28
--- /dev/null
+++ b/polygerrit-ui/app/elements/custom-light-theme_test.js
@@ -0,0 +1,65 @@
+/**
+ * @license
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import '../test/common-test-setup-karma.js';
+import {getComputedStyleValue} from '../utils/dom-util.js';
+import './shared/gr-rest-api-interface/gr-rest-api-interface.js';
+import './gr-app.js';
+import {pluginLoader} from './shared/gr-js-api-interface/gr-plugin-loader.js';
+
+const basicFixture = fixtureFromElement('gr-app');
+
+suite('gr-app custom light theme tests', () => {
+ let element;
+ setup(done => {
+ window.localStorage.removeItem('dark-theme');
+ stub('gr-rest-api-interface', {
+ getConfig() { return Promise.resolve({test: 'config'}); },
+ getAccount() { return Promise.resolve({}); },
+ getDiffComments() { return Promise.resolve({}); },
+ getDiffRobotComments() { return Promise.resolve({}); },
+ getDiffDrafts() { return Promise.resolve({}); },
+ _fetchSharedCacheURL() { return Promise.resolve({}); },
+ });
+ element = basicFixture.instantiate();
+ pluginLoader.loadPlugins([]);
+ pluginLoader.awaitPluginsLoaded().then(() => flush(done));
+ });
+ teardown(() => {
+ // The app sends requests to server. This can lead to
+ // unexpected gr-alert elements in document.body
+ document.body.querySelectorAll('gr-alert').forEach(grAlert => {
+ grAlert.remove();
+ });
+ });
+
+ test('should not load dark theme', () => {
+ assert.isFalse(!!document.head.querySelector('#dark-theme'));
+ assert.isTrue(!!document.head.querySelector('#light-theme'));
+ });
+
+ test('applies the right theme', () => {
+ assert.equal(
+ getComputedStyleValue('--header-background-color', element)
+ .toLowerCase(),
+ '#f1f3f4');
+ assert.equal(
+ getComputedStyleValue('--footer-background-color', element)
+ .toLowerCase(),
+ 'transparent');
+ });
+});
diff --git a/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.js b/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.js
index 16dee09..6394bff 100644
--- a/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.js
+++ b/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.js
@@ -90,7 +90,10 @@
return Promise.all(promises)
.then(() => {
// ensures gr-overlay repositions overlay in center
- this.$.applyFixOverlay.fire('iron-resize');
+ this.$.applyFixOverlay.dispatchEvent(
+ new CustomEvent('iron-resize', {
+ composed: true, bubbles: true,
+ }));
});
}
@@ -98,7 +101,10 @@
super.attached();
this.refitOverlay = () => {
// re-center the dialog as content changed
- this.$.applyFixOverlay.fire('iron-resize');
+ this.$.applyFixOverlay.dispatchEvent(
+ new CustomEvent('iron-resize', {
+ composed: true, bubbles: true,
+ }));
};
this.addEventListener('diff-context-expanded', this.refitOverlay);
}
diff --git a/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog_test.html b/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog_test.js
similarity index 78%
rename from polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog_test.html
rename to polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog_test.js
index 65958c8..b3ba637 100644
--- a/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog_test.js
@@ -1,41 +1,29 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2019 The Android Open Source Project
+/**
+ * @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.
+ */
-Licensed under the Apache License, Version 2.0 (the 'License');
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an 'AS IS' BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<meta name='viewport' content='width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes'>
-<title>gr-apply-fix-dialog</title>
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id='basic'>
- <template>
- <gr-apply-fix-dialog></gr-apply-fix-dialog>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-apply-fix-dialog.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
+const basicFixture = fixtureFromElement('gr-apply-fix-dialog');
+
suite('gr-apply-fix-dialog tests', () => {
let element;
- let sandbox;
+
const ROBOT_COMMENT_WITH_TWO_FIXES = {
robot_id: 'robot_1',
fix_suggestions: [{fix_id: 'fix_1'}, {fix_id: 'fix_2'}],
@@ -47,8 +35,7 @@
};
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.changeNum = '1';
element._patchNum = 2;
element.change = {
@@ -67,13 +54,9 @@
};
});
- teardown(() => {
- sandbox.restore();
- });
-
suite('dialog open', () => {
setup(() => {
- sandbox.stub(element.$.restAPI, 'getRobotCommentFixPreview')
+ sinon.stub(element.$.restAPI, 'getRobotCommentFixPreview')
.returns(Promise.resolve({
f1: {
meta_a: {},
@@ -106,7 +89,7 @@
],
},
}));
- sandbox.stub(element.$.applyFixOverlay, 'open')
+ sinon.stub(element.$.applyFixOverlay, 'open')
.returns(Promise.resolve());
});
@@ -164,9 +147,9 @@
});
test('next button state updated when suggestions changed', done => {
- sandbox.stub(element.$.restAPI, 'getRobotCommentFixPreview')
+ sinon.stub(element.$.restAPI, 'getRobotCommentFixPreview')
.returns(Promise.resolve({}));
- sandbox.stub(element.$.applyFixOverlay, 'open').returns(Promise.resolve());
+ sinon.stub(element.$.applyFixOverlay, 'open').returns(Promise.resolve());
element.open({detail: {patchNum: 2, comment: ROBOT_COMMENT_WITH_ONE_FIX}})
.then(() => assert.isTrue(element.$.nextFix.disabled))
@@ -180,7 +163,7 @@
});
test('preview endpoint throws error should reset dialog', done => {
- sandbox.stub(window, 'fetch', (url => {
+ sinon.stub(window, 'fetch').callsFake((url => {
if (url.endsWith('/preview')) {
return Promise.reject(new Error('backend error'));
}
@@ -203,9 +186,9 @@
test('apply fix button should call apply ' +
'and navigate to change view', done => {
- sandbox.stub(element.$.restAPI, 'applyFixSuggestion')
+ sinon.stub(element.$.restAPI, 'applyFixSuggestion')
.returns(Promise.resolve({ok: true}));
- sandbox.stub(GerritNav, 'navigateToChange');
+ sinon.stub(GerritNav, 'navigateToChange');
element._currentFix = {fix_id: '123'};
element._handleApplyFix().then(() => {
@@ -229,9 +212,9 @@
});
test('should not navigate to change view if incorect reponse', done => {
- sandbox.stub(element.$.restAPI, 'applyFixSuggestion')
+ sinon.stub(element.$.restAPI, 'applyFixSuggestion')
.returns(Promise.resolve({}));
- sandbox.stub(GerritNav, 'navigateToChange');
+ sinon.stub(GerritNav, 'navigateToChange');
element._currentFix = {fix_id: '123'};
element._handleApplyFix().then(() => {
@@ -245,7 +228,7 @@
});
test('select fix forward and back of multiple suggested fixes', done => {
- sandbox.stub(element.$.restAPI, 'getRobotCommentFixPreview')
+ sinon.stub(element.$.restAPI, 'getRobotCommentFixPreview')
.returns(Promise.resolve({
f1: {
meta_a: {},
@@ -278,7 +261,7 @@
],
},
}));
- sandbox.stub(element.$.applyFixOverlay, 'open').returns(Promise.resolve());
+ sinon.stub(element.$.applyFixOverlay, 'open').returns(Promise.resolve());
element.open({detail: {patchNum: 2, comment: ROBOT_COMMENT_WITH_TWO_FIXES}})
.then(() => {
@@ -291,7 +274,7 @@
});
test('server-error should throw for failed apply call', done => {
- sandbox.stub(window, 'fetch', (url => {
+ sinon.stub(window, 'fetch').callsFake((url => {
if (url.endsWith('/apply')) {
return Promise.reject(new Error('backend error'));
}
@@ -303,7 +286,7 @@
}));
const errorStub = sinon.stub();
document.addEventListener('network-error', errorStub);
- sandbox.stub(GerritNav, 'navigateToChange');
+ sinon.stub(GerritNav, 'navigateToChange');
element._currentFix = {fix_id: '123'};
element._handleApplyFix();
flush(() => {
@@ -313,4 +296,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api_test.html b/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api_test.js
similarity index 90%
rename from polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api_test.html
rename to polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api_test.js
index 172a342..0a7c3b5 100644
--- a/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api_test.js
@@ -1,64 +1,46 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-comment-api</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-comment-api></gr-comment-api>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-comment-api.js';
+
+const basicFixture = fixtureFromElement('gr-comment-api');
+
suite('gr-comment-api tests', () => {
const PARENT = 'PARENT';
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
+ element = basicFixture.instantiate();
});
- teardown(() => { sandbox.restore(); });
-
test('loads logged-out', () => {
const changeNum = 1234;
- sandbox.stub(element.$.restAPI, 'getLoggedIn')
+ sinon.stub(element.$.restAPI, 'getLoggedIn')
.returns(Promise.resolve(false));
- sandbox.stub(element.$.restAPI, 'getDiffComments')
+ sinon.stub(element.$.restAPI, 'getDiffComments')
.returns(Promise.resolve({
'foo.c': [{id: '123', message: 'foo bar', in_reply_to: '321'}],
}));
- sandbox.stub(element.$.restAPI, 'getDiffRobotComments')
+ sinon.stub(element.$.restAPI, 'getDiffRobotComments')
.returns(Promise.resolve({'foo.c': [{id: '321', message: 'done'}]}));
- sandbox.stub(element.$.restAPI, 'getDiffDrafts')
+ sinon.stub(element.$.restAPI, 'getDiffDrafts')
.returns(Promise.resolve({}));
return element.loadAll(changeNum).then(() => {
@@ -77,15 +59,15 @@
test('loads logged-in', () => {
const changeNum = 1234;
- sandbox.stub(element.$.restAPI, 'getLoggedIn')
+ sinon.stub(element.$.restAPI, 'getLoggedIn')
.returns(Promise.resolve(true));
- sandbox.stub(element.$.restAPI, 'getDiffComments')
+ sinon.stub(element.$.restAPI, 'getDiffComments')
.returns(Promise.resolve({
'foo.c': [{id: '123', message: 'foo bar', in_reply_to: '321'}],
}));
- sandbox.stub(element.$.restAPI, 'getDiffRobotComments')
+ sinon.stub(element.$.restAPI, 'getDiffRobotComments')
.returns(Promise.resolve({'foo.c': [{id: '321', message: 'done'}]}));
- sandbox.stub(element.$.restAPI, 'getDiffDrafts')
+ sinon.stub(element.$.restAPI, 'getDiffDrafts')
.returns(Promise.resolve({'foo.c': [{id: '555', message: 'ack'}]}));
return element.loadAll(changeNum).then(() => {
@@ -106,17 +88,17 @@
let robotCommentStub;
let draftStub;
setup(() => {
- commentStub = sandbox.stub(element.$.restAPI, 'getDiffComments')
+ commentStub = sinon.stub(element.$.restAPI, 'getDiffComments')
.returns(Promise.resolve({}));
- robotCommentStub = sandbox.stub(element.$.restAPI,
+ robotCommentStub = sinon.stub(element.$.restAPI,
'getDiffRobotComments').returns(Promise.resolve({}));
- draftStub = sandbox.stub(element.$.restAPI, 'getDiffDrafts')
+ draftStub = sinon.stub(element.$.restAPI, 'getDiffDrafts')
.returns(Promise.resolve({}));
});
test('without loadAll first', done => {
assert.isNotOk(element._changeComments);
- sandbox.spy(element, 'loadAll');
+ sinon.spy(element, 'loadAll');
element.reloadDrafts().then(() => {
assert.isTrue(element.loadAll.called);
assert.isOk(element._changeComments);
@@ -209,9 +191,9 @@
const patchRange2 = {basePatchNum: 123, patchNum: 125};
const patchRange3 = {basePatchNum: 124, patchNum: 125};
- const isInBasePatchStub = sandbox.stub(element._changeComments,
+ const isInBasePatchStub = sinon.stub(element._changeComments,
'_isInBaseOfPatchRange');
- const isInRevisionPatchStub = sandbox.stub(element._changeComments,
+ const isInRevisionPatchStub = sinon.stub(element._changeComments,
'_isInRevisionOfPatchRange');
isInBasePatchStub.withArgs({}, patchRange1).returns(true);
@@ -760,4 +742,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/diff/gr-coverage-layer/gr-coverage-layer_test.html b/polygerrit-ui/app/elements/diff/gr-coverage-layer/gr-coverage-layer_test.js
similarity index 67%
rename from polygerrit-ui/app/elements/diff/gr-coverage-layer/gr-coverage-layer_test.html
rename to polygerrit-ui/app/elements/diff/gr-coverage-layer/gr-coverage-layer_test.js
index b80c56f3..e886e61 100644
--- a/polygerrit-ui/app/elements/diff/gr-coverage-layer/gr-coverage-layer_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-coverage-layer/gr-coverage-layer_test.js
@@ -1,40 +1,26 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2019 The Android Open Source Project
+/**
+ * @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.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-coverage-layer</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-coverage-layer></gr-coverage-layer>
- </template>
-</test-fixture>
-
-<script type="module">
+import '../../../test/common-test-setup-karma.js';
import '../gr-diff/gr-diff-line.js';
-import '../../../test/common-test-setup.js';
import './gr-coverage-layer.js';
+
+const basicFixture = fixtureFromElement('gr-coverage-layer');
+
suite('gr-coverage-layer', () => {
let element;
@@ -74,7 +60,7 @@
},
];
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.coverageRanges = initialCoverageRanges;
element.side = 'right';
});
@@ -135,4 +121,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-binary.js b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-binary.js
index a65fdca..9a56797 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-binary.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-binary.js
@@ -15,14 +15,14 @@
* limitations under the License.
*/
-import {GrDiffBuilder} from './gr-diff-builder.js';
+import {GrDiffBuilderUnified} from './gr-diff-builder-unified.js';
/** @constructor */
export function GrDiffBuilderBinary(diff, prefs, outputEl) {
- GrDiffBuilder.call(this, diff, prefs, outputEl);
+ GrDiffBuilderUnified.call(this, diff, prefs, outputEl, []);
}
-GrDiffBuilderBinary.prototype = Object.create(GrDiffBuilder.prototype);
+GrDiffBuilderBinary.prototype = Object.create(GrDiffBuilderUnified.prototype);
GrDiffBuilderBinary.prototype.constructor = GrDiffBuilderBinary;
// This method definition is a no-op to satisfy the parent type.
@@ -30,12 +30,15 @@
GrDiffBuilderBinary.prototype.buildSectionElement = function() {
const section = this._createElement('tbody', 'binary-diff');
- const row = this._createElement('tr');
- const cell = this._createElement('td');
- const label = this._createElement('label');
- label.textContent = 'Difference in binary files';
- cell.appendChild(label);
- row.appendChild(cell);
- section.appendChild(row);
+ const fileRow = this._createRow(section, {
+ beforeNumber: 'FILE',
+ afterNumber: 'FILE',
+ type: 'both',
+ text: '',
+ });
+ const contentTd = fileRow.querySelector('td.both.file');
+ contentTd.textContent = ' Difference in binary files';
+
+ section.appendChild(fileRow);
return section;
-};
+};
\ No newline at end of file
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-element.js b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-element.js
index c9d5d78..bb617f0 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-element.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-element.js
@@ -113,6 +113,14 @@
};
}
+ /** @override */
+ detached() {
+ super.detached();
+ if (this._builder) {
+ this._builder.clear();
+ }
+ }
+
get diffElement() {
return this.queryEffectiveChildren('#diffTable');
}
@@ -144,6 +152,9 @@
// Stop the processor if it's running.
this.cancel();
+ if (this._builder) {
+ this._builder.clear();
+ }
this._builder = this._getDiffBuilder(this.diff, prefs);
this.$.processor.context = prefs.context;
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-element_test.html b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-element_test.js
similarity index 91%
rename from polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-element_test.html
rename to polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-element_test.js
index 057401b..a88ac27 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-element_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-element_test.js
@@ -1,54 +1,21 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-diff-builder</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template is="dom-template">
- <gr-diff-builder>
- <table id="diffTable"></table>
- </gr-diff-builder>
- </template>
-</test-fixture>
-
-<test-fixture id="div-with-text">
- <template>
- <div>Lorem ipsum dolor sit amet, suspendisse inceptos vehicula</div>
- </template>
-</test-fixture>
-
-<test-fixture id="mock-diff">
- <template>
- <gr-diff-builder view-mode="SIDE_BY_SIDE">
- <table id="diffTable"></table>
- </gr-diff-builder>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import '../gr-diff/gr-diff-group.js';
import './gr-diff-builder.js';
import '../../shared/gr-rest-api-interface/gr-rest-api-interface.js';
@@ -59,6 +26,23 @@
import {GrDiffLine} from '../gr-diff/gr-diff-line.js';
import {GrDiffGroup} from '../gr-diff/gr-diff-group.js';
import {GrDiffBuilder} from './gr-diff-builder.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const basicFixture = fixtureFromTemplate(html`
+ <gr-diff-builder>
+ <table id="diffTable"></table>
+ </gr-diff-builder>
+`);
+
+const divWithTextFixture = fixtureFromTemplate(html`
+<div>Lorem ipsum dolor sit amet, suspendisse inceptos vehicula</div>
+`);
+
+const mockDiffFixture = fixtureFromTemplate(html`
+<gr-diff-builder view-mode="SIDE_BY_SIDE">
+ <table id="diffTable"></table>
+ </gr-diff-builder>
+`);
const DiffViewMode = {
SIDE_BY_SIDE: 'SIDE_BY_SIDE',
@@ -69,12 +53,11 @@
let prefs;
let element;
let builder;
- let sandbox;
+
const LINE_FEED_HTML = '<span class="style-scope gr-diff br"></span>';
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
+ element = basicFixture.instantiate();
stub('gr-rest-api-interface', {
getLoggedIn() { return Promise.resolve(false); },
getProjectConfig() { return Promise.resolve({}); },
@@ -87,8 +70,6 @@
builder = new GrDiffBuilder({content: []}, prefs);
});
- teardown(() => { sandbox.restore(); });
-
test('_createElement classStr applies all classes', () => {
const node = builder._createElement('div', 'test classes');
assert.isTrue(node.classList.contains('gr-diff'));
@@ -319,7 +300,7 @@
});
test('_handlePreferenceError called with invalid preference', () => {
- sandbox.stub(element, '_handlePreferenceError');
+ sinon.stub(element, '_handlePreferenceError');
const prefs = {tab_size: 0};
element._getDiffBuilder(element.diff, prefs);
assert.isTrue(element._handlePreferenceError.lastCall
@@ -379,9 +360,9 @@
}
setup(() => {
- el = fixture('div-with-text');
+ el = divWithTextFixture.instantiate();
str = el.textContent;
- annotateElementSpy = sandbox.spy(GrAnnotation, 'annotateElement');
+ annotateElementSpy = sinon.spy(GrAnnotation, 'annotateElement');
layer = document.createElement('gr-diff-builder')
._createIntralineLayer();
});
@@ -537,7 +518,7 @@
const lineNumberEl = document.createElement('td');
setup(() => {
- element = fixture('basic');
+ element = basicFixture.instantiate();
element._showTabs = true;
layer = element._createTabIndicatorLayer();
});
@@ -546,7 +527,7 @@
const line = {text: ''};
const el = document.createElement('div');
const annotateElementStub =
- sandbox.stub(GrAnnotation, 'annotateElement');
+ sinon.stub(GrAnnotation, 'annotateElement');
layer.annotate(el, lineNumberEl, line);
@@ -559,7 +540,7 @@
const el = document.createElement('div');
el.textContent = str;
const annotateElementStub =
- sandbox.stub(GrAnnotation, 'annotateElement');
+ sinon.stub(GrAnnotation, 'annotateElement');
layer.annotate(el, lineNumberEl, line);
@@ -572,7 +553,7 @@
const el = document.createElement('div');
el.textContent = str;
const annotateElementStub =
- sandbox.stub(GrAnnotation, 'annotateElement');
+ sinon.stub(GrAnnotation, 'annotateElement');
layer.annotate(el, lineNumberEl, line);
@@ -592,7 +573,7 @@
const el = document.createElement('div');
el.textContent = str;
const annotateElementStub =
- sandbox.stub(GrAnnotation, 'annotateElement');
+ sinon.stub(GrAnnotation, 'annotateElement');
layer.annotate(el, lineNumberEl, line);
@@ -605,7 +586,7 @@
const el = document.createElement('div');
el.textContent = str;
const annotateElementStub =
- sandbox.stub(GrAnnotation, 'annotateElement');
+ sinon.stub(GrAnnotation, 'annotateElement');
layer.annotate(el, lineNumberEl, line);
@@ -630,7 +611,7 @@
const el = document.createElement('div');
el.textContent = str;
const annotateElementStub =
- sandbox.stub(GrAnnotation, 'annotateElement');
+ sinon.stub(GrAnnotation, 'annotateElement');
layer.annotate(el, lineNumberEl, line);
@@ -649,7 +630,7 @@
let withLayerCount;
setup(() => {
const layers = [];
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.layers = layers;
element._showTrailingWhitespace = true;
element._setupAnnotationLayers();
@@ -664,7 +645,7 @@
suite('with layers', () => {
const layers = [{}, {}];
setup(() => {
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.layers = layers;
element._showTrailingWhitespace = true;
element._setupAnnotationLayers();
@@ -685,7 +666,7 @@
const lineNumberEl = document.createElement('td');
setup(() => {
- element = fixture('basic');
+ element = basicFixture.instantiate();
element._showTrailingWhitespace = true;
layer = element._createTrailingWhitespaceLayer();
});
@@ -694,7 +675,7 @@
const line = {text: ''};
const el = document.createElement('div');
const annotateElementStub =
- sandbox.stub(GrAnnotation, 'annotateElement');
+ sinon.stub(GrAnnotation, 'annotateElement');
layer.annotate(el, lineNumberEl, line);
assert.isFalse(annotateElementStub.called);
});
@@ -705,7 +686,7 @@
const el = document.createElement('div');
el.textContent = str;
const annotateElementStub =
- sandbox.stub(GrAnnotation, 'annotateElement');
+ sinon.stub(GrAnnotation, 'annotateElement');
layer.annotate(el, lineNumberEl, line);
assert.isFalse(annotateElementStub.called);
});
@@ -716,7 +697,7 @@
const el = document.createElement('div');
el.textContent = str;
const annotateElementStub =
- sandbox.stub(GrAnnotation, 'annotateElement');
+ sinon.stub(GrAnnotation, 'annotateElement');
layer.annotate(el, lineNumberEl, line);
assert.isTrue(annotateElementStub.called);
assert.equal(annotateElementStub.lastCall.args[1], 11);
@@ -729,7 +710,7 @@
const el = document.createElement('div');
el.textContent = str;
const annotateElementStub =
- sandbox.stub(GrAnnotation, 'annotateElement');
+ sinon.stub(GrAnnotation, 'annotateElement');
layer.annotate(el, lineNumberEl, line);
assert.isTrue(annotateElementStub.called);
assert.equal(annotateElementStub.lastCall.args[1], 11);
@@ -742,7 +723,7 @@
const el = document.createElement('div');
el.textContent = str;
const annotateElementStub =
- sandbox.stub(GrAnnotation, 'annotateElement');
+ sinon.stub(GrAnnotation, 'annotateElement');
layer.annotate(el, lineNumberEl, line);
assert.isTrue(annotateElementStub.called);
assert.equal(annotateElementStub.lastCall.args[1], 11);
@@ -755,7 +736,7 @@
const el = document.createElement('div');
el.textContent = str;
const annotateElementStub =
- sandbox.stub(GrAnnotation, 'annotateElement');
+ sinon.stub(GrAnnotation, 'annotateElement');
layer.annotate(el, lineNumberEl, line);
assert.isTrue(annotateElementStub.called);
assert.equal(annotateElementStub.lastCall.args[1], 1);
@@ -769,7 +750,7 @@
const el = document.createElement('div');
el.textContent = str;
const annotateElementStub =
- sandbox.stub(GrAnnotation, 'annotateElement');
+ sinon.stub(GrAnnotation, 'annotateElement');
layer.annotate(el, lineNumberEl, line);
assert.isFalse(annotateElementStub.called);
});
@@ -782,9 +763,9 @@
let content;
setup(() => {
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.viewMode = 'SIDE_BY_SIDE';
- processStub = sandbox.stub(element.$.processor, 'process')
+ processStub = sinon.stub(element.$.processor, 'process')
.returns(Promise.resolve());
keyLocations = {left: {}, right: {}};
prefs = {
@@ -856,12 +837,12 @@
],
},
];
- element = fixture('basic');
+ element = basicFixture.instantiate();
outputEl = element.queryEffectiveChildren('#diffTable');
keyLocations = {left: {}, right: {}};
- sandbox.stub(element, '_getDiffBuilder', () => {
+ sinon.stub(element, '_getDiffBuilder').callsFake(() => {
const builder = new GrDiffBuilder({content}, prefs, outputEl);
- sandbox.stub(builder, 'addColumns');
+ sinon.stub(builder, 'addColumns');
builder.buildSectionElement = function(group) {
const section = document.createElement('stub');
section.textContent = group.lines
@@ -898,7 +879,7 @@
});
test('render-start and render-content are fired', done => {
- const dispatchEventStub = sandbox.stub(element, 'dispatchEvent');
+ const dispatchEventStub = sinon.stub(element, 'dispatchEvent');
element.render(keyLocations, {}).then(() => {
const firedEventTypes = dispatchEventStub.getCalls()
.map(c => c.args[0].type);
@@ -909,7 +890,7 @@
});
test('cancel', () => {
- const processorCancelStub = sandbox.stub(element.$.processor, 'cancel');
+ const processorCancelStub = sinon.stub(element.$.processor, 'cancel');
element.cancel();
assert.isTrue(processorCancelStub.called);
});
@@ -923,7 +904,7 @@
let keyLocations;
setup(done => {
- element = fixture('mock-diff');
+ element = mockDiffFixture.instantiate();
diff = getMockDiffResponse();
element.diff = diff;
@@ -1014,7 +995,7 @@
});
test('_renderContentByRange', () => {
- const spy = sandbox.spy(builder, '_createTextEl');
+ const spy = sinon.spy(builder, '_createTextEl');
const start = 9;
const end = 14;
const count = end - start + 1;
@@ -1028,9 +1009,9 @@
});
test('_renderContentByRange notexistent elements', () => {
- const spy = sandbox.spy(builder, '_createTextEl');
+ const spy = sinon.spy(builder, '_createTextEl');
- sandbox.stub(builder, 'findLinesByRange',
+ sinon.stub(builder, 'findLinesByRange').callsFake(
(s, e, d, lines, elements) => {
// Add a line and a corresponding element.
lines.push(new GrDiffLine(GrDiffLine.Type.BOTH));
@@ -1186,7 +1167,7 @@
});
test('setBlame attempts to render each blamed line', () => {
- const getBlameStub = sandbox.stub(builder, '_getBlameByLineNum')
+ const getBlameStub = sinon.stub(builder, '_getBlameByLineNum')
.returns(null);
builder.setBlame(mockBlame);
assert.equal(getBlameStub.callCount, 32);
@@ -1252,4 +1233,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-unified_test.html b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-unified_test.js
similarity index 84%
rename from polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-unified_test.html
rename to polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-unified_test.js
index 2d26667..7346bf7 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-unified_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-unified_test.js
@@ -1,32 +1,21 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>GrDiffBuilderUnified</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import '../gr-diff/gr-diff-group.js';
import './gr-diff-builder.js';
import './gr-diff-builder-unified.js';
@@ -202,4 +191,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.js b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.js
index 1cabd82..04f1548 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.js
@@ -62,13 +62,22 @@
throw Error('Invalid line length from preferences.');
}
+ this._layerUpdateListener = this._handleLayerUpdate.bind(this);
for (const layer of this.layers) {
if (layer.addListener) {
- layer.addListener(this._handleLayerUpdate.bind(this));
+ layer.addListener(this._layerUpdateListener);
}
}
}
+GrDiffBuilder.prototype.clear = function() {
+ for (const layer of this.layers) {
+ if (layer.removeListener) {
+ layer.removeListener(this._layerUpdateListener);
+ }
+ }
+};
+
GrDiffBuilder.GroupType = {
ADDED: 'b',
BOTH: 'ab',
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor.js b/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor.js
index acb8f0c..9d68ba3 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor.js
@@ -202,9 +202,10 @@
}
}
- moveToNextChunk(opt_clipToTop) {
+ moveToNextChunk(opt_clipToTop, opt_navigateToNextFile) {
this.$.cursorManager.next(this._isFirstRowOfChunk.bind(this),
- target => target.parentNode.scrollHeight, opt_clipToTop);
+ target => target.parentNode.scrollHeight, opt_clipToTop,
+ opt_navigateToNextFile);
this._fixSide();
}
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor_test.html b/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor_test.js
similarity index 82%
rename from polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor_test.html
rename to polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor_test.js
index 71fc341..4ca75eb 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor_test.js
@@ -1,60 +1,42 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-diff-cursor</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-diff></gr-diff>
- <gr-diff-cursor></gr-diff-cursor>
- <gr-rest-api-interface></gr-rest-api-interface>
- </template>
-</test-fixture>
-
-<test-fixture id="empty">
- <template>
- <div></div>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import '../gr-diff/gr-diff.js';
import './gr-diff-cursor.js';
import '../../shared/gr-rest-api-interface/gr-rest-api-interface.js';
import {getMockDiffResponse} from '../../../test/mocks/diff-response.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const basicFixture = fixtureFromTemplate(html`
+ <gr-diff></gr-diff>
+ <gr-diff-cursor></gr-diff-cursor>
+ <gr-rest-api-interface></gr-rest-api-interface>
+`);
+
+const emptyFixture = fixtureFromElement('div');
+
suite('gr-diff-cursor tests', () => {
- let sandbox;
let cursorElement;
let diffElement;
setup(done => {
- sandbox = sinon.sandbox.create();
-
- const fixtureElems = fixture('basic');
+ const fixtureElems = basicFixture.instantiate();
diffElement = fixtureElems[0];
cursorElement = fixtureElems[1];
const restAPI = fixtureElems[2];
@@ -83,8 +65,6 @@
});
});
- teardown(() => sandbox.restore());
-
test('diff cursor functionality (side-by-side)', () => {
// The cursor has been initialized to the first delta.
assert.isOk(cursorElement.diffRow);
@@ -134,7 +114,7 @@
});
test('moves to selected line', () => {
- const moveToNumStub = sandbox.stub(cursorElement, 'moveToLineNumber');
+ const moveToNumStub = sinon.stub(cursorElement, 'moveToLineNumber');
cursorElement._handleDiffLineSelected(
new CustomEvent('line-selected', {
@@ -244,11 +224,27 @@
assert.equal(cursorElement.side, 'left');
});
+ test('navigate to next unreviewed file via moveToNextChunk', () => {
+ const cursor = cursorElement.shadowRoot.querySelector('#cursorManager');
+ cursor.index = cursor.stops.length - 1;
+ const dispatchEventStub = sinon.stub(cursor, 'dispatchEvent');
+ cursorElement.moveToNextChunk(/* opt_clipToTop = */false,
+ /* opt_navigateToNextFile = */true);
+ assert.isTrue(dispatchEventStub.called);
+ assert.equal(dispatchEventStub.getCall(0).args[0].type, 'show-alert');
+
+ cursorElement.moveToNextChunk(/* opt_clipToTop = */false,
+ /* opt_navigateToNextFile = */true);
+ assert.equal(dispatchEventStub.getCall(1).args[0].type,
+ 'navigate-to-next-unreviewed-file');
+ });
+
test('initialLineNumber not provided', done => {
let scrollBehaviorDuringMove;
- const moveToNumStub = sandbox.stub(cursorElement, 'moveToLineNumber');
- const moveToChunkStub = sandbox.stub(cursorElement, 'moveToFirstChunk',
- () => { scrollBehaviorDuringMove = cursorElement._scrollMode; });
+ const moveToNumStub = sinon.stub(cursorElement, 'moveToLineNumber');
+ const moveToChunkStub = sinon.stub(cursorElement, 'moveToFirstChunk')
+ .callsFake(
+ () => { scrollBehaviorDuringMove = cursorElement._scrollMode; });
function renderHandler() {
diffElement.removeEventListener('render', renderHandler);
@@ -265,9 +261,10 @@
test('initialLineNumber provided', done => {
let scrollBehaviorDuringMove;
- const moveToNumStub = sandbox.stub(cursorElement, 'moveToLineNumber',
- () => { scrollBehaviorDuringMove = cursorElement._scrollMode; });
- const moveToChunkStub = sandbox.stub(cursorElement, 'moveToFirstChunk');
+ const moveToNumStub = sinon.stub(cursorElement, 'moveToLineNumber')
+ .callsFake(
+ () => { scrollBehaviorDuringMove = cursorElement._scrollMode; });
+ const moveToChunkStub = sinon.stub(cursorElement, 'moveToFirstChunk');
function renderHandler() {
diffElement.removeEventListener('render', renderHandler);
cursorElement.reInitCursor();
@@ -349,9 +346,9 @@
});
test('createCommentInPlace ignores call if nothing is selected', () => {
- const createRangeCommentStub = sandbox.stub(diffElement,
+ const createRangeCommentStub = sinon.stub(diffElement,
'createRangeComment');
- const addDraftAtLineStub = sandbox.stub(diffElement, 'addDraftAtLine');
+ const addDraftAtLineStub = sinon.stub(diffElement, 'addDraftAtLine');
cursorElement.diffRow = undefined;
cursorElement.createCommentInPlace();
assert.isFalse(createRangeCommentStub.called);
@@ -398,7 +395,7 @@
});
test('expand context updates stops', done => {
- sandbox.spy(cursorElement, '_updateStops');
+ sinon.spy(cursorElement, '_updateStops');
MockInteractions.tap(diffElement.shadowRoot
.querySelector('.showContext'));
flush(() => {
@@ -408,15 +405,13 @@
});
suite('gr-diff-cursor event tests', () => {
- let sandbox;
let someEmptyDiv;
setup(() => {
- sandbox = sinon.sandbox.create();
- someEmptyDiv = fixture('empty');
+ someEmptyDiv = emptyFixture.instantiate();
});
- teardown(() => sandbox.restore());
+ teardown(() => sinon.restore());
test('ready is fired after component is rendered', done => {
const cursorElement = document.createElement('gr-diff-cursor');
@@ -427,4 +422,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-annotation_test.html b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-annotation_test.js
similarity index 85%
rename from polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-annotation_test.html
rename to polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-annotation_test.js
index 2bda950..65f5e07 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-annotation_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-annotation_test.js
@@ -1,57 +1,40 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
+const basicFixture = fixtureFromTemplate(html`
+<div>Lorem ipsum dolor sit amet, suspendisse inceptos vehicula</div>
+`);
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-annotation</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <div>Lorem ipsum dolor sit amet, suspendisse inceptos vehicula</div>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import {GrAnnotation} from './gr-annotation.js';
import {sanitizeDOMValue, setSanitizeDOMValue} from '@polymer/polymer/lib/utils/settings.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
suite('annotation', () => {
let str;
let parent;
let textNode;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
- parent = fixture('basic');
+ parent = basicFixture.instantiate();
textNode = parent.childNodes[0];
str = textNode.textContent;
});
- teardown(() => {
- sandbox.restore();
- });
-
test('_annotateText Case 1', () => {
GrAnnotation._annotateText(textNode, 0, str.length, 'foobar');
@@ -205,7 +188,7 @@
setup(() => {
originalSanitizeDOMValue = sanitizeDOMValue;
assert.isDefined(originalSanitizeDOMValue);
- mockSanitize = sandbox.spy(originalSanitizeDOMValue);
+ mockSanitize = sinon.spy(originalSanitizeDOMValue);
setSanitizeDOMValue(mockSanitize);
});
@@ -295,4 +278,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight.js b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight.js
index 229ae43..665e4a6 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight.js
@@ -119,6 +119,30 @@
return null;
}
+ _toggleRangeElHighlight(threadEl, highlightRange = false) {
+ // We don't want to re-create the line just for highlighting the range which
+ // is creating annoying bugs: @see Issue 12934
+ // As gr-ranged-comment-layer now does not notify the layer re-render and
+ // lack of access to the thread or the lineEl from the ranged-comment-layer,
+ // need to update range class for styles here.
+ const currentLine = threadEl.assignedSlot.parentElement.previousSibling;
+ if (currentLine && currentLine.querySelector) {
+ if (highlightRange) {
+ const rangeNode = currentLine.querySelector('.range');
+ if (rangeNode) {
+ rangeNode.classList.add('rangeHighlight');
+ rangeNode.classList.remove('range');
+ }
+ } else {
+ const rangeNode = currentLine.querySelector('.rangeHighlight');
+ if (rangeNode) {
+ rangeNode.classList.remove('rangeHighlight');
+ rangeNode.classList.add('range');
+ }
+ }
+ }
+ }
+
_handleCommentThreadMouseenter(e) {
const threadEl = this._getThreadEl(e);
const index = this._indexForThreadEl(threadEl);
@@ -126,6 +150,8 @@
if (index !== undefined) {
this.set(['commentRanges', index, 'hovering'], true);
}
+
+ this._toggleRangeElHighlight(threadEl, /* highlightRange= */ true);
}
_handleCommentThreadMouseleave(e) {
@@ -135,6 +161,8 @@
if (index !== undefined) {
this.set(['commentRanges', index, 'hovering'], false);
}
+
+ this._toggleRangeElHighlight(threadEl, /* highlightRange= */ false);
}
_indexForThreadEl(threadEl) {
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight_test.html b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight_test.js
similarity index 85%
rename from polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight_test.html
rename to polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight_test.js
index ec7e6d2..957d039 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight_test.js
@@ -1,37 +1,34 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
+import '../../../test/common-test-setup-karma.js';
+import './gr-diff-highlight.js';
+import {GrRangeNormalizer} from './gr-range-normalizer.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-diff-highlight</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <style>
+// Splitting long lines in html into shorter rows breaks tests:
+// zero-length text nodes and new lines are not expected in some places
+/* eslint-disable max-len */
+const basicFixture = fixtureFromTemplate(html`
+<style>
.tab-indicator:before {
color: #C62828;
/* >> character */
- content: '\00BB';
+ content: '\\00BB';
}
</style>
<gr-diff-highlight>
@@ -50,10 +47,10 @@
<tr class="diff-row side-by-side" left-type="remove" right-type="add">
<td class="left lineNum" data-value="2"></td>
<!-- Next tag is formatted to eliminate zero-length text nodes. -->
- <td class="content remove"><div class="contentText">na💢ti <hl class="foo">te, inquit</hl>, sumus <hl class="bar">aliquando</hl> otiosum, <hl>certe</hl> a <hl><span class="tab-indicator" style="tab-size:8;"> </span></hl>udiam, <hl>quid</hl> sit, <span class="tab-indicator" style="tab-size:8;"> </span>quod <hl>Epicurum</hl></div></td>
+ <td class="content remove"><div class="contentText">na💢ti <hl class="foo">te, inquit</hl>, sumus <hl class="bar">aliquando</hl> otiosum, <hl>certe</hl> a <hl><span class="tab-indicator" style="tab-size:8;">\u0009</span></hl>udiam, <hl>quid</hl> sit, <span class="tab-indicator" style="tab-size:8;">\u0009</span>quod <hl>Epicurum</hl></div></td>
<td class="right lineNum" data-value="2"></td>
<!-- Next tag is formatted to eliminate zero-length text nodes. -->
- <td class="content add"><div class="contentText">nacti , <hl>,</hl> sumus <hl><span class="tab-indicator" style="tab-size:8;"> </span></hl> otiosum, <span class="tab-indicator" style="tab-size:8;"> </span> audiam, sit, quod</div></td>
+ <td class="content add"><div class="contentText">nacti , <hl>,</hl> sumus <hl><span class="tab-indicator" style="tab-size:8;">\u0009</span></hl> otiosum, <span class="tab-indicator" style="tab-size:8;">\u0009</span> audiam, sit, quod</div></td>
</tr>
</tbody>
@@ -70,19 +67,19 @@
<tr class="diff-row side-by-side" left-type="remove" right-type="add">
<td class="left lineNum" data-value="140"></td>
<!-- Next tag is formatted to eliminate zero-length text nodes. -->
- <td class="content remove"><div class="contentText">na💢ti <hl class="foo">te, inquit</hl>, sumus <hl class="bar">aliquando</hl> otiosum, <hl>certe</hl> a <hl><span class="tab-indicator" style="tab-size:8;"> </span></hl>udiam, <hl>quid</hl> sit, <span class="tab-indicator" style="tab-size:8;"> </span>quod <hl>Epicurum</hl></div><div class="comment-thread">
+ <td class="content remove"><div class="contentText">na💢ti <hl class="foo">te, inquit</hl>, sumus <hl class="bar">aliquando</hl> otiosum, <hl>certe</hl> a <hl><span class="tab-indicator" style="tab-size:8;">\u0009</span></hl>udiam, <hl>quid</hl> sit, <span class="tab-indicator" style="tab-size:8;">\u0009</span>quod <hl>Epicurum</hl></div><div class="comment-thread">
[Yet another random diff thread content here]
</div></td>
<td class="right lineNum" data-value="120"></td>
<!-- Next tag is formatted to eliminate zero-length text nodes. -->
- <td class="content add"><div class="contentText">nacti , <hl>,</hl> sumus <hl><span class="tab-indicator" style="tab-size:8;"> </span></hl> otiosum, <span class="tab-indicator" style="tab-size:8;"> </span> audiam, sit, quod</div></td>
+ <td class="content add"><div class="contentText">nacti , <hl>,</hl> sumus <hl><span class="tab-indicator" style="tab-size:8;">\u0009</span></hl> otiosum, <span class="tab-indicator" style="tab-size:8;">\u0009</span> audiam, sit, quod</div></td>
</tr>
</tbody>
<tbody class="section both">
<tr class="diff-row side-by-side" left-type="both" right-type="both">
<td class="left lineNum" data-value="141"></td>
- <td class="content both"><div class="contentText">nam et<hl><span class="tab-indicator" style="tab-size:8;"> </span></hl>complectitur<span class="tab-indicator" style="tab-size:8;"> </span>verbis, quod vult, et dicit plane, quod intellegam;</div></td>
+ <td class="content both"><div class="contentText">nam et<hl><span class="tab-indicator" style="tab-size:8;">\u0009</span></hl>complectitur<span class="tab-indicator" style="tab-size:8;">\u0009</span>verbis, quod vult, et dicit plane, quod intellegam;</div></td>
<td class="right lineNum" data-value="130"></td>
<td class="content both"><div class="contentText">nam et complectitur verbis, quod vult, et dicit plane, quod intellegam;</div></td>
</tr>
@@ -123,41 +120,20 @@
<td class="left lineNum" data-value="165"></td>
<td class="content both"><div class="contentText"></div></td>
<td class="right lineNum" data-value="147"></td>
- <td class="content both"><div class="contentText">in physicis, <hl><span class="tab-indicator" style="tab-size:8;"> </span></hl> quibus maxime gloriatur, primum totus est alienus. Democritea dicit</div></td>
+ <td class="content both"><div class="contentText">in physicis, <hl><span class="tab-indicator" style="tab-size:8;">\u0009</span></hl> quibus maxime gloriatur, primum totus est alienus. Democritea dicit</div></td>
</tr>
</tbody>
</table>
</gr-diff-highlight>
- </template>
-</test-fixture>
-
-<test-fixture id="highlighted">
- <template>
- <div>
- <hl class="rangeHighlight">foo</hl>
- bar
- <hl class="rangeHighlight">baz</hl>
- </div>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-diff-highlight.js';
-import {GrRangeNormalizer} from './gr-range-normalizer.js';
+`);
+/* eslint-enable max-len */
suite('gr-diff-highlight', () => {
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic')[1];
- });
-
- teardown(() => {
- sandbox.restore();
+ element = basicFixture.instantiate()[1];
});
suite('comment events', () => {
@@ -165,9 +141,9 @@
setup(() => {
builder = {
- getContentsByLineRange: sandbox.stub().returns([]),
- getLineElByChild: sandbox.stub().returns({}),
- getSideByLineEl: sandbox.stub().returns('other-side'),
+ getContentsByLineRange: sinon.stub().returns([]),
+ getLineElByChild: sinon.stub().returns({}),
+ getSideByLineEl: sinon.stub().returns('other-side'),
};
element._cachedDiffBuilder = builder;
});
@@ -180,7 +156,7 @@
element.appendChild(threadEl);
element.commentRanges = [{side: 'right'}];
- sandbox.stub(element, 'set');
+ sinon.stub(element, 'set');
threadEl.dispatchEvent(new CustomEvent(
'comment-thread-mouseenter', {bubbles: true, composed: true}));
assert.isFalse(element.set.called);
@@ -205,7 +181,7 @@
end_character: 6,
}}];
- sandbox.stub(element, 'set');
+ sinon.stub(element, 'set');
threadEl.dispatchEvent(new CustomEvent(
'comment-thread-mouseenter', {bubbles: true, composed: true}));
assert.isTrue(element.set.called);
@@ -222,7 +198,7 @@
element.appendChild(threadEl);
element.commentRanges = [{side: 'right'}];
- sandbox.stub(element, 'set');
+ sinon.stub(element, 'set');
threadEl.dispatchEvent(new CustomEvent(
'comment-thread-mouseleave', {bubbles: true, composed: true}));
assert.isFalse(element.set.called);
@@ -230,7 +206,7 @@
test(`create-range-comment for range when create-comment-requested
is fired`, () => {
- sandbox.stub(element, '_removeActionBox');
+ sinon.stub(element, '_removeActionBox');
element.selectedRange = {
side: 'left',
range: {
@@ -291,16 +267,16 @@
setup(() => {
contentStubs = [];
stub('gr-selection-action-box', {
- placeAbove: sandbox.stub(),
- placeBelow: sandbox.stub(),
+ placeAbove: sinon.stub(),
+ placeBelow: sinon.stub(),
});
diff = element.querySelector('#diffTable');
builder = {
- getContentTdByLine: sandbox.stub(),
- getContentTdByLineEl: sandbox.stub(),
+ getContentTdByLine: sinon.stub(),
+ getContentTdByLineEl: sinon.stub(),
getLineElByChild,
- getLineNumberByChild: sandbox.stub(),
- getSideByLineEl: sandbox.stub(),
+ getLineNumberByChild: sinon.stub(),
+ getSideByLineEl: sinon.stub(),
};
element._cachedDiffBuilder = builder;
});
@@ -312,7 +288,7 @@
test('single first line', () => {
const content = stubContent(1, 'right');
- sandbox.spy(element, '_positionActionBox');
+ sinon.spy(element, '_positionActionBox');
emulateSelection(content.firstChild, 5, content.firstChild, 12);
const actionBox = element.shadowRoot
.querySelector('gr-selection-action-box');
@@ -322,7 +298,7 @@
test('multiline starting on first line', () => {
const startContent = stubContent(1, 'right');
const endContent = stubContent(2, 'right');
- sandbox.spy(element, '_positionActionBox');
+ sinon.spy(element, '_positionActionBox');
emulateSelection(
startContent.firstChild, 10, endContent.lastChild, 7);
const actionBox = element.shadowRoot
@@ -332,7 +308,7 @@
test('single line', () => {
const content = stubContent(138, 'left');
- sandbox.spy(element, '_positionActionBox');
+ sinon.spy(element, '_positionActionBox');
emulateSelection(content.firstChild, 5, content.firstChild, 12);
const actionBox = element.shadowRoot
.querySelector('gr-selection-action-box');
@@ -350,7 +326,7 @@
test('multiline', () => {
const startContent = stubContent(119, 'right');
const endContent = stubContent(120, 'right');
- sandbox.spy(element, '_positionActionBox');
+ sinon.spy(element, '_positionActionBox');
emulateSelection(
startContent.firstChild, 10, endContent.lastChild, 7);
const actionBox = element.shadowRoot
@@ -378,7 +354,7 @@
endRange.setStart(endContent.lastChild, 6);
endRange.setEnd(endContent.lastChild, 7);
- const getRangeAtStub = sandbox.stub();
+ const getRangeAtStub = sinon.stub();
getRangeAtStub
.onFirstCall().returns(startRange)
.onSecondCall()
@@ -386,7 +362,7 @@
const selection = {
rangeCount: 2,
getRangeAt: getRangeAtStub,
- removeAllRanges: sandbox.stub(),
+ removeAllRanges: sinon.stub(),
};
element._handleSelection(selection);
const {range} = element.selectedRange;
@@ -627,4 +603,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.js b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.js
index cb299de..bdf41a9 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.js
@@ -314,12 +314,19 @@
});
}
+ /** @override */
+ detached() {
+ super.detached();
+ this.clear();
+ }
+
/**
* @param {boolean=} shouldReportMetric indicate a new Diff Page. This is a
* signal to report metrics event that started on location change.
* @return {!Promise}
**/
reload(shouldReportMetric) {
+ this.clear();
this._loading = true;
this._errorMessage = null;
const whitespaceLevel = this._getIgnoreWhitespace();
@@ -398,6 +405,11 @@
.then(() => { this._loading = false; });
}
+ clear() {
+ this.$.jsAPI.disposeDiffLayers(this.path);
+ this._layers = [];
+ }
+
_getCoverageData() {
const {changeNum, path, patchRange: {basePatchNum, patchNum}} = this;
this.$.jsAPI.getCoverageAnnotationApi().
@@ -921,7 +933,7 @@
preferredWhitespaceLevel,
loadedWhitespaceLevel,
noRenderOnPrefsChange,
- ].some(arg => arg === undefined)) {
+ ].includes(undefined)) {
return;
}
@@ -937,7 +949,7 @@
if ([
noRenderOnPrefsChange,
prefsChangeRecord,
- ].some(arg => arg === undefined)) {
+ ].includes(undefined)) {
return;
}
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.html b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.js
similarity index 91%
rename from polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.html
rename to polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.js
index 342c7ec..d0e6b62 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.js
@@ -1,62 +1,42 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2018 The Android Open Source Project
+/**
+ * @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.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-diff</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-diff-host></gr-diff-host>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-diff-host.js';
import {GrDiffBuilderImage} from '../gr-diff-builder/gr-diff-builder-image.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {DiffSide} from '../gr-diff/gr-diff-utils.js';
+const basicFixture = fixtureFromElement('gr-diff-host');
+
suite('gr-diff-host tests', () => {
let element;
- let sandbox;
+
let getLoggedIn;
setup(() => {
- sandbox = sinon.sandbox.create();
getLoggedIn = false;
stub('gr-rest-api-interface', {
async getLoggedIn() { return getLoggedIn; },
});
- element = fixture('basic');
- sandbox.stub(element.reporting, 'time');
- sandbox.stub(element.reporting, 'timeEnd');
- });
-
- teardown(() => {
- sandbox.restore();
+ element = basicFixture.instantiate();
+ sinon.stub(element.reporting, 'time');
+ sinon.stub(element.reporting, 'timeEnd');
});
suite('plugin layers', () => {
@@ -65,7 +45,7 @@
stub('gr-js-api-interface', {
getDiffLayers() { return pluginLayers; },
});
- element = fixture('basic');
+ element = basicFixture.instantiate();
});
test('plugin layers requested', () => {
element.patchRange = {};
@@ -76,7 +56,7 @@
suite('handle comment-update', () => {
setup(() => {
- sandbox.stub(element, '_commentsChanged');
+ sinon.stub(element, '_commentsChanged');
element.comments = {
meta: {
changeNum: '42',
@@ -122,7 +102,7 @@
side: 'PARENT',
__commentSide: 'left',
};
- const diffCommentsModifiedStub = sandbox.stub();
+ const diffCommentsModifiedStub = sinon.stub();
element.addEventListener('diff-comments-modified',
diffCommentsModifiedStub);
element.comments.left.push(comment);
@@ -147,7 +127,7 @@
side: 'PARENT',
__commentSide: 'left',
};
- const diffCommentsModifiedStub = sandbox.stub();
+ const diffCommentsModifiedStub = sinon.stub();
element.addEventListener('diff-comments-modified',
diffCommentsModifiedStub);
element.comments.left.push(comment);
@@ -166,7 +146,7 @@
});
test('remove comment', () => {
- sandbox.stub(element, '_commentsChanged');
+ sinon.stub(element, '_commentsChanged');
element.comments = {
meta: {
changeNum: '42',
@@ -320,13 +300,13 @@
});
test('ends total and syntax timer after syntax layer processing', done => {
- sandbox.stub(element.reporting, 'diffViewContentDisplayed');
+ sinon.stub(element.reporting, 'diffViewContentDisplayed');
let notifySyntaxProcessed;
- sandbox.stub(element.$.syntaxLayer, 'process').returns(new Promise(
+ sinon.stub(element.$.syntaxLayer, 'process').returns(new Promise(
resolve => {
notifySyntaxProcessed = resolve;
}));
- sandbox.stub(element.$.restAPI, 'getDiff').returns(
+ sinon.stub(element.$.restAPI, 'getDiff').returns(
Promise.resolve({content: []}));
element.patchRange = {};
element.$.restAPI.getDiffPreferences().then(prefs => {
@@ -349,26 +329,30 @@
});
test('ends total timer w/ no syntax layer processing', done => {
- sandbox.stub(element.$.restAPI, 'getDiff').returns(
+ sinon.stub(element.$.restAPI, 'getDiff').returns(
Promise.resolve({content: []}));
element.patchRange = {};
element.reload();
// Multiple cascading microtasks are scheduled.
setTimeout(() => {
- assert.isTrue(element.reporting.timeEnd.calledOnce);
- assert.isTrue(element.reporting.timeEnd.calledWithExactly(
- 'Diff Total Render'));
+ // Reporting can be called with other parameters (ex. PluginsLoaded),
+ // but only 'Diff Total Render' is important in this test.
+ assert.equal(
+ element.reporting.timeEnd.getCalls()
+ .filter(call => call.calledWithExactly('Diff Total Render'))
+ .length,
+ 1);
done();
});
});
test('completes reload promise after syntax layer processing', done => {
let notifySyntaxProcessed;
- sandbox.stub(element.$.syntaxLayer, 'process').returns(new Promise(
+ sinon.stub(element.$.syntaxLayer, 'process').returns(new Promise(
resolve => {
notifySyntaxProcessed = resolve;
}));
- sandbox.stub(element.$.restAPI, 'getDiff').returns(
+ sinon.stub(element.$.restAPI, 'getDiff').returns(
Promise.resolve({content: []}));
element.patchRange = {};
let reloadComplete = false;
@@ -394,10 +378,10 @@
});
test('reload() cancels before network resolves', () => {
- const cancelStub = sandbox.stub(element.$.diff, 'cancel');
+ const cancelStub = sinon.stub(element.$.diff, 'cancel');
// Stub the network calls into requests that never resolve.
- sandbox.stub(element, '_getDiff', () => new Promise(() => {}));
+ sinon.stub(element, '_getDiff').callsFake(() => new Promise(() => {}));
element.patchRange = {};
element.reload();
@@ -407,13 +391,13 @@
suite('not logged in', () => {
setup(() => {
getLoggedIn = false;
- element = fixture('basic');
+ element = basicFixture.instantiate();
});
test('reload() loads files weblinks', () => {
- const weblinksStub = sandbox.stub(GerritNav, '_generateWeblinks')
+ const weblinksStub = sinon.stub(GerritNav, '_generateWeblinks')
.returns({name: 'stubb', url: '#s'});
- sandbox.stub(element.$.restAPI, 'getDiff').returns(Promise.resolve({
+ sinon.stub(element.$.restAPI, 'getDiff').returns(Promise.resolve({
content: [],
}));
element.projectName = 'test-project';
@@ -446,7 +430,7 @@
});
test('prefetch getDiff', done => {
- const diffRestApiStub = sandbox.stub(element.$.restAPI, 'getDiff')
+ const diffRestApiStub = sinon.stub(element.$.restAPI, 'getDiff')
.returns(Promise.resolve({content: []}));
element.changeNum = 123;
element.patchRange = {basePatchNum: 1, patchNum: 2};
@@ -469,9 +453,9 @@
});
test('reload resolves on error', () => {
- const onErrStub = sandbox.stub(element, '_handleGetDiffError');
+ const onErrStub = sinon.stub(element, '_handleGetDiffError');
const error = {ok: false, status: 500};
- sandbox.stub(element.$.restAPI, 'getDiff',
+ sinon.stub(element.$.restAPI, 'getDiff').callsFake(
(changeNum, basePatchNum, patchNum, path, onErr) => {
onErr(error);
});
@@ -530,12 +514,12 @@
'wsAAAAAAAAAAAAA/////w==',
type: 'image/bmp',
};
- sandbox.stub(element.$.restAPI,
- 'getB64FileContents',
- (changeId, patchNum, path, opt_parentIndex) => Promise.resolve(
- opt_parentIndex === 1 ? mockFile1 :
- mockFile2)
- );
+ sinon.stub(element.$.restAPI,
+ 'getB64FileContents')
+ .callsFake(
+ (changeId, patchNum, path, opt_parentIndex) => Promise.resolve(
+ opt_parentIndex === 1 ? mockFile1 : mockFile2)
+ );
element.patchRange = {basePatchNum: 'PARENT', patchNum: 1};
element.comments = {
@@ -562,7 +546,7 @@
content: [{skip: 66}],
binary: true,
};
- sandbox.stub(element.$.restAPI, 'getDiff')
+ sinon.stub(element.$.restAPI, 'getDiff')
.returns(Promise.resolve(mockDiff));
const rendered = () => {
@@ -643,7 +627,7 @@
content: [{skip: 66}],
binary: true,
};
- sandbox.stub(element.$.restAPI, 'getDiff')
+ sinon.stub(element.$.restAPI, 'getDiff')
.returns(Promise.resolve(mockDiff));
const rendered = () => {
@@ -725,7 +709,7 @@
content: [{skip: 66}],
binary: true,
};
- sandbox.stub(element.$.restAPI, 'getDiff')
+ sinon.stub(element.$.restAPI, 'getDiff')
.returns(Promise.resolve(mockDiff));
element.addEventListener('render', () => {
@@ -766,7 +750,7 @@
content: [{skip: 66}],
binary: true,
};
- sandbox.stub(element.$.restAPI, 'getDiff')
+ sinon.stub(element.$.restAPI, 'getDiff')
.returns(Promise.resolve(mockDiff));
element.addEventListener('render', () => {
@@ -809,7 +793,7 @@
};
mockFile1.type = 'image/jpeg-evil';
- sandbox.stub(element.$.restAPI, 'getDiff')
+ sinon.stub(element.$.restAPI, 'getDiff')
.returns(Promise.resolve(mockDiff));
element.addEventListener('render', () => {
@@ -832,7 +816,7 @@
});
test('delegates cancel()', () => {
- const stub = sandbox.stub(element.$.diff, 'cancel');
+ const stub = sinon.stub(element.$.diff, 'cancel');
element.patchRange = {};
element.reload();
assert.isTrue(stub.calledOnce);
@@ -841,7 +825,7 @@
test('delegates getCursorStops()', () => {
const returnValue = [document.createElement('b')];
- const stub = sandbox.stub(element.$.diff, 'getCursorStops')
+ const stub = sinon.stub(element.$.diff, 'getCursorStops')
.returns(returnValue);
assert.equal(element.getCursorStops(), returnValue);
assert.isTrue(stub.calledOnce);
@@ -850,7 +834,7 @@
test('delegates isRangeSelected()', () => {
const returnValue = true;
- const stub = sandbox.stub(element.$.diff, 'isRangeSelected')
+ const stub = sinon.stub(element.$.diff, 'isRangeSelected')
.returns(returnValue);
assert.equal(element.isRangeSelected(), returnValue);
assert.isTrue(stub.calledOnce);
@@ -858,7 +842,7 @@
});
test('delegates toggleLeftDiff()', () => {
- const stub = sandbox.stub(element.$.diff, 'toggleLeftDiff');
+ const stub = sinon.stub(element.$.diff, 'toggleLeftDiff');
element.toggleLeftDiff();
assert.isTrue(stub.calledOnce);
assert.equal(stub.lastCall.args.length, 0);
@@ -866,12 +850,12 @@
suite('blame', () => {
setup(() => {
- element = fixture('basic');
+ element = basicFixture.instantiate();
});
test('clearBlame', () => {
element._blame = [];
- const setBlameSpy = sandbox.spy(element.$.diff.$.diffBuilder, 'setBlame');
+ const setBlameSpy = sinon.spy(element.$.diff.$.diffBuilder, 'setBlame');
element.clearBlame();
assert.isNull(element._blame);
assert.isTrue(setBlameSpy.calledWithExactly(null));
@@ -882,7 +866,7 @@
const mockBlame = [{id: 'commit id', ranges: [{start: 1, end: 2}]}];
const showAlertStub = sinon.stub();
element.addEventListener('show-alert', showAlertStub);
- const getBlameStub = sandbox.stub(element.$.restAPI, 'getBlame')
+ const getBlameStub = sinon.stub(element.$.restAPI, 'getBlame')
.returns(Promise.resolve(mockBlame));
element.changeNum = 42;
element.patchRange = {patchNum: 5, basePatchNum: 4};
@@ -900,7 +884,7 @@
const mockBlame = [];
const showAlertStub = sinon.stub();
element.addEventListener('show-alert', showAlertStub);
- sandbox.stub(element.$.restAPI, 'getBlame')
+ sinon.stub(element.$.restAPI, 'getBlame')
.returns(Promise.resolve(mockBlame));
element.changeNum = 42;
element.patchRange = {patchNum: 5, basePatchNum: 4};
@@ -926,7 +910,7 @@
test('delegates addDraftAtLine(el)', () => {
const param0 = document.createElement('b');
- const stub = sandbox.stub(element.$.diff, 'addDraftAtLine');
+ const stub = sinon.stub(element.$.diff, 'addDraftAtLine');
element.addDraftAtLine(param0);
assert.isTrue(stub.calledOnce);
assert.equal(stub.lastCall.args.length, 1);
@@ -934,14 +918,14 @@
});
test('delegates clearDiffContent()', () => {
- const stub = sandbox.stub(element.$.diff, 'clearDiffContent');
+ const stub = sinon.stub(element.$.diff, 'clearDiffContent');
element.clearDiffContent();
assert.isTrue(stub.calledOnce);
assert.equal(stub.lastCall.args.length, 0);
});
test('delegates expandAllContext()', () => {
- const stub = sandbox.stub(element.$.diff, 'expandAllContext');
+ const stub = sinon.stub(element.$.diff, 'expandAllContext');
element.expandAllContext();
assert.isTrue(stub.calledOnce);
assert.equal(stub.lastCall.args.length, 0);
@@ -1036,10 +1020,10 @@
let reportStub;
setup(() => {
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.path = 'file.txt';
element.patchRange = {basePatchNum: 1};
- reportStub = sandbox.stub(element.reporting, 'reportInteraction');
+ reportStub = sinon.stub(element.reporting, 'reportInteraction');
});
test('null and content-less', () => {
@@ -1489,9 +1473,9 @@
});
test('starts syntax layer processing on render event', done => {
- sandbox.stub(element.$.syntaxLayer, 'process')
+ sinon.stub(element.$.syntaxLayer, 'process')
.returns(Promise.resolve());
- sandbox.stub(element.$.restAPI, 'getDiff').returns(
+ sinon.stub(element.$.restAPI, 'getDiff').returns(
Promise.resolve({content: []}));
element.reload();
setTimeout(() => {
@@ -1571,7 +1555,7 @@
});
},
});
- element = fixture('basic');
+ element = basicFixture.instantiate();
const prefs = {
line_length: 10,
show_tabs: true,
@@ -1665,7 +1649,7 @@
suite('_hasTrailingNewlines', () => {
test('shared no trailing', () => {
const diff = undefined;
- sandbox.stub(element, '_lastChunkForSide')
+ sinon.stub(element, '_lastChunkForSide')
.returns({ab: ['foo', 'bar']});
assert.isFalse(element._hasTrailingNewlines(diff, false));
assert.isFalse(element._hasTrailingNewlines(diff, true));
@@ -1673,7 +1657,7 @@
test('delta trailing in right', () => {
const diff = undefined;
- sandbox.stub(element, '_lastChunkForSide')
+ sinon.stub(element, '_lastChunkForSide')
.returns({a: ['foo', 'bar'], b: ['baz', '']});
assert.isTrue(element._hasTrailingNewlines(diff, false));
assert.isFalse(element._hasTrailingNewlines(diff, true));
@@ -1681,7 +1665,7 @@
test('addition', () => {
const diff = undefined;
- sandbox.stub(element, '_lastChunkForSide', (diff, leftSide) => {
+ sinon.stub(element, '_lastChunkForSide').callsFake((diff, leftSide) => {
if (leftSide) { return null; }
return {b: ['foo', '']};
});
@@ -1691,7 +1675,7 @@
test('deletion', () => {
const diff = undefined;
- sandbox.stub(element, '_lastChunkForSide', (diff, leftSide) => {
+ sinon.stub(element, '_lastChunkForSide').callsFake((diff, leftSide) => {
if (!leftSide) { return null; }
return {a: ['foo']};
});
@@ -1701,4 +1685,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-mode-selector/gr-diff-mode-selector_test.html b/polygerrit-ui/app/elements/diff/gr-diff-mode-selector/gr-diff-mode-selector_test.html
deleted file mode 100644
index 309f4ac..0000000
--- a/polygerrit-ui/app/elements/diff/gr-diff-mode-selector/gr-diff-mode-selector_test.html
+++ /dev/null
@@ -1,84 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-diff-mode-selector</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<script src="/node_modules/page/page.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-diff-mode-selector></gr-diff-mode-selector>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-diff-mode-selector.js';
-suite('gr-diff-mode-selector tests', () => {
- let element;
- let sandbox;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('_computeSelectedClass', () => {
- assert.equal(
- element._computeSelectedClass('SIDE_BY_SIDE', 'SIDE_BY_SIDE'),
- 'selected');
- assert.equal(
- element._computeSelectedClass('SIDE_BY_SIDE', 'UNIFIED_DIFF'), '');
- });
-
- test('setMode', () => {
- const saveStub = sandbox.stub(element.$.restAPI, 'savePreferences');
-
- // Setting the mode initially does not save prefs.
- element.saveOnChange = true;
- element.setMode('SIDE_BY_SIDE');
- assert.isFalse(saveStub.called);
-
- // Setting the mode to itself does not save prefs.
- element.setMode('SIDE_BY_SIDE');
- assert.isFalse(saveStub.called);
-
- // Setting the mode to something else does not save prefs if saveOnChange
- // is false.
- element.saveOnChange = false;
- element.setMode('UNIFIED_DIFF');
- assert.isFalse(saveStub.called);
-
- // Setting the mode to something else does not save prefs if saveOnChange
- // is false.
- element.saveOnChange = true;
- element.setMode('SIDE_BY_SIDE');
- assert.isTrue(saveStub.calledOnce);
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-mode-selector/gr-diff-mode-selector_test.js b/polygerrit-ui/app/elements/diff/gr-diff-mode-selector/gr-diff-mode-selector_test.js
new file mode 100644
index 0000000..e84ef2b
--- /dev/null
+++ b/polygerrit-ui/app/elements/diff/gr-diff-mode-selector/gr-diff-mode-selector_test.js
@@ -0,0 +1,63 @@
+/**
+ * @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.
+ */
+
+import '../../../test/common-test-setup-karma.js';
+import './gr-diff-mode-selector.js';
+
+const basicFixture = fixtureFromElement('gr-diff-mode-selector');
+
+suite('gr-diff-mode-selector tests', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ test('_computeSelectedClass', () => {
+ assert.equal(
+ element._computeSelectedClass('SIDE_BY_SIDE', 'SIDE_BY_SIDE'),
+ 'selected');
+ assert.equal(
+ element._computeSelectedClass('SIDE_BY_SIDE', 'UNIFIED_DIFF'), '');
+ });
+
+ test('setMode', () => {
+ const saveStub = sinon.stub(element.$.restAPI, 'savePreferences');
+
+ // Setting the mode initially does not save prefs.
+ element.saveOnChange = true;
+ element.setMode('SIDE_BY_SIDE');
+ assert.isFalse(saveStub.called);
+
+ // Setting the mode to itself does not save prefs.
+ element.setMode('SIDE_BY_SIDE');
+ assert.isFalse(saveStub.called);
+
+ // Setting the mode to something else does not save prefs if saveOnChange
+ // is false.
+ element.saveOnChange = false;
+ element.setMode('UNIFIED_DIFF');
+ assert.isFalse(saveStub.called);
+
+ // Setting the mode to something else does not save prefs if saveOnChange
+ // is false.
+ element.saveOnChange = true;
+ element.setMode('SIDE_BY_SIDE');
+ assert.isTrue(saveStub.calledOnce);
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-preferences-dialog/gr-diff-preferences-dialog_test.html b/polygerrit-ui/app/elements/diff/gr-diff-preferences-dialog/gr-diff-preferences-dialog_test.html
deleted file mode 100644
index d3050af..0000000
--- a/polygerrit-ui/app/elements/diff/gr-diff-preferences-dialog/gr-diff-preferences-dialog_test.html
+++ /dev/null
@@ -1,69 +0,0 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2020 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-diff-preferences-dialog</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<script src="/components/web-component-tester/data/a11ySuite.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-diff-preferences-dialog></gr-diff-preferences-dialog>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-diff-preferences-dialog.js';
-import {flush} from '@polymer/polymer/lib/legacy/polymer.dom.js';
-
-suite('gr-diff-preferences-dialog', () => {
- let element;
- setup(() => {
- element = fixture('basic');
- });
- test('changes applies only on save', async () => {
- const originalDiffPrefs = {
- line_wrapping: true,
- };
- element.diffPrefs = originalDiffPrefs;
-
- element.open();
- await flush();
- assert.isTrue(element.$.diffPreferences.$.lineWrappingInput.checked);
-
- MockInteractions.tap(element.$.diffPreferences.$.lineWrappingInput);
- await flush();
- assert.isFalse(element.$.diffPreferences.$.lineWrappingInput.checked);
- assert.isTrue(element._diffPrefsChanged);
- assert.isTrue(element.diffPrefs.line_wrapping);
- assert.isTrue(originalDiffPrefs.line_wrapping);
-
- MockInteractions.tap(element.$.saveButton);
- await flush();
- // Original prefs must remains unchanged, dialog must expose a new object
- assert.isTrue(originalDiffPrefs.line_wrapping);
- assert.isFalse(element.diffPrefs.line_wrapping);
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-processor/gr-diff-processor_test.html b/polygerrit-ui/app/elements/diff/gr-diff-processor/gr-diff-processor_test.js
similarity index 94%
rename from polygerrit-ui/app/elements/diff/gr-diff-processor/gr-diff-processor_test.html
rename to polygerrit-ui/app/elements/diff/gr-diff-processor/gr-diff-processor_test.js
index aafd374..a8fba5d 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-processor/gr-diff-processor_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-processor/gr-diff-processor_test.js
@@ -1,42 +1,27 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-diff-processor test</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-diff-processor></gr-diff-processor>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-diff-processor.js';
import {GrDiffLine} from '../gr-diff/gr-diff-line.js';
import {GrDiffGroup} from '../gr-diff/gr-diff-group.js';
+const basicFixture = fixtureFromElement('gr-diff-processor');
+
suite('gr-diff-processor tests', () => {
const WHOLE_FILE = -1;
const loremIpsum =
@@ -47,19 +32,14 @@
'fugit assum per.';
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
- });
- teardown(() => {
- sandbox.restore();
});
suite('not logged in', () => {
setup(() => {
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.context = 4;
});
@@ -609,12 +589,12 @@
test('scrolling pauses rendering', () => {
const contentRow = {
ab: [
- '<!DOCTYPE html>',
- '<meta charset="utf-8">',
+ '',
+ '',
],
};
const content = _.times(200, _.constant(contentRow));
- sandbox.stub(element, 'async');
+ sinon.stub(element, 'async');
element._isScrolling = true;
element.process(content);
// Just the files group - no more processing during scrolling.
@@ -629,12 +609,12 @@
test('image diffs', () => {
const contentRow = {
ab: [
- '<!DOCTYPE html>',
- '<meta charset="utf-8">',
+ '',
+ '',
],
};
const content = _.times(200, _.constant(contentRow));
- sandbox.stub(element, 'async');
+ sinon.stub(element, 'async');
element.process(content, true);
assert.equal(element.groups.length, 1);
@@ -870,7 +850,7 @@
suite('_breakdown*', () => {
test('_breakdownChunk breaks down additions', () => {
- sandbox.spy(element, '_breakdown');
+ sinon.spy(element, '_breakdown');
const chunk = {b: ['blah', 'blah', 'blah']};
const result = element._breakdownChunk(chunk);
assert.deepEqual(result, [chunk]);
@@ -879,7 +859,7 @@
test('_breakdownChunk keeps due_to_rebase for broken down additions',
() => {
- sandbox.spy(element, '_breakdown');
+ sinon.spy(element, '_breakdown');
const chunk = {b: ['blah', 'blah', 'blah'], due_to_rebase: true};
const result = element._breakdownChunk(chunk);
for (const subResult of result) {
@@ -926,10 +906,10 @@
});
test('detaching cancels', () => {
- element = fixture('basic');
- sandbox.stub(element, 'cancel');
+ element = basicFixture.instantiate();
+ sinon.stub(element, 'cancel');
element.detached();
assert(element.cancel.called);
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection_test.html b/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection_test.js
similarity index 85%
rename from polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection_test.html
rename to polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection_test.js
index 1221b58..c37ac93 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection_test.js
@@ -1,33 +1,28 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import '../../../test/common-test-setup-karma.js';
+import './gr-diff-selection.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-diff-selection</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-diff-selection>
+// Splitting long lines in html into shorter rows breaks tests:
+// zero-length text nodes and new lines are not expected in some places
+/* eslint-disable max-len */
+const basicFixture = fixtureFromTemplate(html`
+<gr-diff-selection>
<table id="diffTable" class="side-by-side">
<tr class="diff-row">
<td class="blame" data-line-number="1"></td>
@@ -100,22 +95,18 @@
</tr>
</table>
</gr-diff-selection>
- </template>
-</test-fixture>
+`);
+/* eslint-enable max-len */
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-diff-selection.js';
suite('gr-diff-selection', () => {
let element;
- let sandbox;
const emulateCopyOn = function(target) {
const fakeEvent = {
target,
- preventDefault: sandbox.stub(),
+ preventDefault: sinon.stub(),
clipboardData: {
- setData: sandbox.stub(),
+ setData: sinon.stub(),
},
};
element._getCopyEventTarget.returns(target);
@@ -124,12 +115,12 @@
};
setup(() => {
- element = fixture('basic');
- sandbox = sinon.sandbox.create();
- sandbox.stub(element, '_getCopyEventTarget');
+ element = basicFixture.instantiate();
+
+ sinon.stub(element, '_getCopyEventTarget');
element._cachedDiffBuilder = {
- getLineElByChild: sandbox.stub().returns({}),
- getSideByLineEl: sandbox.stub(),
+ getLineElByChild: sinon.stub().returns({}),
+ getSideByLineEl: sinon.stub(),
diffElement: element.querySelector('#diffTable'),
};
element.diff = {
@@ -150,10 +141,6 @@
};
});
- teardown(() => {
- sandbox.restore();
- });
-
test('applies selected-left on left side click', () => {
element.classList.add('selected-right');
element._cachedDiffBuilder.getSideByLineEl.returns('left');
@@ -178,7 +165,7 @@
test('applies selected-blame on blame click', () => {
element.classList.add('selected-left');
element.diffBuilder.getLineElByChild.returns(null);
- sandbox.stub(element, '_elementDescendedFromClass',
+ sinon.stub(element, '_elementDescendedFromClass').callsFake(
(el, className) => className === 'blame');
MockInteractions.down(element);
assert.isTrue(
@@ -188,26 +175,26 @@
});
test('ignores copy for non-content Element', () => {
- sandbox.stub(element, '_getSelectedText');
+ sinon.stub(element, '_getSelectedText');
emulateCopyOn(element.querySelector('.not-diff-row'));
assert.isFalse(element._getSelectedText.called);
});
test('asks for text for left side Elements', () => {
element._cachedDiffBuilder.getSideByLineEl.returns('left');
- sandbox.stub(element, '_getSelectedText');
+ sinon.stub(element, '_getSelectedText');
emulateCopyOn(element.querySelector('div.contentText'));
assert.deepEqual(['left', false], element._getSelectedText.lastCall.args);
});
test('reacts to copy for content Elements', () => {
- sandbox.stub(element, '_getSelectedText');
+ sinon.stub(element, '_getSelectedText');
emulateCopyOn(element.querySelector('div.contentText'));
assert.isTrue(element._getSelectedText.called);
});
test('copy event is prevented for content Elements', () => {
- sandbox.stub(element, '_getSelectedText');
+ sinon.stub(element, '_getSelectedText');
element._cachedDiffBuilder.getSideByLineEl.returns('left');
element._getSelectedText.returns('test');
const event = emulateCopyOn(element.querySelector('div.contentText'));
@@ -215,7 +202,7 @@
});
test('inserts text into clipboard on copy', () => {
- sandbox.stub(element, '_getSelectedText').returns('the text');
+ sinon.stub(element, '_getSelectedText').returns('the text');
const event = emulateCopyOn(element.querySelector('div.contentText'));
assert.deepEqual(
['Text', 'the text'], event.clipboardData.setData.lastCall.args);
@@ -238,10 +225,11 @@
test('_setClasses removes before it ads', () => {
element.classList.add('selected-right');
- const addStub = sandbox.stub(element.classList, 'add');
- const removeStub = sandbox.stub(element.classList, 'remove', () => {
- assert.isFalse(addStub.called);
- });
+ const addStub = sinon.stub(element.classList, 'add');
+ const removeStub = sinon.stub(element.classList, 'remove').callsFake(
+ () => {
+ assert.isFalse(addStub.called);
+ });
element._setClasses(['selected-comment', 'selected-left']);
assert.isTrue(addStub.called);
assert.isTrue(removeStub.called);
@@ -303,7 +291,7 @@
test('defers to default behavior for textarea', () => {
element.classList.add('selected-left');
element.classList.remove('selected-right');
- const selectedTextSpy = sandbox.spy(element, '_getSelectedText');
+ const selectedTextSpy = sinon.spy(element, '_getSelectedText');
emulateCopyOn(element.querySelector('textarea'));
assert.isFalse(selectedTextSpy.called);
});
@@ -398,4 +386,4 @@
assert.deepEqual(element._linesCache, {left: null, right: null});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
index 19abdaf..ad72ee1 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
@@ -300,6 +300,13 @@
[this.Shortcut.TOGGLE_BLAME]: '_handleToggleBlame',
[this.Shortcut.TOGGLE_HIDE_ALL_COMMENT_THREADS]:
'_handleToggleHideAllCommentThreads',
+ [this.Shortcut.DIFF_AGAINST_BASE]: '_handleDiffAgainstBase',
+ [this.Shortcut.DIFF_AGAINST_LATEST]: '_handleDiffAgainstLatest',
+ [this.Shortcut.DIFF_BASE_AGAINST_LEFT]: '_handleDiffBaseAgainstLeft',
+ [this.Shortcut.DIFF_RIGHT_AGAINST_LATEST]:
+ '_handleDiffRightAgainstLatest',
+ [this.Shortcut.DIFF_BASE_AGAINST_LATEST]:
+ '_handleDiffBaseAgainstLatest',
// Final two are actually handled by gr-comment-thread.
[this.Shortcut.EXPAND_ALL_COMMENT_THREADS]: null,
@@ -556,7 +563,8 @@
this.$.cursor.moveToNextCommentThread();
} else {
if (this.modifierPressed(e)) { return; }
- this.$.cursor.moveToNextChunk();
+ this.$.cursor.moveToNextChunk(/* opt_clipToTop = */false,
+ /* opt_navigateToNextFile = */true);
}
}
@@ -669,10 +677,12 @@
_goToEditFile() {
// TODO(taoalpha): add a shortcut for editing
+ const cursorAddress = this.$.cursor.getAddress();
const editUrl = GerritNav.getEditUrlForDiff(
this._change,
this._path,
- this._patchRange.patchNum
+ this._patchRange.patchNum,
+ cursorAddress && cursorAddress.number
);
return GerritNav.navigateToRelativeUrl(editUrl);
}
@@ -841,7 +851,7 @@
_setReviewedObserver(_loggedIn, paramsRecord, _prefs) {
// Polymer 2: check for undefined
- if ([_loggedIn, paramsRecord, _prefs].some(arg => arg === undefined)) {
+ if ([_loggedIn, paramsRecord, _prefs].includes(undefined)) {
return;
}
@@ -898,7 +908,7 @@
}
_getDiffUrl(change, patchRange, path) {
- if ([change, patchRange, path].some(arg => arg === undefined)) {
+ if ([change, patchRange, path].includes(undefined)) {
return '';
}
return GerritNav.getUrlForDiff(change, path, patchRange.patchNum,
@@ -939,7 +949,7 @@
}
_getChangePath(change, patchRange, revisions) {
- if ([change, patchRange].some(arg => arg === undefined)) {
+ if ([change, patchRange].includes(undefined)) {
return '';
}
const range = this._getChangeUrlRange(patchRange, revisions);
@@ -962,7 +972,7 @@
files,
patchNum,
changeComments,
- ].some(arg => arg === undefined)) {
+ ].includes(undefined)) {
return;
}
@@ -1059,8 +1069,8 @@
}
}
- _computeModeSelectHideClass(isImageDiff) {
- return isImageDiff ? 'hide' : '';
+ _computeModeSelectHideClass(_diff) {
+ return _diff.binary ? 'hide' : '';
}
_onLineSelected(e, detail) {
@@ -1156,7 +1166,7 @@
path,
patchRange,
projectConfig,
- ].some(arg => arg === undefined)) {
+ ].includes(undefined)) {
return undefined;
}
@@ -1190,7 +1200,7 @@
commentMap,
fileList,
path,
- ].some(arg => arg === undefined)) {
+ ].includes(undefined)) {
return undefined;
}
@@ -1286,6 +1296,87 @@
this.toggleClass('hideComments');
}
+ _handleDiffAgainstBase(e) {
+ if (this.shouldSuppressKeyboardShortcut(e)) { return; }
+ if (this.patchNumEquals(this._patchRange.basePatchNum, 'PARENT')) {
+ this.dispatchEvent(new CustomEvent('show-alert', {
+ detail: {
+ message: 'Base is already selected.',
+ },
+ composed: true, bubbles: true,
+ }));
+ return;
+ }
+ GerritNav.navigateToDiff(
+ this._change, this._path, this._patchRange.patchNum);
+ }
+
+ _handleDiffBaseAgainstLeft(e) {
+ if (this.shouldSuppressKeyboardShortcut(e)) { return; }
+ if (this.patchNumEquals(this._patchRange.basePatchNum, 'PARENT')) {
+ this.dispatchEvent(new CustomEvent('show-alert', {
+ detail: {
+ message: 'Left is already base.',
+ },
+ composed: true, bubbles: true,
+ }));
+ return;
+ }
+ GerritNav.navigateToDiff(this._change, this._path,
+ this._patchRange.basePatchNum);
+ }
+
+ _handleDiffAgainstLatest(e) {
+ if (this.shouldSuppressKeyboardShortcut(e)) { return; }
+
+ const latestPatchNum = this.computeLatestPatchNum(this._allPatchSets);
+ if (this.patchNumEquals(this._patchRange.patchNum, latestPatchNum)) {
+ this.dispatchEvent(new CustomEvent('show-alert', {
+ detail: {
+ message: 'Latest is already selected.',
+ },
+ composed: true, bubbles: true,
+ }));
+ return;
+ }
+
+ GerritNav.navigateToDiff(
+ this._change, this._path, latestPatchNum,
+ this._patchRange.basePatchNum);
+ }
+
+ _handleDiffRightAgainstLatest(e) {
+ if (this.shouldSuppressKeyboardShortcut(e)) { return; }
+ const latestPatchNum = this.computeLatestPatchNum(this._allPatchSets);
+ if (this.patchNumEquals(this._patchRange.patchNum, latestPatchNum)) {
+ this.dispatchEvent(new CustomEvent('show-alert', {
+ detail: {
+ message: 'Right is already latest.',
+ },
+ composed: true, bubbles: true,
+ }));
+ return;
+ }
+ GerritNav.navigateToDiff(this._change, this._path, latestPatchNum,
+ this._patchRange.patchNum);
+ }
+
+ _handleDiffBaseAgainstLatest(e) {
+ if (this.shouldSuppressKeyboardShortcut(e)) { return; }
+ const latestPatchNum = this.computeLatestPatchNum(this._allPatchSets);
+ if (this.patchNumEquals(this._patchRange.patchNum, latestPatchNum) &&
+ this.patchNumEquals(this._patchRange.basePatchNum, 'PARENT')) {
+ this.dispatchEvent(new CustomEvent('show-alert', {
+ detail: {
+ message: 'Already diffing base against latest.',
+ },
+ composed: true, bubbles: true,
+ }));
+ return;
+ }
+ GerritNav.navigateToDiff(this._change, this._path, latestPatchNum);
+ }
+
_computeBlameLoaderClass(isImageDiff, path) {
return !this.isMagicPath(path) && !isImageDiff ? 'show' : '';
}
@@ -1296,7 +1387,7 @@
_computeFileNum(file, files) {
// Polymer 2: check for undefined
- if ([file, files].some(arg => arg === undefined)) {
+ if ([file, files].includes(undefined)) {
return undefined;
}
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_html.js b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_html.js
index 3d30f77..b05a4ac 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_html.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_html.js
@@ -325,9 +325,7 @@
</span>
</template>
<span class="separator"></span>
- <div
- class$="diffModeSelector [[_computeModeSelectHideClass(_isImageDiff)]]"
- >
+ <div class$="diffModeSelector [[_computeModeSelectHideClass(_diff)]]">
<span>Diff view:</span>
<gr-diff-mode-selector
id="modeSelect"
@@ -422,6 +420,7 @@
<gr-diff-cursor
id="cursor"
scroll-top-margin="[[_scrollTopMargin]]"
+ on-navigate-to-next-unreviewed-file="_handleNextUnreviewedFile"
></gr-diff-cursor>
<gr-comment-api id="commentAPI"></gr-comment-api>
`;
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.html b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.js
similarity index 78%
rename from polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.html
rename to polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.js
index 21d1144..8646336 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.js
@@ -1,83 +1,68 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2015 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-diff-view</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<script src="/node_modules/page/page.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-diff-view></gr-diff-view>
- </template>
-</test-fixture>
-
-<test-fixture id="blank">
- <template>
- <div></div>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-diff-view.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
-import {KeyboardShortcutBinder} from '../../../behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
import {ChangeStatus} from '../../../constants/constants.js';
+import {TestKeyboardShortcutBinder} from '../../../test/test-utils';
+
+const basicFixture = fixtureFromElement('gr-diff-view');
+
+const blankFixture = fixtureFromElement('div');
suite('gr-diff-view tests', () => {
suite('basic tests', () => {
- const kb = KeyboardShortcutBinder;
- kb.bindShortcut(kb.Shortcut.LEFT_PANE, 'shift+left');
- kb.bindShortcut(kb.Shortcut.RIGHT_PANE, 'shift+right');
- kb.bindShortcut(kb.Shortcut.NEXT_LINE, 'j', 'down');
- kb.bindShortcut(kb.Shortcut.PREV_LINE, 'k', 'up');
- kb.bindShortcut(kb.Shortcut.NEXT_FILE_WITH_COMMENTS, 'shift+j');
- kb.bindShortcut(kb.Shortcut.PREV_FILE_WITH_COMMENTS, 'shift+k');
- kb.bindShortcut(kb.Shortcut.NEW_COMMENT, 'c');
- kb.bindShortcut(kb.Shortcut.SAVE_COMMENT, 'ctrl+s');
- kb.bindShortcut(kb.Shortcut.NEXT_FILE, ']');
- kb.bindShortcut(kb.Shortcut.PREV_FILE, '[');
- kb.bindShortcut(kb.Shortcut.NEXT_CHUNK, 'n');
- kb.bindShortcut(kb.Shortcut.NEXT_COMMENT_THREAD, 'shift+n');
- kb.bindShortcut(kb.Shortcut.PREV_CHUNK, 'p');
- kb.bindShortcut(kb.Shortcut.PREV_COMMENT_THREAD, 'shift+p');
- kb.bindShortcut(kb.Shortcut.OPEN_REPLY_DIALOG, 'a');
- kb.bindShortcut(kb.Shortcut.TOGGLE_LEFT_PANE, 'shift+a');
- kb.bindShortcut(kb.Shortcut.UP_TO_CHANGE, 'u');
- kb.bindShortcut(kb.Shortcut.OPEN_DIFF_PREFS, ',');
- kb.bindShortcut(kb.Shortcut.TOGGLE_DIFF_MODE, 'm');
- kb.bindShortcut(kb.Shortcut.TOGGLE_FILE_REVIEWED, 'r');
- kb.bindShortcut(kb.Shortcut.EXPAND_ALL_DIFF_CONTEXT, 'shift+x');
- kb.bindShortcut(kb.Shortcut.EXPAND_ALL_COMMENT_THREADS, 'e');
- kb.bindShortcut(kb.Shortcut.TOGGLE_HIDE_ALL_COMMENT_THREADS, 'h');
- kb.bindShortcut(kb.Shortcut.COLLAPSE_ALL_COMMENT_THREADS, 'shift+e');
- kb.bindShortcut(kb.Shortcut.NEXT_UNREVIEWED_FILE, 'shift+m');
- kb.bindShortcut(kb.Shortcut.TOGGLE_BLAME, 'b');
-
let element;
- let sandbox;
+
+ suiteSetup(() => {
+ const kb = TestKeyboardShortcutBinder.push();
+ kb.bindShortcut(kb.Shortcut.LEFT_PANE, 'shift+left');
+ kb.bindShortcut(kb.Shortcut.RIGHT_PANE, 'shift+right');
+ kb.bindShortcut(kb.Shortcut.NEXT_LINE, 'j', 'down');
+ kb.bindShortcut(kb.Shortcut.PREV_LINE, 'k', 'up');
+ kb.bindShortcut(kb.Shortcut.NEXT_FILE_WITH_COMMENTS, 'shift+j');
+ kb.bindShortcut(kb.Shortcut.PREV_FILE_WITH_COMMENTS, 'shift+k');
+ kb.bindShortcut(kb.Shortcut.NEW_COMMENT, 'c');
+ kb.bindShortcut(kb.Shortcut.SAVE_COMMENT, 'ctrl+s');
+ kb.bindShortcut(kb.Shortcut.NEXT_FILE, ']');
+ kb.bindShortcut(kb.Shortcut.PREV_FILE, '[');
+ kb.bindShortcut(kb.Shortcut.NEXT_CHUNK, 'n');
+ kb.bindShortcut(kb.Shortcut.NEXT_COMMENT_THREAD, 'shift+n');
+ kb.bindShortcut(kb.Shortcut.PREV_CHUNK, 'p');
+ kb.bindShortcut(kb.Shortcut.PREV_COMMENT_THREAD, 'shift+p');
+ kb.bindShortcut(kb.Shortcut.OPEN_REPLY_DIALOG, 'a');
+ kb.bindShortcut(kb.Shortcut.TOGGLE_LEFT_PANE, 'shift+a');
+ kb.bindShortcut(kb.Shortcut.UP_TO_CHANGE, 'u');
+ kb.bindShortcut(kb.Shortcut.OPEN_DIFF_PREFS, ',');
+ kb.bindShortcut(kb.Shortcut.TOGGLE_DIFF_MODE, 'm');
+ kb.bindShortcut(kb.Shortcut.TOGGLE_FILE_REVIEWED, 'r');
+ kb.bindShortcut(kb.Shortcut.EXPAND_ALL_DIFF_CONTEXT, 'shift+x');
+ kb.bindShortcut(kb.Shortcut.EXPAND_ALL_COMMENT_THREADS, 'e');
+ kb.bindShortcut(kb.Shortcut.TOGGLE_HIDE_ALL_COMMENT_THREADS, 'h');
+ kb.bindShortcut(kb.Shortcut.COLLAPSE_ALL_COMMENT_THREADS, 'shift+e');
+ kb.bindShortcut(kb.Shortcut.NEXT_UNREVIEWED_FILE, 'shift+m');
+ kb.bindShortcut(kb.Shortcut.TOGGLE_BLAME, 'b');
+ });
+
+ suiteTeardown(() => {
+ TestKeyboardShortcutBinder.pop();
+ });
const PARENT = 'PARENT';
@@ -93,8 +78,6 @@
}
setup(() => {
- sandbox = sinon.sandbox.create();
-
stub('gr-rest-api-interface', {
getConfig() {
return Promise.resolve({change: {}});
@@ -127,18 +110,14 @@
return Promise.resolve([]);
},
});
- element = fixture('basic');
+ element = basicFixture.instantiate();
return element._loadComments();
});
- teardown(() => {
- sandbox.restore();
- });
-
test('params change triggers diffViewDisplayed()', () => {
- sandbox.stub(element.reporting, 'diffViewDisplayed');
- sandbox.stub(element.$.diffHost, 'reload').returns(Promise.resolve());
- sandbox.spy(element, '_paramsChanged');
+ sinon.stub(element.reporting, 'diffViewDisplayed');
+ sinon.stub(element.$.diffHost, 'reload').returns(Promise.resolve());
+ sinon.spy(element, '_paramsChanged');
element.params = {
view: GerritNav.View.DIFF,
changeNum: '42',
@@ -155,10 +134,10 @@
test('params change cases blame to load if it was set to true', () => {
// Blame loads for subsequent files if it was loaded for one file
element._isBlameLoaded = true;
- sandbox.stub(element.reporting, 'diffViewDisplayed');
- sandbox.stub(element, '_loadBlame');
- sandbox.stub(element.$.diffHost, 'reload').returns(Promise.resolve());
- sandbox.spy(element, '_paramsChanged');
+ sinon.stub(element.reporting, 'diffViewDisplayed');
+ sinon.stub(element, '_loadBlame');
+ sinon.stub(element.$.diffHost, 'reload').returns(Promise.resolve());
+ sinon.spy(element, '_paramsChanged');
element.params = {
view: GerritNav.View.DIFF,
changeNum: '42',
@@ -174,7 +153,7 @@
});
test('toggle left diff with a hotkey', () => {
- const toggleLeftDiffStub = sandbox.stub(
+ const toggleLeftDiffStub = sinon.stub(
element.$.diffHost, 'toggleLeftDiff');
MockInteractions.pressAndReleaseKeyOn(element, 65, 'shift', 'a');
assert.isTrue(toggleLeftDiffStub.calledOnce);
@@ -198,8 +177,8 @@
element.changeViewState.selectedFileIndex = 1;
element._loggedIn = true;
- const diffNavStub = sandbox.stub(GerritNav, 'navigateToDiff');
- const changeNavStub = sandbox.stub(GerritNav, 'navigateToChange');
+ const diffNavStub = sinon.stub(GerritNav, 'navigateToDiff');
+ const changeNavStub = sinon.stub(GerritNav, 'navigateToChange');
MockInteractions.pressAndReleaseKeyOn(element, 85, null, 'u');
assert(changeNavStub.lastCall.calledWith(element._change),
@@ -233,7 +212,7 @@
assert.isTrue(element._loading);
const showPrefsStub =
- sandbox.stub(element.$.diffPreferencesDialog, 'open',
+ sinon.stub(element.$.diffPreferencesDialog, 'open').callsFake(
() => Promise.resolve());
MockInteractions.pressAndReleaseKeyOn(element, 188, null, ',');
@@ -243,24 +222,24 @@
MockInteractions.pressAndReleaseKeyOn(element, 188, null, ',');
assert(showPrefsStub.calledOnce);
- let scrollStub = sandbox.stub(element.$.cursor, 'moveToNextChunk');
+ let scrollStub = sinon.stub(element.$.cursor, 'moveToNextChunk');
MockInteractions.pressAndReleaseKeyOn(element, 78, null, 'n');
assert(scrollStub.calledOnce);
- scrollStub = sandbox.stub(element.$.cursor, 'moveToPreviousChunk');
+ scrollStub = sinon.stub(element.$.cursor, 'moveToPreviousChunk');
MockInteractions.pressAndReleaseKeyOn(element, 80, null, 'p');
assert(scrollStub.calledOnce);
- scrollStub = sandbox.stub(element.$.cursor, 'moveToNextCommentThread');
+ scrollStub = sinon.stub(element.$.cursor, 'moveToNextCommentThread');
MockInteractions.pressAndReleaseKeyOn(element, 78, 'shift', 'n');
assert(scrollStub.calledOnce);
- scrollStub = sandbox.stub(element.$.cursor,
+ scrollStub = sinon.stub(element.$.cursor,
'moveToPreviousCommentThread');
MockInteractions.pressAndReleaseKeyOn(element, 80, 'shift', 'p');
assert(scrollStub.calledOnce);
- const computeContainerClassStub = sandbox.stub(element.$.diffHost.$.diff,
+ const computeContainerClassStub = sinon.stub(element.$.diffHost.$.diff,
'_computeContainerClass');
MockInteractions.pressAndReleaseKeyOn(element, 74, null, 'j');
assert(computeContainerClassStub.lastCall.calledWithExactly(
@@ -270,23 +249,101 @@
assert(computeContainerClassStub.lastCall.calledWithExactly(
false, 'SIDE_BY_SIDE', false));
- sandbox.stub(element, '_setReviewed');
+ sinon.stub(element, '_setReviewed');
+ sinon.spy(element, '_handleToggleFileReviewed');
element.$.reviewed.checked = false;
MockInteractions.pressAndReleaseKeyOn(element, 82, 'shift', 'r');
assert.isFalse(element._setReviewed.called);
+ assert.isTrue(element._handleToggleFileReviewed.calledOnce);
MockInteractions.pressAndReleaseKeyOn(element, 82, null, 'r');
+ assert.isTrue(element._handleToggleFileReviewed.calledTwice);
assert.isTrue(element._setReviewed.called);
assert.equal(element._setReviewed.lastCall.args[0], true);
});
test('shift+x shortcut expands all diff context', () => {
- const expandStub = sandbox.stub(element.$.diffHost, 'expandAllContext');
+ const expandStub = sinon.stub(element.$.diffHost, 'expandAllContext');
MockInteractions.pressAndReleaseKeyOn(element, 88, 'shift', 'x');
flushAsynchronousOperations();
assert.isTrue(expandStub.called);
});
+ test('diff against base', () => {
+ element._patchRange = {
+ basePatchNum: '5',
+ patchNum: '10',
+ };
+ sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
+ const diffNavStub = sinon.stub(GerritNav, 'navigateToDiff');
+ element._handleDiffAgainstBase(new CustomEvent(''));
+ const args = diffNavStub.getCall(0).args;
+ assert.equal(args[2], 10);
+ assert.isNotOk(args[3]);
+ });
+
+ test('diff against latest', () => {
+ element._patchRange = {
+ basePatchNum: '5',
+ patchNum: '10',
+ };
+ sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
+ sinon.stub(element, 'computeLatestPatchNum').returns(12);
+ const diffNavStub = sinon.stub(GerritNav, 'navigateToDiff');
+ element._handleDiffAgainstLatest(new CustomEvent(''));
+ const args = diffNavStub.getCall(0).args;
+ assert.equal(args[2], 12);
+ assert.equal(args[3], 5);
+ });
+
+ test('_handleDiffBaseAgainstLeft', () => {
+ element._changeNum = '1';
+ element._patchRange = {
+ patchNum: 3,
+ basePatchNum: 1,
+ };
+ sinon.stub(element, 'computeLatestPatchNum').returns(10);
+ sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
+ const diffNavStub = sinon.stub(GerritNav, 'navigateToDiff');
+ element._handleDiffBaseAgainstLeft(new CustomEvent(''));
+ assert(diffNavStub.called);
+ const args = diffNavStub.getCall(0).args;
+ assert.equal(args[2], 1);
+ assert.isNotOk(args[3]);
+ });
+
+ test('_handleDiffRightAgainstLatest', () => {
+ element._changeNum = '1';
+ element._patchRange = {
+ basePatchNum: 1,
+ patchNum: 3,
+ };
+ sinon.stub(element, 'computeLatestPatchNum').returns(10);
+ sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
+ const diffNavStub = sinon.stub(GerritNav, 'navigateToDiff');
+ element._handleDiffRightAgainstLatest(new CustomEvent(''));
+ assert(diffNavStub.called);
+ const args = diffNavStub.getCall(0).args;
+ assert.equal(args[2], 10);
+ assert.equal(args[3], 3);
+ });
+
+ test('_handleDiffBaseAgainstLatest', () => {
+ element._changeNum = '1';
+ element._patchRange = {
+ basePatchNum: 1,
+ patchNum: 3,
+ };
+ sinon.stub(element, 'computeLatestPatchNum').returns(10);
+ sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
+ const diffNavStub = sinon.stub(GerritNav, 'navigateToDiff');
+ element._handleDiffBaseAgainstLatest(new CustomEvent(''));
+ assert(diffNavStub.called);
+ const args = diffNavStub.getCall(0).args;
+ assert.equal(args[2], 10);
+ assert.isNotOk(args[3]);
+ });
+
test('keyboard shortcuts with patch range', () => {
element._changeNum = '42';
element._patchRange = {
@@ -304,8 +361,8 @@
['chell.go', 'glados.txt', 'wheatley.md']);
element._path = 'glados.txt';
- const diffNavStub = sandbox.stub(GerritNav, 'navigateToDiff');
- const changeNavStub = sandbox.stub(GerritNav, 'navigateToChange');
+ const diffNavStub = sinon.stub(GerritNav, 'navigateToDiff');
+ const changeNavStub = sinon.stub(GerritNav, 'navigateToChange');
MockInteractions.pressAndReleaseKeyOn(element, 65, null, 'a');
assert.isTrue(changeNavStub.notCalled, 'The `a` keyboard shortcut ' +
@@ -372,8 +429,8 @@
['chell.go', 'glados.txt', 'wheatley.md']);
element._path = 'glados.txt';
- const diffNavStub = sandbox.stub(GerritNav, 'navigateToDiff');
- const changeNavStub = sandbox.stub(GerritNav, 'navigateToChange');
+ const diffNavStub = sinon.stub(GerritNav, 'navigateToDiff');
+ const changeNavStub = sinon.stub(GerritNav, 'navigateToChange');
MockInteractions.pressAndReleaseKeyOn(element, 65, null, 'a');
assert.isTrue(changeNavStub.notCalled, 'The `a` keyboard shortcut ' +
@@ -433,7 +490,7 @@
b: {_number: 2, commit: {parents: []}},
},
};
- const redirectStub = sandbox.stub(GerritNav, 'navigateToRelativeUrl');
+ const redirectStub = sinon.stub(GerritNav, 'navigateToRelativeUrl');
flush(() => {
const editBtn = element.shadowRoot
.querySelector('.editButton gr-button');
@@ -450,6 +507,43 @@
});
});
+ test('edit should redirect to edit page with line number', done => {
+ const lineNumber = 42;
+ element._loggedIn = true;
+ element._path = 't.txt';
+ element._patchRange = {
+ basePatchNum: PARENT,
+ patchNum: '1',
+ };
+ element._change = {
+ _number: 42,
+ project: 'gerrit',
+ status: ChangeStatus.NEW,
+ revisions: {
+ a: {_number: 1, commit: {parents: []}},
+ b: {_number: 2, commit: {parents: []}},
+ },
+ };
+ sinon.stub(element.$.cursor, 'getAddress')
+ .returns({number: lineNumber, isLeftSide: false});
+ const redirectStub = sinon.stub(GerritNav, 'navigateToRelativeUrl');
+ flush(() => {
+ const editBtn = element.shadowRoot
+ .querySelector('.editButton gr-button');
+ assert.isTrue(!!editBtn);
+ MockInteractions.tap(editBtn);
+ assert.isTrue(redirectStub.called);
+ assert.isTrue(redirectStub.lastCall.calledWithExactly(
+ GerritNav.getEditUrlForDiff(
+ element._change,
+ element._path,
+ element._patchRange.patchNum,
+ lineNumber
+ )));
+ done();
+ });
+ });
+
function isEditVisibile({loggedIn, changeStatus}) {
return new Promise(resolve => {
element._loggedIn = loggedIn;
@@ -543,8 +637,8 @@
});
test('prefsButton opens gr-diff-preferences', () => {
- const handlePrefsTapSpy = sandbox.spy(element, '_handlePrefsTap');
- const overlayOpenStub = sandbox.stub(element.$.diffPreferencesDialog,
+ const handlePrefsTapSpy = sinon.spy(element, '_handlePrefsTap');
+ const overlayOpenStub = sinon.stub(element.$.diffPreferencesDialog,
'open');
const prefsButton =
dom(element.root).querySelector('.prefsButton');
@@ -559,9 +653,9 @@
const path = '/test';
element.$.commentAPI.loadAll().then(comments => {
const commentCountStub =
- sandbox.stub(comments, 'computeCommentCount');
+ sinon.stub(comments, 'computeCommentCount');
const unresolvedCountStub =
- sandbox.stub(comments, 'computeUnresolvedNum');
+ sinon.stub(comments, 'computeUnresolvedNum');
commentCountStub.withArgs({patchNum: 1, path}).returns(0);
commentCountStub.withArgs({patchNum: 2, path}).returns(1);
commentCountStub.withArgs({patchNum: 3, path}).returns(2);
@@ -595,14 +689,14 @@
suite('url params', () => {
setup(() => {
- sandbox.stub(
+ sinon.stub(
GerritNav,
- 'getUrlForDiff',
- (c, p, pn, bpn) => `${c._number}-${p}-${pn}-${bpn}`);
- sandbox.stub(
+ 'getUrlForDiff')
+ .callsFake((c, p, pn, bpn) => `${c._number}-${p}-${pn}-${bpn}`);
+ sinon.stub(
GerritNav
- , 'getUrlForChange',
- (c, pn, bpn) => `${c._number}-${pn}-${bpn}`);
+ , 'getUrlForChange')
+ .callsFake((c, pn, bpn) => `${c._number}-${pn}-${bpn}`);
});
test('_formattedFiles', () => {
@@ -729,7 +823,7 @@
});
test('_handlePatchChange calls navigateToDiff correctly', () => {
- const navigateStub = sandbox.stub(GerritNav, 'navigateToDiff');
+ const navigateStub = sinon.stub(GerritNav, 'navigateToDiff');
element._change = {_number: 321, project: 'foo/bar'};
element._path = 'path/to/file.txt';
@@ -751,12 +845,12 @@
});
test('_prefs.manual_review is respected', () => {
- const saveReviewedStub = sandbox.stub(element, '_saveReviewedState',
- () => Promise.resolve());
- const getReviewedStub = sandbox.stub(element, '_getReviewedStatus',
- () => Promise.resolve());
+ const saveReviewedStub = sinon.stub(element, '_saveReviewedState')
+ .callsFake(() => Promise.resolve());
+ const getReviewedStub = sinon.stub(element, '_getReviewedStatus')
+ .callsFake(() => Promise.resolve());
- sandbox.stub(element.$.diffHost, 'reload');
+ sinon.stub(element.$.diffHost, 'reload');
element._loggedIn = true;
element.params = {
view: GerritNav.View.DIFF,
@@ -779,9 +873,9 @@
});
test('file review status', () => {
- const saveReviewedStub = sandbox.stub(element, '_saveReviewedState',
- () => Promise.resolve());
- sandbox.stub(element.$.diffHost, 'reload');
+ const saveReviewedStub = sinon.stub(element, '_saveReviewedState')
+ .callsFake(() => Promise.resolve());
+ sinon.stub(element.$.diffHost, 'reload');
element._loggedIn = true;
element.params = {
@@ -816,7 +910,7 @@
});
test('file review status with edit loaded', () => {
- const saveReviewedStub = sandbox.stub(element, '_saveReviewedState');
+ const saveReviewedStub = sinon.stub(element, '_saveReviewedState');
element._patchRange = {patchNum: element.EDIT_NAME};
flushAsynchronousOperations();
@@ -827,8 +921,8 @@
});
test('hash is determined from params', done => {
- sandbox.stub(element.$.diffHost, 'reload');
- sandbox.stub(element, '_initCursor');
+ sinon.stub(element.$.diffHost, 'reload');
+ sinon.stub(element, '_initCursor');
element._loggedIn = true;
element.params = {
@@ -875,11 +969,12 @@
const prefsPromise = new Promise(resolve => {
resolvePrefs = resolve;
});
- sandbox.stub(element.$.restAPI, 'getPreferences', () => prefsPromise);
+ sinon.stub(element.$.restAPI, 'getPreferences')
+ .callsFake(() => prefsPromise);
// Attach a new gr-diff-view so we can intercept the preferences fetch.
const view = document.createElement('gr-diff-view');
- fixture('blank').appendChild(view);
+ blankFixture.instantiate().appendChild(view);
flushAsynchronousOperations();
// At this point the diff mode doesn't yet have the user's preference.
@@ -891,11 +986,22 @@
assert.equal(element._getDiffViewMode(), 'SIDE_BY_SIDE');
});
+ test('diff mode selector should be hidden for binary', done => {
+ element._diff = {binary: true, content: []};
+
+ flush(() => {
+ const diffModeSelector = element.shadowRoot
+ .querySelector('.diffModeSelector');
+ assert.isTrue(diffModeSelector.classList.contains('hide'));
+ done();
+ });
+ });
+
suite('_commitRange', () => {
setup(() => {
- sandbox.stub(element.$.diffHost, 'reload');
- sandbox.stub(element, '_initCursor');
- sandbox.stub(element, '_getChangeDetail').returns(Promise.resolve({
+ sinon.stub(element.$.diffHost, 'reload');
+ sinon.stub(element, '_initCursor');
+ sinon.stub(element, '_getChangeDetail').returns(Promise.resolve({
_number: 42,
revisions: {
'commit-sha-1': {
@@ -991,9 +1097,9 @@
});
test('_onLineSelected', () => {
- const getUrlStub = sandbox.stub(GerritNav, 'getUrlForDiffById');
- const replaceStateStub = sandbox.stub(history, 'replaceState');
- sandbox.stub(element.$.cursor, 'getAddress')
+ const getUrlStub = sinon.stub(GerritNav, 'getUrlForDiffById');
+ const replaceStateStub = sinon.stub(history, 'replaceState');
+ sinon.stub(element.$.cursor, 'getAddress')
.returns({number: 123, isLeftSide: false});
element._changeNum = 321;
@@ -1012,10 +1118,10 @@
});
test('_onLineSelected w/o line address', () => {
- const getUrlStub = sandbox.stub(GerritNav, 'getUrlForDiffById');
- sandbox.stub(history, 'replaceState');
- sandbox.stub(element.$.cursor, 'moveToLineNumber');
- sandbox.stub(element.$.cursor, 'getAddress').returns(null);
+ const getUrlStub = sinon.stub(GerritNav, 'getUrlForDiffById');
+ sinon.stub(history, 'replaceState');
+ sinon.stub(element.$.cursor, 'moveToLineNumber');
+ sinon.stub(element.$.cursor, 'getAddress').returns(null);
element._changeNum = 321;
element._change = {_number: 321, project: 'foo/bar'};
element._patchRange = {basePatchNum: '3', patchNum: '5'};
@@ -1039,7 +1145,7 @@
});
test('_handleToggleDiffMode', () => {
- sandbox.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
+ sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
const e = {preventDefault: () => {}};
// Initial state.
assert.equal(element._getDiffViewMode(), 'SIDE_BY_SIDE');
@@ -1060,11 +1166,11 @@
});
test('has paths', done => {
- sandbox.stub(element, '_getPaths').returns({
+ sinon.stub(element, '_getPaths').returns({
'path/to/file/one.cpp': [{patch_set: 3, message: 'lorem'}],
'path-to/file/two.py': [{patch_set: 5, message: 'ipsum'}],
});
- sandbox.stub(element, '_getCommentsForPath').returns({meta: {}});
+ sinon.stub(element, '_getCommentsForPath').returns({meta: {}});
element._changeNum = '42';
element._patchRange = {
basePatchNum: '3',
@@ -1127,8 +1233,8 @@
let navToDiffStub;
setup(() => {
- navToChangeStub = sandbox.stub(element, '_navToChangeView');
- navToDiffStub = sandbox.stub(GerritNav, 'navigateToDiff');
+ navToChangeStub = sinon.stub(element, '_navToChangeView');
+ navToDiffStub = sinon.stub(GerritNav, 'navigateToDiff');
element._files = getFilesFromFileList([
'path/one.jpg', 'path/two.m4v', 'path/three.wav',
]);
@@ -1230,7 +1336,7 @@
const promises = [];
element.$.restAPI.getReviewedFiles.restore();
- sandbox.stub(element.$.restAPI, 'getReviewedFiles')
+ sinon.stub(element.$.restAPI, 'getReviewedFiles')
.returns(Promise.resolve(['path']));
promises.push(element._getReviewedStatus(true, null, null, 'path')
@@ -1247,14 +1353,15 @@
suite('blame', () => {
test('toggle blame with button', () => {
- const toggleBlame = sandbox.stub(
- element.$.diffHost, 'loadBlame', () => Promise.resolve());
+ const toggleBlame = sinon.stub(
+ element.$.diffHost, 'loadBlame')
+ .callsFake(() => Promise.resolve());
MockInteractions.tap(element.$.toggleBlame);
assert.isTrue(toggleBlame.calledOnce);
});
test('toggle blame with shortcut', () => {
- const toggleBlame = sandbox.stub(
- element.$.diffHost, 'loadBlame', () => Promise.resolve());
+ const toggleBlame = sinon.stub(
+ element.$.diffHost, 'loadBlame').callsFake(() => Promise.resolve());
MockInteractions.pressAndReleaseKeyOn(element, 66, null, 'b');
assert.isTrue(toggleBlame.calledOnce);
});
@@ -1271,7 +1378,7 @@
};
test('reviewed checkbox', () => {
- sandbox.stub(element, '_handlePatchChange');
+ sinon.stub(element, '_handlePatchChange');
element._patchRange = {patchNum: '1'};
// Reviewed checkbox should be shown.
assert.isTrue(isVisible(element.$.reviewed));
@@ -1283,9 +1390,9 @@
});
test('_paramsChanged sets in projectLookup', () => {
- sandbox.stub(element, '_getLineOfInterest');
- sandbox.stub(element, '_initCursor');
- const setStub = sandbox.stub(element.$.restAPI, 'setInProjectLookup');
+ sinon.stub(element, '_getLineOfInterest');
+ sinon.stub(element, '_initCursor');
+ const setStub = sinon.stub(element.$.restAPI, 'setInProjectLookup');
element._paramsChanged({
view: GerritNav.View.DIFF,
changeNum: 101,
@@ -1300,8 +1407,8 @@
element._files = getFilesFromFileList(['file1', 'file2', 'file3']);
element._reviewedFiles = new Set(['file1', 'file2']);
element._path = 'file1';
- const reviewedStub = sandbox.stub(element, '_setReviewed');
- const navStub = sandbox.stub(element, '_navToFile');
+ const reviewedStub = sinon.stub(element, '_setReviewed');
+ const navStub = sinon.stub(element, '_navToFile');
MockInteractions.pressAndReleaseKeyOn(element, 77, 'shift', 'm');
flushAsynchronousOperations();
@@ -1315,9 +1422,9 @@
test('File change should trigger navigateToDiff once', () => {
element._files = getFilesFromFileList(['file1', 'file2', 'file3']);
- sandbox.stub(element, '_getLineOfInterest');
- sandbox.stub(element, '_initCursor');
- sandbox.stub(GerritNav, 'navigateToDiff');
+ sinon.stub(element, '_getLineOfInterest');
+ sinon.stub(element, '_initCursor');
+ sinon.stub(GerritNav, 'navigateToDiff');
// Load file1
element._paramsChanged({
@@ -1443,10 +1550,8 @@
});
suite('gr-diff-view tests unmodified files with comments', () => {
- let sandbox;
let element;
setup(() => {
- sandbox = sinon.sandbox.create();
const changedFiles = {
'file1.txt': {},
'a/b/test.c': {},
@@ -1463,14 +1568,10 @@
getDiffDrafts() { return Promise.resolve({}); },
getReviewedFiles() { return Promise.resolve([]); },
});
- element = fixture('basic');
+ element = basicFixture.instantiate();
return element._loadComments();
});
- teardown(() => {
- sandbox.restore();
- });
-
test('_getFiles add files with comments without changes', () => {
const patchChangeRecord = {
base: {
@@ -1479,7 +1580,7 @@
},
};
const changeComments = {
- getPaths: sandbox.stub().returns({
+ getPaths: sinon.stub().returns({
'file2.txt': {},
'file1.txt': {},
}),
@@ -1498,4 +1599,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff-group_test.html b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff-group_test.js
similarity index 86%
rename from polygerrit-ui/app/elements/diff/gr-diff/gr-diff-group_test.html
rename to polygerrit-ui/app/elements/diff/gr-diff/gr-diff-group_test.js
index d50a7f4..d72f981 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff-group_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff-group_test.js
@@ -1,30 +1,21 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-diff-group</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import {GrDiffLine} from './gr-diff-line.js';
import {GrDiffGroup} from './gr-diff-group.js';
@@ -206,4 +197,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
index 0942646..252b9bc 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
@@ -299,7 +299,7 @@
_enableSelectionObserver(loggedIn, isAttached) {
// Polymer 2: check for undefined
- if ([loggedIn, isAttached].some(arg => arg === undefined)) {
+ if ([loggedIn, isAttached].includes(undefined)) {
return;
}
@@ -828,6 +828,15 @@
const commentSide = threadEl.getAttribute('comment-side');
const lineEl = this.$.diffBuilder.getLineElByNumber(
lineNumString, commentSide);
+ // When the line the comment refers to does not exist, log an error
+ // but don't crash. This can happen e.g. if the API does not fully
+ // validate e.g. (robot) comments
+ if (lineEl == undefined) {
+ console.error(
+ 'thread attached to line ', commentSide, lineNumString,
+ ' which does not exist.');
+ continue;
+ }
const contentEl = this.$.diffBuilder.getContentTdByLineEl(lineEl);
const threadGroupEl = this._getOrCreateThreadGroup(
contentEl, commentSide);
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.js b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.js
index a10db97..d60d174 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.js
@@ -36,16 +36,11 @@
suite('gr-diff tests', () => {
let element;
- let sandbox;
const MINIMAL_PREFS = {tab_size: 2, line_length: 80};
setup(() => {
- sandbox = sinon.sandbox.create();
- });
- teardown(() => {
- sandbox.restore();
});
suite('selectionchange event handling', () => {
@@ -55,7 +50,7 @@
setup(() => {
element = basicFixture.instantiate();
- sandbox.stub(element.$.highlights, 'handleSelectionChange');
+ sinon.stub(element.$.highlights, 'handleSelectionChange');
});
test('enabled if logged in', () => {
@@ -73,7 +68,7 @@
test('cancel', () => {
element = basicFixture.instantiate();
- const cancelStub = sandbox.stub(element.$.diffBuilder, 'cancel');
+ const cancelStub = sinon.stub(element.$.diffBuilder, 'cancel');
element.cancel();
assert.isTrue(cancelStub.calledOnce);
});
@@ -195,8 +190,8 @@
});
test('addDraftAtLine', () => {
- sandbox.stub(element, '_selectLine');
- const loggedInErrorSpy = sandbox.spy();
+ sinon.stub(element, '_selectLine');
+ const loggedInErrorSpy = sinon.spy();
element.addEventListener('show-auth-required', loggedInErrorSpy);
element.addDraftAtLine();
assert.isTrue(loggedInErrorSpy.called);
@@ -211,7 +206,7 @@
});
test('displayLine class added called when displayLine is true', () => {
- const spy = sandbox.spy(element, '_computeContainerClass');
+ const spy = sinon.spy(element, '_computeContainerClass');
element.displayLine = true;
assert.isTrue(spy.called);
assert.isTrue(
@@ -545,7 +540,7 @@
});
test('_handleTap lineNum', done => {
- const addDraftStub = sandbox.stub(element, 'addDraftAtLine');
+ const addDraftStub = sinon.stub(element, 'addDraftAtLine');
const el = document.createElement('div');
el.className = 'lineNum';
el.addEventListener('click', e => {
@@ -559,7 +554,7 @@
test('_handleTap context', done => {
const showContextStub =
- sandbox.stub(element.$.diffBuilder, 'showContext');
+ sinon.stub(element.$.diffBuilder, 'showContext');
const el = document.createElement('div');
el.className = 'showContext';
el.addEventListener('click', e => {
@@ -574,8 +569,9 @@
const content = document.createElement('div');
const lineEl = document.createElement('div');
- const selectStub = sandbox.stub(element, '_selectLine');
- sandbox.stub(element.$.diffBuilder, 'getLineElByChild', () => lineEl);
+ const selectStub = sinon.stub(element, '_selectLine');
+ sinon.stub(element.$.diffBuilder, 'getLineElByChild')
+ .callsFake(() => lineEl);
content.className = 'content';
content.addEventListener('click', e => {
@@ -642,16 +638,16 @@
element.patchRange = {};
fakeLineEl = {
- getAttribute: sandbox.stub().returns(42),
+ getAttribute: sinon.stub().returns(42),
classList: {
- contains: sandbox.stub().returns(true),
+ contains: sinon.stub().returns(true),
},
};
});
test('addDraftAtLine', () => {
- sandbox.stub(element, '_selectLine');
- sandbox.stub(element, '_createComment');
+ sinon.stub(element, '_selectLine');
+ sinon.stub(element, '_createComment');
element.addDraftAtLine(fakeLineEl);
assert.isTrue(element._createComment
.calledWithExactly(fakeLineEl, 42));
@@ -659,9 +655,9 @@
test('addDraftAtLine on an edit', () => {
element.patchRange.basePatchNum = element.EDIT_NAME;
- sandbox.stub(element, '_selectLine');
- sandbox.stub(element, '_createComment');
- const alertSpy = sandbox.spy();
+ sinon.stub(element, '_selectLine');
+ sinon.stub(element, '_createComment');
+ const alertSpy = sinon.spy();
element.addEventListener('show-alert', alertSpy);
element.addDraftAtLine(fakeLineEl);
assert.isTrue(alertSpy.called);
@@ -671,9 +667,9 @@
test('addDraftAtLine on an edit base', () => {
element.patchRange.patchNum = element.EDIT_NAME;
element.patchRange.basePatchNum = element.PARENT_NAME;
- sandbox.stub(element, '_selectLine');
- sandbox.stub(element, '_createComment');
- const alertSpy = sandbox.spy();
+ sinon.stub(element, '_selectLine');
+ sinon.stub(element, '_createComment');
+ const alertSpy = sinon.spy();
element.addEventListener('show-alert', alertSpy);
element.addDraftAtLine(fakeLineEl);
assert.isTrue(alertSpy.called);
@@ -695,7 +691,7 @@
});
test('change in preferences re-renders diff', () => {
- sandbox.stub(element, '_renderDiffTable');
+ sinon.stub(element, '_renderDiffTable');
element.prefs = Object.assign(
{}, MINIMAL_PREFS, {time_format: 'HHMM_12'});
element.flushDebouncer('renderDiffTable');
@@ -703,7 +699,7 @@
});
test('adding/removing property in preferences re-renders diff', () => {
- const stub = sandbox.stub(element, '_renderDiffTable');
+ const stub = sinon.stub(element, '_renderDiffTable');
const newPrefs1 = Object.assign({}, MINIMAL_PREFS,
{line_wrapping: true});
element.prefs = newPrefs1;
@@ -720,7 +716,7 @@
test('change in preferences does not re-renders diff with ' +
'noRenderOnPrefsChange', () => {
- sandbox.stub(element, '_renderDiffTable');
+ sinon.stub(element, '_renderDiffTable');
element.noRenderOnPrefsChange = true;
element.prefs = Object.assign(
{}, MINIMAL_PREFS, {time_format: 'HHMM_12'});
@@ -778,13 +774,13 @@
setup(() => {
element = basicFixture.instantiate();
- renderStub = sandbox.stub(element.$.diffBuilder, 'render',
+ renderStub = sinon.stub(element.$.diffBuilder, 'render').callsFake(
() => {
element.$.diffBuilder.dispatchEvent(
new CustomEvent('render', {bubbles: true, composed: true}));
return Promise.resolve({});
});
- sandbox.stub(element, 'getDiffLength').returns(10000);
+ sinon.stub(element, 'getDiffLength').returns(10000);
element.diff = getMockDiffResponse();
element.noRenderOnPrefsChange = true;
});
@@ -834,7 +830,7 @@
test('unsetting', () => {
element.blame = [];
- const setBlameSpy = sandbox.spy(element.$.diffBuilder, 'setBlame');
+ const setBlameSpy = sinon.spy(element.$.diffBuilder, 'setBlame');
element.classList.add('showBlame');
element.blame = null;
assert.isTrue(setBlameSpy.calledWithExactly(null));
@@ -935,7 +931,7 @@
setup(() => {
element = basicFixture.instantiate();
element.prefs = {};
- renderStub = sandbox.stub(element.$.diffBuilder, 'render')
+ renderStub = sinon.stub(element.$.diffBuilder, 'render')
.returns(new Promise(() => {}));
});
@@ -1143,7 +1139,7 @@
test('`render` event has contentRendered field in detail', done => {
element = basicFixture.instantiate();
element.prefs = {};
- sandbox.stub(element.$.diffBuilder, 'render')
+ sinon.stub(element.$.diffBuilder, 'render')
.returns(Promise.resolve());
element.addEventListener('render', event => {
assert.isTrue(event.detail.contentRendered);
diff --git a/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select.js b/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select.js
index c00c0fb..806e147 100644
--- a/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select.js
+++ b/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select.js
@@ -97,7 +97,7 @@
_sortedRevisions,
changeComments,
revisionInfo,
- ].some(arg => arg === undefined)) {
+ ].includes(undefined)) {
return undefined;
}
@@ -150,7 +150,7 @@
basePatchNum,
_sortedRevisions,
changeComments,
- ].some(arg => arg === undefined)) {
+ ].includes(undefined)) {
return undefined;
}
@@ -289,14 +289,18 @@
_handlePatchChange(e) {
const detail = {patchNum: this.patchNum, basePatchNum: this.basePatchNum};
const target = dom(e).localTarget;
-
+ const latestPatchNum = this.computeLatestPatchNum(this.availablePatches);
if (target === this.$.patchNumDropdown) {
if (detail.patchNum === e.detail.value) return;
this.reporting.reportInteraction('right-patchset-changed',
- {previous: detail.patchNum, current: e.detail.value});
+ {
+ previous: detail.patchNum,
+ current: e.detail.value,
+ latest: latestPatchNum,
+ });
detail.patchNum = e.detail.value;
} else {
- if (detail.basePatchNum === e.detail.value) return;
+ if (this.patchNumEquals(detail.basePatchNum, e.detail.value)) return;
this.reporting.reportInteraction('left-patchset-changed',
{previous: detail.basePatchNum, current: e.detail.value});
detail.basePatchNum = e.detail.value;
diff --git a/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select_test.html b/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select_test.js
similarity index 86%
rename from polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select_test.html
rename to polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select_test.js
index 218ca7e..9145b19 100644
--- a/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select_test.js
@@ -1,56 +1,42 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2015 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-patch-range-select</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<script src="/node_modules/page/page.js"></script>
-
-<dom-module id="comment-api-mock">
- <template>
- <gr-patch-range-select id="patchRange" auto
- change-comments="[[_changeComments]]"></gr-patch-range-select>
- <gr-comment-api id="commentAPI"></gr-comment-api>
- </template>
- </dom-module>
-
-<test-fixture id="basic">
- <template>
- <comment-api-mock></comment-api-mock>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import '../gr-comment-api/gr-comment-api.js';
import '../../shared/revision-info/revision-info.js';
import './gr-patch-range-select.js';
import '../../../test/mocks/comment-api.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {RevisionInfo} from '../../shared/revision-info/revision-info.js';
+import {createCommentApiMockWithTemplateElement} from '../../../test/mocks/comment-api';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const commentApiMockElement = createCommentApiMockWithTemplateElement(
+ 'gr-patch-range-select-comment-api-mock', html`
+ <gr-patch-range-select id="patchRange" auto
+ change-comments="[[_changeComments]]"></gr-patch-range-select>
+ <gr-comment-api id="commentAPI"></gr-comment-api>
+`);
+
+const basicFixture = fixtureFromElement(commentApiMockElement.is);
+
suite('gr-patch-range-select tests', () => {
let element;
- let sandbox;
+
let commentApiWrapper;
function getInfo(revisions) {
@@ -62,8 +48,6 @@
}
setup(() => {
- sandbox = sinon.sandbox.create();
-
stub('gr-rest-api-interface', {
getDiffComments() { return Promise.resolve({}); },
getDiffRobotComments() { return Promise.resolve({}); },
@@ -72,7 +56,7 @@
// Element must be wrapped in an element with direct access to the
// comment API.
- commentApiWrapper = fixture('basic');
+ commentApiWrapper = basicFixture.instantiate();
element = commentApiWrapper.$.patchRange;
// Stub methods on the changeComments object after changeComments has
@@ -80,8 +64,6 @@
return commentApiWrapper.loadComments();
});
- teardown(() => sandbox.restore());
-
test('enabled/disabled options', () => {
const patchRange = {
basePatchNum: 'PARENT',
@@ -204,7 +186,7 @@
element.basePatchNum = 'PARENT';
flushAsynchronousOperations();
- sandbox.stub(element, '_computeBaseDropdownContent');
+ sinon.stub(element, '_computeBaseDropdownContent');
// Should be recomputed for each available patch
element.set('patchNum', 1);
@@ -231,7 +213,7 @@
flushAsynchronousOperations();
// Should be recomputed for each available patch
- sandbox.stub(element, '_computeBaseDropdownContent');
+ sinon.stub(element, '_computeBaseDropdownContent');
assert.equal(element._computeBaseDropdownContent.callCount, 0);
commentApiWrapper.loadComments().then()
.then(() => {
@@ -259,7 +241,7 @@
flushAsynchronousOperations();
// Should be recomputed for each available patch
- sandbox.stub(element, '_computePatchDropdownContent');
+ sinon.stub(element, '_computePatchDropdownContent');
element.set('basePatchNum', 1);
assert.equal(element._computePatchDropdownContent.callCount, 1);
});
@@ -283,7 +265,7 @@
flushAsynchronousOperations();
// Should be recomputed for each available patch
- sandbox.stub(element, '_computePatchDropdownContent');
+ sinon.stub(element, '_computePatchDropdownContent');
assert.equal(element._computePatchDropdownContent.callCount, 0);
commentApiWrapper.loadComments().then()
.then(() => {
@@ -410,7 +392,7 @@
});
test('patch-range-change fires', () => {
- const handler = sandbox.stub();
+ const handler = sinon.stub();
element.basePatchNum = 1;
element.patchNum = 3;
element.addEventListener('patch-range-change', handler);
@@ -426,4 +408,4 @@
{basePatchNum: 1, patchNum: 'edit'});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer.js b/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer.js
index 70aa1e7..c774f1a 100644
--- a/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer.js
+++ b/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer.js
@@ -107,6 +107,10 @@
this._listeners.push(fn);
}
+ removeListener(fn) {
+ this._listeners = this._listeners.filter(f => f != fn);
+ }
+
/**
* Notify Layer listeners of changes to annotations.
*
@@ -133,10 +137,11 @@
if (record.path === 'commentRanges') {
this._rangesMap = {left: {}, right: {}};
for (const {side, range, hovering} of record.value) {
- this._updateRangesMap(
- side, range, hovering, (forLine, start, end, hovering) => {
- forLine.push({start, end, hovering});
- });
+ this._updateRangesMap({
+ side, range, hovering,
+ operation: (forLine, start, end, hovering) => {
+ forLine.push({start, end, hovering});
+ }});
}
}
@@ -147,12 +152,13 @@
// not the index, especially in polymer 1.
const {side, range, hovering} = this.get(match[1]);
- this._updateRangesMap(
- side, range, hovering, (forLine, start, end, hovering) => {
- const index = forLine.findIndex(lineRange =>
- lineRange.start === start && lineRange.end === end);
- forLine[index].hovering = hovering;
- });
+ this._updateRangesMap({
+ side, range, hovering, skipLayerUpdate: true,
+ operation: (forLine, start, end, hovering) => {
+ const index = forLine.findIndex(lineRange =>
+ lineRange.start === start && lineRange.end === end);
+ forLine[index].hovering = hovering;
+ }});
}
// If comments were spliced in or out.
@@ -160,26 +166,40 @@
for (const indexSplice of record.value.indexSplices) {
const removed = indexSplice.removed;
for (const {side, range, hovering} of removed) {
- this._updateRangesMap(
- side, range, hovering, (forLine, start, end) => {
- const index = forLine.findIndex(lineRange =>
- lineRange.start === start && lineRange.end === end);
- forLine.splice(index, 1);
- });
+ this._updateRangesMap({
+ side, range, hovering, operation: (forLine, start, end) => {
+ const index = forLine.findIndex(lineRange =>
+ lineRange.start === start && lineRange.end === end);
+ forLine.splice(index, 1);
+ }});
}
const added = indexSplice.object.slice(
indexSplice.index, indexSplice.index + indexSplice.addedCount);
for (const {side, range, hovering} of added) {
- this._updateRangesMap(
- side, range, hovering, (forLine, start, end, hovering) => {
- forLine.push({start, end, hovering});
- });
+ this._updateRangesMap({
+ side, range, hovering,
+ operation: (forLine, start, end, hovering) => {
+ forLine.push({start, end, hovering});
+ }});
}
}
}
}
- _updateRangesMap(side, range, hovering, operation) {
+ /**
+ * @param {!Object} options
+ * @property {!string} options.side
+ * @property {boolean} options.hovering
+ * @property {boolean} options.skipLayerUpdate
+ * @property {!Function} options.operation
+ * @property {!{
+ * start_character: number,
+ * start_line: number,
+ * end_line: number,
+ * end_character: number}} options.range
+ */
+ _updateRangesMap(options) {
+ const {side, range, hovering, operation, skipLayerUpdate} = options;
const forSide = this._rangesMap[side] || (this._rangesMap[side] = {});
for (let line = range.start_line; line <= range.end_line; line++) {
const forLine = forSide[line] || (forSide[line] = []);
@@ -187,7 +207,9 @@
const end = line === range.end_line ? range.end_character : -1;
operation(forLine, start, end, hovering);
}
- this._notifyUpdateRange(range.start_line, range.end_line, side);
+ if (!skipLayerUpdate) {
+ this._notifyUpdateRange(range.start_line, range.end_line, side);
+ }
}
_getRangesForLine(line, side) {
diff --git a/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer_test.html b/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer_test.js
similarity index 82%
rename from polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer_test.html
rename to polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer_test.js
index ff1f4a7..2ce0afa 100644
--- a/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer_test.js
@@ -1,46 +1,30 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-ranged-comment-layer</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-ranged-comment-layer></gr-ranged-comment-layer>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import '../gr-diff/gr-diff-line.js';
import './gr-ranged-comment-layer.js';
import {GrAnnotation} from '../gr-diff-highlight/gr-annotation.js';
import {GrDiffLine} from '../gr-diff/gr-diff-line.js';
+const basicFixture = fixtureFromElement('gr-ranged-comment-layer');
+
suite('gr-ranged-comment-layer', () => {
let element;
- let sandbox;
setup(() => {
const initialCommentRanges = [
@@ -82,35 +66,24 @@
},
];
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.commentRanges = initialCommentRanges;
});
- teardown(() => {
- sandbox.restore();
- });
-
suite('annotate', () => {
- let sandbox;
let el;
let line;
let annotateElementStub;
const lineNumberEl = document.createElement('td');
setup(() => {
- sandbox = sinon.sandbox.create();
- annotateElementStub = sandbox.stub(GrAnnotation, 'annotateElement');
+ annotateElementStub = sinon.stub(GrAnnotation, 'annotateElement');
el = document.createElement('div');
el.setAttribute('data-side', 'left');
line = new GrDiffLine(GrDiffLine.Type.BOTH);
line.text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit,';
});
- teardown(() => {
- sandbox.restore();
- });
-
test('type=Remove no-comment', () => {
line.type = GrDiffLine.Type.REMOVE;
line.beforeNumber = 40;
@@ -210,15 +183,12 @@
test('_handleCommentRangesChange hovering', () => {
const notifyStub = sinon.stub();
element.addListener(notifyStub);
- const updateRangesMapSpy = sandbox.spy(element, '_updateRangesMap');
+ const updateRangesMapSpy = sinon.spy(element, '_updateRangesMap');
element.set(['commentRanges', 1, 'hovering'], true);
- assert.isTrue(notifyStub.called);
- const lastCall = notifyStub.lastCall;
- assert.equal(lastCall.args[0], 10);
- assert.equal(lastCall.args[1], 12);
- assert.equal(lastCall.args[2], 'right');
+ // notify will be skipped for hovering
+ assert.isFalse(notifyStub.called);
assert.isTrue(updateRangesMapSpy.called);
});
@@ -260,7 +230,7 @@
test('_handleCommentRangesChange mixed actions', () => {
const notifyStub = sinon.stub();
element.addListener(notifyStub);
- const updateRangesMapSpy = sandbox.spy(element, '_updateRangesMap');
+ const updateRangesMapSpy = sinon.spy(element, '_updateRangesMap');
element.set(['commentRanges', 1, 'hovering'], true);
assert.isTrue(updateRangesMapSpy.callCount === 1);
@@ -342,4 +312,4 @@
assert.equal(range.end, line.text.length);
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box_test.html b/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box_test.html
deleted file mode 100644
index ff6fba7..0000000
--- a/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box_test.html
+++ /dev/null
@@ -1,135 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-selection-action-box</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <div>
- <gr-selection-action-box></gr-selection-action-box>
- <div class="target">some text</div>
- </div>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-selection-action-box.js';
-suite('gr-selection-action-box', () => {
- let container;
- let element;
- let sandbox;
-
- setup(() => {
- container = fixture('basic');
- element = container.querySelector('gr-selection-action-box');
- sandbox = sinon.sandbox.create();
- sandbox.stub(element, 'dispatchEvent');
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('ignores regular keys', () => {
- MockInteractions.pressAndReleaseKeyOn(document.body, 27, null, 'esc');
- assert.isFalse(element.dispatchEvent.called);
- });
-
- suite('mousedown reacts only to main button', () => {
- let e;
-
- setup(() => {
- e = {
- button: 0,
- preventDefault: sandbox.stub(),
- stopPropagation: sandbox.stub(),
- };
- });
-
- test('event handled if main button', () => {
- element._handleMouseDown(e);
- assert.isTrue(e.preventDefault.called);
- assert.equal(
- element.dispatchEvent.lastCall.args[0].type,
- 'create-comment-requested'
- );
- });
-
- test('event ignored if not main button', () => {
- e.button = 1;
- element._handleMouseDown(e);
- assert.isFalse(e.preventDefault.called);
- assert.isFalse(element.dispatchEvent.called);
- });
- });
-
- suite('placeAbove', () => {
- let target;
-
- setup(() => {
- target = container.querySelector('.target');
- sandbox.stub(container, 'getBoundingClientRect').returns(
- {top: 1, bottom: 2, left: 3, right: 4, width: 50, height: 6});
- sandbox.stub(element, '_getTargetBoundingRect').returns(
- {top: 42, bottom: 20, left: 30, right: 40, width: 100, height: 60});
- sandbox.stub(element.$.tooltip, 'getBoundingClientRect').returns(
- {width: 10, height: 10});
- });
-
- test('placeAbove for Element argument', () => {
- element.placeAbove(target);
- assert.equal(element.style.top, '25px');
- assert.equal(element.style.left, '72px');
- });
-
- test('placeAbove for Text Node argument', () => {
- element.placeAbove(target.firstChild);
- assert.equal(element.style.top, '25px');
- assert.equal(element.style.left, '72px');
- });
-
- test('placeBelow for Element argument', () => {
- element.placeBelow(target);
- assert.equal(element.style.top, '45px');
- assert.equal(element.style.left, '72px');
- });
-
- test('placeBelow for Text Node argument', () => {
- element.placeBelow(target.firstChild);
- assert.equal(element.style.top, '45px');
- assert.equal(element.style.left, '72px');
- });
-
- test('uses document.createRange', () => {
- sandbox.spy(document, 'createRange');
- element._getTargetBoundingRect.restore();
- sandbox.spy(element, '_getTargetBoundingRect');
- element.placeAbove(target.firstChild);
- assert.isTrue(document.createRange.called);
- });
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box_test.js b/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box_test.js
new file mode 100644
index 0000000..81cf0d6
--- /dev/null
+++ b/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box_test.js
@@ -0,0 +1,119 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-selection-action-box.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const basicFixture = fixtureFromTemplate(html`
+ <div>
+ <gr-selection-action-box></gr-selection-action-box>
+ <div class="target">some text</div>
+ </div>
+`);
+
+suite('gr-selection-action-box', () => {
+ let container;
+ let element;
+
+ setup(() => {
+ container = basicFixture.instantiate();
+ element = container.querySelector('gr-selection-action-box');
+
+ sinon.stub(element, 'dispatchEvent');
+ });
+
+ test('ignores regular keys', () => {
+ MockInteractions.pressAndReleaseKeyOn(document.body, 27, null, 'esc');
+ assert.isFalse(element.dispatchEvent.called);
+ });
+
+ suite('mousedown reacts only to main button', () => {
+ let e;
+
+ setup(() => {
+ e = {
+ button: 0,
+ preventDefault: sinon.stub(),
+ stopPropagation: sinon.stub(),
+ };
+ });
+
+ test('event handled if main button', () => {
+ element._handleMouseDown(e);
+ assert.isTrue(e.preventDefault.called);
+ assert.equal(
+ element.dispatchEvent.lastCall.args[0].type,
+ 'create-comment-requested'
+ );
+ });
+
+ test('event ignored if not main button', () => {
+ e.button = 1;
+ element._handleMouseDown(e);
+ assert.isFalse(e.preventDefault.called);
+ assert.isFalse(element.dispatchEvent.called);
+ });
+ });
+
+ suite('placeAbove', () => {
+ let target;
+
+ setup(() => {
+ target = container.querySelector('.target');
+ sinon.stub(container, 'getBoundingClientRect').returns(
+ {top: 1, bottom: 2, left: 3, right: 4, width: 50, height: 6});
+ sinon.stub(element, '_getTargetBoundingRect').returns(
+ {top: 42, bottom: 20, left: 30, right: 40, width: 100, height: 60});
+ sinon.stub(element.$.tooltip, 'getBoundingClientRect').returns(
+ {width: 10, height: 10});
+ });
+
+ test('placeAbove for Element argument', () => {
+ element.placeAbove(target);
+ assert.equal(element.style.top, '25px');
+ assert.equal(element.style.left, '72px');
+ });
+
+ test('placeAbove for Text Node argument', () => {
+ element.placeAbove(target.firstChild);
+ assert.equal(element.style.top, '25px');
+ assert.equal(element.style.left, '72px');
+ });
+
+ test('placeBelow for Element argument', () => {
+ element.placeBelow(target);
+ assert.equal(element.style.top, '45px');
+ assert.equal(element.style.left, '72px');
+ });
+
+ test('placeBelow for Text Node argument', () => {
+ element.placeBelow(target.firstChild);
+ assert.equal(element.style.top, '45px');
+ assert.equal(element.style.left, '72px');
+ });
+
+ test('uses document.createRange', () => {
+ sinon.spy(document, 'createRange');
+ element._getTargetBoundingRect.restore();
+ sinon.spy(element, '_getTargetBoundingRect');
+ element.placeAbove(target.firstChild);
+ assert.isTrue(document.createRange.called);
+ });
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer.js b/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer.js
index 1a0bbd9..6399c4a 100644
--- a/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer.js
+++ b/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer.js
@@ -102,7 +102,7 @@
};
const ASYNC_DELAY = 10;
-const CLASS_WHITELIST = {
+const CLASS_SAFELIST = {
'gr-diff gr-syntax gr-syntax-attr': true,
'gr-diff gr-syntax gr-syntax-attribute': true,
'gr-diff gr-syntax gr-syntax-built_in': true,
@@ -365,7 +365,7 @@
// Note: HLJS may emit a span with class undefined when it thinks there
// may be a syntax error.
if (node.tagName === 'SPAN' && node.className !== 'undefined') {
- if (CLASS_WHITELIST.hasOwnProperty(node.className)) {
+ if (CLASS_SAFELIST.hasOwnProperty(node.className)) {
result.push({
start: offset,
length: nodeLength,
diff --git a/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer_test.html b/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer_test.js
similarity index 86%
rename from polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer_test.html
rename to polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer_test.js
index 638b188..03acfb5 100644
--- a/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer_test.js
@@ -1,45 +1,29 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-syntax-layer</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-syntax-layer></gr-syntax-layer>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import {getMockDiffResponse} from '../../../test/mocks/diff-response.js';
import './gr-syntax-layer.js';
import {GrAnnotation} from '../gr-diff-highlight/gr-annotation.js';
import {GrDiffLine} from '../gr-diff/gr-diff-line.js';
+const basicFixture = fixtureFromElement('gr-syntax-layer');
+
suite('gr-syntax-layer tests', () => {
- let sandbox;
let diff;
let element;
const lineNumberEl = document.createElement('td');
@@ -64,18 +48,13 @@
}
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
+ element = basicFixture.instantiate();
diff = getMockDiffResponse();
element.diff = diff;
});
- teardown(() => {
- sandbox.restore();
- });
-
test('annotate without range does nothing', () => {
- const annotationSpy = sandbox.spy(GrAnnotation, 'annotateElement');
+ const annotationSpy = sinon.spy(GrAnnotation, 'annotateElement');
const el = document.createElement('div');
el.textContent = 'Etiam dui, blandit wisi.';
const line = new GrDiffLine(GrDiffLine.Type.REMOVE);
@@ -92,7 +71,7 @@
const length = 3;
const className = 'foobar';
- const annotationSpy = sandbox.spy(GrAnnotation, 'annotateElement');
+ const annotationSpy = sinon.spy(GrAnnotation, 'annotateElement');
const el = document.createElement('div');
el.textContent = str;
const line = new GrDiffLine(GrDiffLine.Type.REMOVE);
@@ -119,7 +98,7 @@
const length = 3;
const className = 'foobar';
- const annotationSpy = sandbox.spy(GrAnnotation, 'annotateElement');
+ const annotationSpy = sinon.spy(GrAnnotation, 'annotateElement');
const el = document.createElement('div');
el.textContent = str;
const line = new GrDiffLine(GrDiffLine.Type.REMOVE);
@@ -142,7 +121,7 @@
meta_b: {content_type: 'application/json'},
content: [],
};
- const processNextSpy = sandbox.spy(element, '_processNextLine');
+ const processNextSpy = sinon.spy(element, '_processNextLine');
const processPromise = element.process();
@@ -160,7 +139,7 @@
meta_b: {content_type: 'application/not-a-real-language'},
content: [],
};
- const processNextSpy = sandbox.spy(element, '_processNextLine');
+ const processNextSpy = sinon.spy(element, '_processNextLine');
const processPromise = element.process();
@@ -173,9 +152,9 @@
});
test('process while disabled does nothing', done => {
- const processNextSpy = sandbox.spy(element, '_processNextLine');
+ const processNextSpy = sinon.spy(element, '_processNextLine');
element.enabled = false;
- const loadHLJSSpy = sandbox.spy(element, '_loadHLJS');
+ const loadHLJSSpy = sinon.spy(element, '_loadHLJS');
const processPromise = element.process();
@@ -194,9 +173,9 @@
const mockHLJS = getMockHLJS();
const highlightSpy = sinon.spy(mockHLJS, 'highlight');
- sandbox.stub(element.$.libLoader, 'getHLJS',
+ sinon.stub(element.$.libLoader, 'getHLJS').callsFake(
() => Promise.resolve(mockHLJS));
- const processNextSpy = sandbox.spy(element, '_processNextLine');
+ const processNextSpy = sinon.spy(element, '_processNextLine');
const processPromise = element.process();
processPromise.then(() => {
@@ -259,7 +238,7 @@
});
test('_diffChanged calls cancel', () => {
- const cancelSpy = sandbox.spy(element, '_diffChanged');
+ const cancelSpy = sinon.spy(element, '_diffChanged');
element.diff = {content: []};
assert.isTrue(cancelSpy.called);
});
@@ -297,11 +276,11 @@
assert.equal(result[0].className, className);
});
- test('_rangesFromElement non-whitelist', () => {
+ test('_rangesFromElement non-allowed', () => {
const str0 = 'Etiam ';
const str1 = 'dui, blandit';
const str2 = ' wisi.';
- const className = 'not-in-the-whitelist';
+ const className = 'not-in-the-safelist';
const offset = 100;
const elem = document.createElement('span');
@@ -384,7 +363,7 @@
assert.equal(result[1].className, className);
});
- test('_rangesFromString whitelist allows recursion', () => {
+ test('_rangesFromString safelist allows recursion', () => {
const str = [
'<span class="non-whtelisted-class">',
'<span class="gr-diff gr-syntax gr-syntax-keyword">public</span>',
@@ -394,7 +373,7 @@
});
test('_rangesFromString cache same syntax markers', () => {
- sandbox.spy(element, '_rangesFromElement');
+ sinon.spy(element, '_rangesFromElement');
const str =
'<span class="gr-diff gr-syntax gr-syntax-keyword">public</span>';
const cacheMap = new Map();
@@ -500,4 +479,4 @@
assert.equal(element._workaround('go', line), expected);
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/documentation/gr-documentation-search/gr-documentation-search_test.html b/polygerrit-ui/app/elements/documentation/gr-documentation-search/gr-documentation-search_test.html
deleted file mode 100644
index d0581ef..0000000
--- a/polygerrit-ui/app/elements/documentation/gr-documentation-search/gr-documentation-search_test.html
+++ /dev/null
@@ -1,124 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-documentation-search</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/page/page.js"></script>
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-documentation-search></gr-documentation-search>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-documentation-search.js';
-import page from 'page/page.mjs';
-
-let counter;
-const documentationGenerator = () => {
- return {
- title: `Gerrit Code Review - REST API Developers Notes${++counter}`,
- url: 'Documentation/dev-rest-api.html',
- };
-};
-
-suite('gr-documentation-search tests', () => {
- let element;
- let documentationSearches;
- let sandbox;
- let value;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- sandbox.stub(page, 'show');
- element = fixture('basic');
- counter = 0;
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- suite('list with searches for documentation', () => {
- setup(done => {
- documentationSearches = _.times(26, documentationGenerator);
- stub('gr-rest-api-interface', {
- getDocumentationSearches() {
- return Promise.resolve(documentationSearches);
- },
- });
- element._paramsChanged(value).then(() => { flush(done); });
- });
-
- test('test for test repo in the list', done => {
- flush(() => {
- assert.equal(element._documentationSearches[0].title,
- 'Gerrit Code Review - REST API Developers Notes1');
- assert.equal(element._documentationSearches[0].url,
- 'Documentation/dev-rest-api.html');
- done();
- });
- });
- });
-
- suite('filter', () => {
- setup(() => {
- documentationSearches = _.times(25, documentationGenerator);
- _.times(1, documentationSearches);
- });
-
- test('_paramsChanged', done => {
- sandbox.stub(
- element.$.restAPI,
- 'getDocumentationSearches',
- () => Promise.resolve(documentationSearches));
- const value = {
- filter: 'test',
- };
- element._paramsChanged(value).then(() => {
- assert.isTrue(element.$.restAPI.getDocumentationSearches.lastCall
- .calledWithExactly('test'));
- done();
- });
- });
- });
-
- suite('loading', () => {
- test('correct contents are displayed', () => {
- assert.isTrue(element._loading);
- assert.equal(element.computeLoadingClass(element._loading), 'loading');
- assert.equal(getComputedStyle(element.$.loading).display, 'block');
-
- element._loading = false;
- element._repos = _.times(25, documentationGenerator);
-
- flushAsynchronousOperations();
- assert.equal(element.computeLoadingClass(element._loading), '');
- assert.equal(getComputedStyle(element.$.loading).display, 'none');
- });
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/documentation/gr-documentation-search/gr-documentation-search_test.js b/polygerrit-ui/app/elements/documentation/gr-documentation-search/gr-documentation-search_test.js
new file mode 100644
index 0000000..c2a3f3d
--- /dev/null
+++ b/polygerrit-ui/app/elements/documentation/gr-documentation-search/gr-documentation-search_test.js
@@ -0,0 +1,103 @@
+/**
+ * @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.
+ */
+
+import '../../../test/common-test-setup-karma.js';
+import './gr-documentation-search.js';
+import page from 'page/page.mjs';
+
+const basicFixture = fixtureFromElement('gr-documentation-search');
+
+let counter;
+const documentationGenerator = () => {
+ return {
+ title: `Gerrit Code Review - REST API Developers Notes${++counter}`,
+ url: 'Documentation/dev-rest-api.html',
+ };
+};
+
+suite('gr-documentation-search tests', () => {
+ let element;
+ let documentationSearches;
+
+ let value;
+
+ setup(() => {
+ sinon.stub(page, 'show');
+ element = basicFixture.instantiate();
+ counter = 0;
+ });
+
+ suite('list with searches for documentation', () => {
+ setup(done => {
+ documentationSearches = _.times(26, documentationGenerator);
+ stub('gr-rest-api-interface', {
+ getDocumentationSearches() {
+ return Promise.resolve(documentationSearches);
+ },
+ });
+ element._paramsChanged(value).then(() => { flush(done); });
+ });
+
+ test('test for test repo in the list', done => {
+ flush(() => {
+ assert.equal(element._documentationSearches[0].title,
+ 'Gerrit Code Review - REST API Developers Notes1');
+ assert.equal(element._documentationSearches[0].url,
+ 'Documentation/dev-rest-api.html');
+ done();
+ });
+ });
+ });
+
+ suite('filter', () => {
+ setup(() => {
+ documentationSearches = _.times(25, documentationGenerator);
+ _.times(1, documentationSearches);
+ });
+
+ test('_paramsChanged', done => {
+ sinon.stub(
+ element.$.restAPI,
+ 'getDocumentationSearches')
+ .callsFake(() => Promise.resolve(documentationSearches));
+ const value = {
+ filter: 'test',
+ };
+ element._paramsChanged(value).then(() => {
+ assert.isTrue(element.$.restAPI.getDocumentationSearches.lastCall
+ .calledWithExactly('test'));
+ done();
+ });
+ });
+ });
+
+ suite('loading', () => {
+ test('correct contents are displayed', () => {
+ assert.isTrue(element._loading);
+ assert.equal(element.computeLoadingClass(element._loading), 'loading');
+ assert.equal(getComputedStyle(element.$.loading).display, 'block');
+
+ element._loading = false;
+ element._repos = _.times(25, documentationGenerator);
+
+ flushAsynchronousOperations();
+ assert.equal(element.computeLoadingClass(element._loading), '');
+ assert.equal(getComputedStyle(element.$.loading).display, 'none');
+ });
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/edit/gr-default-editor/gr-default-editor_test.html b/polygerrit-ui/app/elements/edit/gr-default-editor/gr-default-editor_test.html
deleted file mode 100644
index 229c6c3..0000000
--- a/polygerrit-ui/app/elements/edit/gr-default-editor/gr-default-editor_test.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-default-editor</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-default-editor></gr-default-editor>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-default-editor.js';
-suite('gr-default-editor tests', () => {
- let element;
-
- setup(() => {
- element = fixture('basic');
- element.fileContent = '';
- });
-
- test('fires content-change event', done => {
- const contentChangedHandler = e => {
- assert.equal(e.detail.value, 'test');
- done();
- };
- const textarea = element.$.textarea;
- element.addEventListener('content-change', contentChangedHandler);
- textarea.value = 'test';
- textarea.dispatchEvent(new CustomEvent('input',
- {target: textarea, bubbles: true, composed: true}));
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/edit/gr-default-editor/gr-default-editor_test.js b/polygerrit-ui/app/elements/edit/gr-default-editor/gr-default-editor_test.js
new file mode 100644
index 0000000..d40e83d
--- /dev/null
+++ b/polygerrit-ui/app/elements/edit/gr-default-editor/gr-default-editor_test.js
@@ -0,0 +1,43 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-default-editor.js';
+
+const basicFixture = fixtureFromElement('gr-default-editor');
+
+suite('gr-default-editor tests', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ element.fileContent = '';
+ });
+
+ test('fires content-change event', done => {
+ const contentChangedHandler = e => {
+ assert.equal(e.detail.value, 'test');
+ done();
+ };
+ const textarea = element.$.textarea;
+ element.addEventListener('content-change', contentChangedHandler);
+ textarea.value = 'test';
+ textarea.dispatchEvent(new CustomEvent('input',
+ {target: textarea, bubbles: true, composed: true}));
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls_test.html b/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls_test.js
similarity index 85%
rename from polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls_test.html
rename to polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls_test.js
index 1267525..8269b81 100644
--- a/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls_test.html
+++ b/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls_test.js
@@ -1,63 +1,46 @@
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-edit-controls</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-edit-controls></gr-edit-controls>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-edit-controls.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
+const basicFixture = fixtureFromElement('gr-edit-controls');
+
suite('gr-edit-controls tests', () => {
let element;
- let sandbox;
+
let showDialogSpy;
let closeDialogSpy;
let queryStub;
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.change = {_number: '42'};
- showDialogSpy = sandbox.spy(element, '_showDialog');
- closeDialogSpy = sandbox.spy(element, '_closeDialog');
- sandbox.stub(element, '_hideAllDialogs');
- queryStub = sandbox.stub(element.$.restAPI, 'queryChangeFiles')
+ showDialogSpy = sinon.spy(element, '_showDialog');
+ closeDialogSpy = sinon.spy(element, '_closeDialog');
+ sinon.stub(element, '_hideAllDialogs');
+ queryStub = sinon.stub(element.$.restAPI, 'queryChangeFiles')
.returns(Promise.resolve([]));
flushAsynchronousOperations();
});
- teardown(() => { sandbox.restore(); });
-
test('all actions exist', () => {
// We take 1 away from the total found, due to an extra button being
// added for the file uploads (browse).
@@ -72,8 +55,8 @@
setup(() => {
navStubs = [
- sandbox.stub(GerritNav, 'getEditUrlForDiff'),
- sandbox.stub(GerritNav, 'navigateToRelativeUrl'),
+ sinon.stub(GerritNav, 'getEditUrlForDiff'),
+ sinon.stub(GerritNav, 'navigateToRelativeUrl'),
];
openAutoCcmplete = element.$.openDialog.querySelector('gr-autocomplete');
});
@@ -131,8 +114,8 @@
let deleteAutocomplete;
setup(() => {
- navStub = sandbox.stub(GerritNav, 'navigateToChange');
- deleteStub = sandbox.stub(element.$.restAPI, 'deleteFileInChangeEdit');
+ navStub = sinon.stub(GerritNav, 'navigateToChange');
+ deleteStub = sinon.stub(element.$.restAPI, 'deleteFileInChangeEdit');
deleteAutocomplete =
element.$.deleteDialog.querySelector('gr-autocomplete');
});
@@ -215,8 +198,8 @@
'.newPathInput';
setup(() => {
- navStub = sandbox.stub(GerritNav, 'navigateToChange');
- renameStub = sandbox.stub(element.$.restAPI, 'renameFileInChangeEdit');
+ navStub = sinon.stub(GerritNav, 'navigateToChange');
+ renameStub = sinon.stub(element.$.restAPI, 'renameFileInChangeEdit');
renameAutocomplete =
element.$.renameDialog.querySelector('gr-autocomplete');
});
@@ -308,8 +291,8 @@
let restoreStub;
setup(() => {
- navStub = sandbox.stub(GerritNav, 'navigateToChange');
- restoreStub = sandbox.stub(element.$.restAPI, 'restoreFileInChangeEdit');
+ navStub = sinon.stub(GerritNav, 'navigateToChange');
+ restoreStub = sinon.stub(element.$.restAPI, 'restoreFileInChangeEdit');
});
test('restore hidden by default', () => {
@@ -372,8 +355,8 @@
let fileStub;
setup(() => {
- navStub = sandbox.stub(GerritNav, 'navigateToChange');
- fileStub = sandbox.stub(element.$.restAPI, 'saveFileUploadChangeEdit');
+ navStub = sinon.stub(GerritNav, 'navigateToChange');
+ fileStub = sinon.stub(element.$.restAPI, 'saveFileUploadChangeEdit');
});
test('_handleUploadConfirm', () => {
@@ -409,7 +392,7 @@
});
test('_getDialogFromEvent', () => {
- const spy = sandbox.spy(element, '_getDialogFromEvent');
+ const spy = sinon.spy(element, '_getDialogFromEvent');
element.addEventListener('tap', element._getDialogFromEvent);
MockInteractions.tap(element.$.openDialog);
@@ -430,4 +413,4 @@
assert.notOk(spy.lastCall.returnValue);
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/edit/gr-edit-file-controls/gr-edit-file-controls_test.html b/polygerrit-ui/app/elements/edit/gr-edit-file-controls/gr-edit-file-controls_test.js
similarity index 61%
rename from polygerrit-ui/app/elements/edit/gr-edit-file-controls/gr-edit-file-controls_test.html
rename to polygerrit-ui/app/elements/edit/gr-edit-file-controls/gr-edit-file-controls_test.js
index e11a2bd..8a1c186 100644
--- a/polygerrit-ui/app/elements/edit/gr-edit-file-controls/gr-edit-file-controls_test.html
+++ b/polygerrit-ui/app/elements/edit/gr-edit-file-controls/gr-edit-file-controls_test.js
@@ -1,55 +1,38 @@
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-edit-file-controls</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-edit-file-controls></gr-edit-file-controls>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import '../gr-edit-constants.js';
import './gr-edit-file-controls.js';
import {GrEditConstants} from '../gr-edit-constants.js';
+const basicFixture = fixtureFromElement('gr-edit-file-controls');
+
suite('gr-edit-file-controls tests', () => {
let element;
- let sandbox;
+
let fileActionHandler;
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- fileActionHandler = sandbox.stub();
+ element = basicFixture.instantiate();
+ fileActionHandler = sinon.stub();
element.addEventListener('file-action-tap', fileActionHandler);
});
- teardown(() => { sandbox.restore(); });
-
test('open tap emits event', () => {
const actions = element.$.actions;
element.filePath = 'foo';
@@ -106,4 +89,4 @@
assert.equal(element._allFileActions.length, 4);
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.js b/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.js
index 886908a..0f459a0 100644
--- a/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.js
+++ b/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.js
@@ -247,7 +247,7 @@
content,
newContent,
saving,
- ].some(arg => arg === undefined)) {
+ ].includes(undefined)) {
return true;
}
diff --git a/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view_test.html b/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view_test.js
similarity index 79%
rename from polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view_test.html
rename to polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view_test.js
index e385854..618f595 100644
--- a/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view_test.html
+++ b/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view_test.js
@@ -1,43 +1,29 @@
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-editor-view</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-editor-view></gr-editor-view>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-editor-view.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
+const basicFixture = fixtureFromElement('gr-editor-view');
+
suite('gr-editor-view tests', () => {
let element;
- let sandbox;
+
let savePathStub;
let saveFileStub;
let changeDetailStub;
@@ -53,15 +39,13 @@
getLoggedIn() { return Promise.resolve(true); },
getEditPreferences() { return Promise.resolve({}); },
});
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- savePathStub = sandbox.stub(element.$.restAPI, 'renameFileInChangeEdit');
- saveFileStub = sandbox.stub(element.$.restAPI, 'saveChangeEdit');
- changeDetailStub = sandbox.stub(element.$.restAPI, 'getDiffChangeDetail');
- navigateStub = sandbox.stub(element, '_viewEditInChangeView');
- });
- teardown(() => { sandbox.restore(); });
+ element = basicFixture.instantiate();
+ savePathStub = sinon.stub(element.$.restAPI, 'renameFileInChangeEdit');
+ saveFileStub = sinon.stub(element.$.restAPI, 'saveChangeEdit');
+ changeDetailStub = sinon.stub(element.$.restAPI, 'getDiffChangeDetail');
+ navigateStub = sinon.stub(element, '_viewEditInChangeView');
+ });
suite('_paramsChanged', () => {
test('incorrect view returns immediately', () => {
@@ -72,7 +56,7 @@
test('good params proceed', () => {
changeDetailStub.returns(Promise.resolve({}));
- const fileStub = sandbox.stub(element, '_getFileData', () => {
+ const fileStub = sinon.stub(element, '_getFileData').callsFake(() => {
element._content = 'text';
element._newContent = 'text';
element._type = 'application/octet-stream';
@@ -120,7 +104,7 @@
});
test('reacts to content-change event', () => {
- const storeStub = sandbox.spy(element.$.storage, 'setEditableContentItem');
+ const storeStub = sinon.spy(element.$.storage, 'setEditableContentItem');
element._newContent = 'test';
element.$.editorEndpoint.dispatchEvent(new CustomEvent('content-change', {
bubbles: true, composed: true,
@@ -152,10 +136,10 @@
});
test('file modification and save, !ok response', () => {
- const saveSpy = sandbox.spy(element, '_saveEdit');
- const eraseStub = sandbox.stub(element.$.storage,
+ const saveSpy = sinon.spy(element, '_saveEdit');
+ const eraseStub = sinon.stub(element.$.storage,
'eraseEditableContentItem');
- const alertStub = sandbox.stub(element, '_showAlert');
+ const alertStub = sinon.stub(element, '_showAlert');
saveFileStub.returns(Promise.resolve({ok: false}));
element._newContent = newText;
flushAsynchronousOperations();
@@ -183,8 +167,8 @@
});
test('file modification and save', () => {
- const saveSpy = sandbox.spy(element, '_saveEdit');
- const alertStub = sandbox.stub(element, '_showAlert');
+ const saveSpy = sinon.spy(element, '_saveEdit');
+ const alertStub = sinon.stub(element, '_showAlert');
saveFileStub.returns(Promise.resolve({ok: true}));
element._newContent = newText;
flushAsynchronousOperations();
@@ -210,7 +194,7 @@
});
test('file modification and close', () => {
- const closeSpy = sandbox.spy(element, '_handleCloseTap');
+ const closeSpy = sinon.spy(element, '_handleCloseTap');
element._newContent = newText;
flushAsynchronousOperations();
@@ -228,11 +212,11 @@
element._newContent = 'initial';
element._content = 'initial';
element._type = 'initial';
- sandbox.stub(element.$.storage, 'getEditableContentItem').returns(null);
+ sinon.stub(element.$.storage, 'getEditableContentItem').returns(null);
});
test('res.ok', () => {
- sandbox.stub(element.$.restAPI, 'getFileContent')
+ sinon.stub(element.$.restAPI, 'getFileContent')
.returns(Promise.resolve({
ok: true,
type: 'text/javascript',
@@ -248,7 +232,7 @@
});
test('!res.ok', () => {
- sandbox.stub(element.$.restAPI, 'getFileContent')
+ sinon.stub(element.$.restAPI, 'getFileContent')
.returns(Promise.resolve({}));
// Ensure no data is set with a bad response.
@@ -260,7 +244,7 @@
});
test('content is undefined', () => {
- sandbox.stub(element.$.restAPI, 'getFileContent')
+ sinon.stub(element.$.restAPI, 'getFileContent')
.returns(Promise.resolve({
ok: true,
type: 'text/javascript',
@@ -274,7 +258,7 @@
});
test('content and type is undefined', () => {
- sandbox.stub(element.$.restAPI, 'getFileContent')
+ sinon.stub(element.$.restAPI, 'getFileContent')
.returns(Promise.resolve({
ok: true,
}));
@@ -299,7 +283,7 @@
test('_viewEditInChangeView respects _patchNum', () => {
navigateStub.restore();
- const navStub = sandbox.stub(GerritNav, 'navigateToChange');
+ const navStub = sinon.stub(GerritNav, 'navigateToChange');
element._patchNum = element.EDIT_NAME;
element._viewEditInChangeView();
assert.equal(navStub.lastCall.args[1], element.EDIT_NAME);
@@ -318,8 +302,8 @@
suite('_handleSaveShortcut', () => {
let saveStub;
setup(() => {
- handleSpy = sandbox.spy(element, '_handleSaveShortcut');
- saveStub = sandbox.stub(element, '_saveEdit');
+ handleSpy = sinon.spy(element, '_handleSaveShortcut');
+ saveStub = sinon.stub(element, '_saveEdit');
});
test('save enabled', () => {
@@ -356,16 +340,16 @@
suite('gr-storage caching', () => {
test('local edit exists', () => {
- sandbox.stub(element.$.storage, 'getEditableContentItem')
+ sinon.stub(element.$.storage, 'getEditableContentItem')
.returns({message: 'pending edit'});
- sandbox.stub(element.$.restAPI, 'getFileContent')
+ sinon.stub(element.$.restAPI, 'getFileContent')
.returns(Promise.resolve({
ok: true,
type: 'text/javascript',
content: 'old content',
}));
- const alertStub = sandbox.stub();
+ const alertStub = sinon.stub();
element.addEventListener('show-alert', alertStub);
return element._getFileData(1, 'test', 1).then(() => {
@@ -379,16 +363,16 @@
});
test('local edit exists, is same as remote edit', () => {
- sandbox.stub(element.$.storage, 'getEditableContentItem')
+ sinon.stub(element.$.storage, 'getEditableContentItem')
.returns({message: 'pending edit'});
- sandbox.stub(element.$.restAPI, 'getFileContent')
+ sinon.stub(element.$.restAPI, 'getFileContent')
.returns(Promise.resolve({
ok: true,
type: 'text/javascript',
content: 'pending edit',
}));
- const alertStub = sandbox.stub();
+ const alertStub = sinon.stub();
element.addEventListener('show-alert', alertStub);
return element._getFileData(1, 'test', 1).then(() => {
@@ -409,4 +393,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/gr-app-element.js b/polygerrit-ui/app/elements/gr-app-element.js
index 4915eda..a01e8a4 100644
--- a/polygerrit-ui/app/elements/gr-app-element.js
+++ b/polygerrit-ui/app/elements/gr-app-element.js
@@ -16,6 +16,7 @@
*/
import '../styles/shared-styles.js';
import '../styles/themes/app-theme.js';
+import {applyTheme as applyDarkTheme} from '../styles/themes/dark-theme.js';
import './admin/gr-admin-view/gr-admin-view.js';
import './documentation/gr-documentation-search/gr-documentation-search.js';
import './change-list/gr-change-list-view/gr-change-list-view.js';
@@ -202,9 +203,7 @@
});
if (window.localStorage.getItem('dark-theme')) {
- // No need to add the style module to element again as it's imported
- // by importHref already
- this.$.libLoader.getDarkTheme();
+ applyDarkTheme();
}
// Note: this is evaluated here to ensure that it only happens after the
@@ -271,9 +270,9 @@
this.Shortcut.EDIT_TOPIC, 't');
this.bindShortcut(
- this.Shortcut.OPEN_REPLY_DIALOG, 'a');
+ this.Shortcut.OPEN_REPLY_DIALOG, 'a:keyup');
this.bindShortcut(
- this.Shortcut.OPEN_DOWNLOAD_DIALOG, 'd');
+ this.Shortcut.OPEN_DOWNLOAD_DIALOG, 'd:keyup');
this.bindShortcut(
this.Shortcut.EXPAND_ALL_MESSAGES, 'x');
this.bindShortcut(
@@ -286,6 +285,16 @@
this.Shortcut.UP_TO_CHANGE, 'u');
this.bindShortcut(
this.Shortcut.TOGGLE_DIFF_MODE, 'm:keyup');
+ this.bindShortcut(
+ this.Shortcut.DIFF_AGAINST_BASE, this.V_KEY, 'down', 's');
+ this.bindShortcut(
+ this.Shortcut.DIFF_AGAINST_LATEST, this.V_KEY, 'up', 'w');
+ this.bindShortcut(
+ this.Shortcut.DIFF_BASE_AGAINST_LEFT, this.V_KEY, 'left', 'a');
+ this.bindShortcut(
+ this.Shortcut.DIFF_RIGHT_AGAINST_LATEST, this.V_KEY, 'right', 'd');
+ this.bindShortcut(
+ this.Shortcut.DIFF_BASE_AGAINST_LATEST, this.V_KEY, 'b');
this.bindShortcut(
this.Shortcut.NEXT_LINE, 'j', 'down');
diff --git a/polygerrit-ui/app/elements/gr-app-init.js b/polygerrit-ui/app/elements/gr-app-init.js
index 780e64a..ea10ce8 100644
--- a/polygerrit-ui/app/elements/gr-app-init.js
+++ b/polygerrit-ui/app/elements/gr-app-init.js
@@ -20,7 +20,6 @@
if (!window.Polymer) {
window.Polymer = {
- passiveTouchGestures: true,
lazyRegister: true,
};
}
diff --git a/polygerrit-ui/app/elements/gr-app.html b/polygerrit-ui/app/elements/gr-app.html
deleted file mode 100644
index 1483f7a..0000000
--- a/polygerrit-ui/app/elements/gr-app.html
+++ /dev/null
@@ -1 +0,0 @@
-<script src='./gr-app.js' type='module'></script>
diff --git a/polygerrit-ui/app/elements/gr-app.js b/polygerrit-ui/app/elements/gr-app.js
index 1300955..e0e7fa9 100644
--- a/polygerrit-ui/app/elements/gr-app.js
+++ b/polygerrit-ui/app/elements/gr-app.js
@@ -26,8 +26,9 @@
* on older touch device.
* See https://github.com/Polymer/polymer/issues/5289
*/
-import {setCancelSyntheticClickEvents} from '@polymer/polymer/lib/utils/settings.js';
+import {setPassiveTouchGestures, setCancelSyntheticClickEvents} from '@polymer/polymer/lib/utils/settings.js';
setCancelSyntheticClickEvents(false);
+setPassiveTouchGestures(true);
import 'polymer-resin/standalone/polymer-resin.js';
import {initGlobalVariables} from './gr-app-global-var-init.js';
diff --git a/polygerrit-ui/app/elements/gr-app_test.html b/polygerrit-ui/app/elements/gr-app_test.html
deleted file mode 100644
index 6322518..0000000
--- a/polygerrit-ui/app/elements/gr-app_test.html
+++ /dev/null
@@ -1,106 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-app</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-app id="app"></gr-app>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../test/common-test-setup.js';
-import './gr-app.js';
-import {appContext} from '../services/app-context.js';
-import {GerritNav} from './core/gr-navigation/gr-navigation.js';
-
-suite('gr-app tests', () => {
- let sandbox;
- let element;
-
- setup(done => {
- sandbox = sinon.sandbox.create();
- sandbox.stub(appContext.reportingService, 'appStarted');
- stub('gr-account-dropdown', {
- _getTopContent: sinon.stub(),
- });
- stub('gr-router', {
- start: sandbox.stub(),
- });
- stub('gr-rest-api-interface', {
- getAccount() { return Promise.resolve({}); },
- getAccountCapabilities() { return Promise.resolve({}); },
- getConfig() {
- return Promise.resolve({
- plugin: {},
- auth: {
- auth_type: undefined,
- },
- });
- },
- getPreferences() { return Promise.resolve({my: []}); },
- getDiffPreferences() { return Promise.resolve({}); },
- getEditPreferences() { return Promise.resolve({}); },
- getVersion() { return Promise.resolve(42); },
- probePath() { return Promise.resolve(42); },
- });
-
- element = fixture('basic');
- flush(done);
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- const appElement = () => element.$['app-element'];
-
- test('reporting', () => {
- assert.isTrue(appElement().reporting.appStarted.calledOnce);
- });
-
- test('reporting called before router start', () => {
- const element = appElement();
- const appStartedStub = element.reporting.appStarted;
- const routerStartStub = element.$.router.start;
- sinon.assert.callOrder(appStartedStub, routerStartStub);
- });
-
- test('passes config to gr-plugin-host', () => {
- const config = appElement().$.restAPI.getConfig;
- return config.lastCall.returnValue.then(config => {
- assert.deepEqual(appElement().$.plugins.config, config);
- });
- });
-
- test('_paramsChanged sets search page', () => {
- appElement()._paramsChanged({base: {view: GerritNav.View.CHANGE}});
- assert.notOk(appElement()._lastSearchPage);
- appElement()._paramsChanged({base: {view: GerritNav.View.SEARCH}});
- assert.ok(appElement()._lastSearchPage);
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/gr-app_test.js b/polygerrit-ui/app/elements/gr-app_test.js
new file mode 100644
index 0000000..4c5e965
--- /dev/null
+++ b/polygerrit-ui/app/elements/gr-app_test.js
@@ -0,0 +1,86 @@
+/**
+ * @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 '../test/common-test-setup-karma.js';
+import './gr-app.js';
+import {appContext} from '../services/app-context.js';
+import {GerritNav} from './core/gr-navigation/gr-navigation.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const basicFixture = fixtureFromTemplate(html`<gr-app id="app"></gr-app>`);
+
+suite('gr-app tests', () => {
+ let element;
+
+ setup(done => {
+ sinon.stub(appContext.reportingService, 'appStarted');
+ stub('gr-account-dropdown', {
+ _getTopContent: sinon.stub(),
+ });
+ stub('gr-router', {
+ start: sinon.stub(),
+ });
+ stub('gr-rest-api-interface', {
+ getAccount() { return Promise.resolve({}); },
+ getAccountCapabilities() { return Promise.resolve({}); },
+ getConfig() {
+ return Promise.resolve({
+ plugin: {},
+ auth: {
+ auth_type: undefined,
+ },
+ });
+ },
+ getPreferences() { return Promise.resolve({my: []}); },
+ getDiffPreferences() { return Promise.resolve({}); },
+ getEditPreferences() { return Promise.resolve({}); },
+ getVersion() { return Promise.resolve(42); },
+ probePath() { return Promise.resolve(42); },
+ });
+
+ element = basicFixture.instantiate();
+ flush(done);
+ });
+
+ const appElement = () => element.$['app-element'];
+
+ test('reporting', () => {
+ assert.isTrue(appElement().reporting.appStarted.calledOnce);
+ });
+
+ test('reporting called before router start', () => {
+ const element = appElement();
+ const appStartedStub = element.reporting.appStarted;
+ const routerStartStub = element.$.router.start;
+ sinon.assert.callOrder(appStartedStub, routerStartStub);
+ });
+
+ test('passes config to gr-plugin-host', () => {
+ const config = appElement().$.restAPI.getConfig;
+ return config.lastCall.returnValue.then(config => {
+ assert.deepEqual(appElement().$.plugins.config, config);
+ });
+ });
+
+ test('_paramsChanged sets search page', () => {
+ appElement()._paramsChanged({base: {view: GerritNav.View.CHANGE}});
+ assert.notOk(appElement()._lastSearchPage);
+ appElement()._paramsChanged({base: {view: GerritNav.View.SEARCH}});
+ assert.ok(appElement()._lastSearchPage);
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/plugins/gr-admin-api/gr-admin-api_test.html b/polygerrit-ui/app/elements/plugins/gr-admin-api/gr-admin-api_test.html
deleted file mode 100644
index a865233..0000000
--- a/polygerrit-ui/app/elements/plugins/gr-admin-api/gr-admin-api_test.html
+++ /dev/null
@@ -1,72 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<title>gr-admin-api</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import '../../shared/gr-js-api-interface/gr-js-api-interface.js';
-import {pluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
-import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit.js';
-
-const pluginApi = _testOnly_initGerritPluginApi();
-
-suite('gr-admin-api tests', () => {
- let sandbox;
- let adminApi;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- let plugin;
- pluginApi.install(p => { plugin = p; }, '0.1',
- 'http://test.com/plugins/testplugin/static/test.js');
- pluginLoader.loadPlugins([]);
- adminApi = plugin.admin();
- });
-
- teardown(() => {
- adminApi = null;
- sandbox.restore();
- });
-
- test('exists', () => {
- assert.isOk(adminApi);
- });
-
- test('addMenuLink', () => {
- adminApi.addMenuLink('text', 'url');
- const links = adminApi.getMenuLinks();
- assert.equal(links.length, 1);
- assert.deepEqual(links[0], {text: 'text', url: 'url', capability: null});
- });
-
- test('addMenuLinkWithCapability', () => {
- adminApi.addMenuLink('text', 'url', 'capability');
- const links = adminApi.getMenuLinks();
- assert.equal(links.length, 1);
- assert.deepEqual(links[0],
- {text: 'text', url: 'url', capability: 'capability'});
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/plugins/gr-admin-api/gr-admin-api_test.js b/polygerrit-ui/app/elements/plugins/gr-admin-api/gr-admin-api_test.js
new file mode 100644
index 0000000..c3552cb
--- /dev/null
+++ b/polygerrit-ui/app/elements/plugins/gr-admin-api/gr-admin-api_test.js
@@ -0,0 +1,59 @@
+/**
+ * @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.
+ */
+
+import '../../../test/common-test-setup-karma.js';
+import '../../shared/gr-js-api-interface/gr-js-api-interface.js';
+import {pluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
+import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit.js';
+
+const pluginApi = _testOnly_initGerritPluginApi();
+
+suite('gr-admin-api tests', () => {
+ let adminApi;
+
+ setup(() => {
+ let plugin;
+ pluginApi.install(p => { plugin = p; }, '0.1',
+ 'http://test.com/plugins/testplugin/static/test.js');
+ pluginLoader.loadPlugins([]);
+ adminApi = plugin.admin();
+ });
+
+ teardown(() => {
+ adminApi = null;
+ });
+
+ test('exists', () => {
+ assert.isOk(adminApi);
+ });
+
+ test('addMenuLink', () => {
+ adminApi.addMenuLink('text', 'url');
+ const links = adminApi.getMenuLinks();
+ assert.equal(links.length, 1);
+ assert.deepEqual(links[0], {text: 'text', url: 'url', capability: null});
+ });
+
+ test('addMenuLinkWithCapability', () => {
+ adminApi.addMenuLink('text', 'url', 'capability');
+ const links = adminApi.getMenuLinks();
+ assert.equal(links.length, 1);
+ assert.deepEqual(links[0],
+ {text: 'text', url: 'url', capability: 'capability'});
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper_test.html b/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper_test.html
deleted file mode 100644
index 50f9002..0000000
--- a/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper_test.html
+++ /dev/null
@@ -1,101 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<title>gr-attribute-helper</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<dom-element id="some-element">
- <script type="module">
-import '../../../test/common-test-setup.js';
-import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
-Polymer({
- is: 'some-element',
- properties: {
- fooBar: {
- type: Object,
- notify: true,
- },
- },
-});
-</script>
-
-</dom-element>
-
-<test-fixture id="basic">
- <template>
- <some-element></some-element>
- </template>
-</test-fixture>
-
-<script type="module">
-import {GrAttributeHelper} from './gr-attribute-helper.js';
-
-suite('gr-attribute-helper tests', () => {
- let element;
- let instance;
- let sandbox;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- instance = new GrAttributeHelper(element);
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('resolved on value change from undefined', () => {
- const promise = instance.get('fooBar').then(value => {
- assert.equal(value, 'foo! bar!');
- });
- element.fooBar = 'foo! bar!';
- return promise;
- });
-
- test('resolves to current attribute value', () => {
- element.fooBar = 'foo-foo-bar';
- const promise = instance.get('fooBar').then(value => {
- assert.equal(value, 'foo-foo-bar');
- });
- element.fooBar = 'no bar';
- return promise;
- });
-
- test('bind', () => {
- const stub = sandbox.stub();
- element.fooBar = 'bar foo';
- const unbind = instance.bind('fooBar', stub);
- element.fooBar = 'partridge in a foo tree';
- element.fooBar = 'five gold bars';
- assert.equal(stub.callCount, 3);
- assert.deepEqual(stub.args[0], ['bar foo']);
- assert.deepEqual(stub.args[1], ['partridge in a foo tree']);
- assert.deepEqual(stub.args[2], ['five gold bars']);
- stub.reset();
- unbind();
- instance.fooBar = 'ladies dancing';
- assert.isFalse(stub.called);
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper_test.js b/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper_test.js
new file mode 100644
index 0000000..ea7bdc3
--- /dev/null
+++ b/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper_test.js
@@ -0,0 +1,76 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
+import {GrAttributeHelper} from './gr-attribute-helper.js';
+
+Polymer({
+ is: 'gr-attrubute-helper-some-element',
+ properties: {
+ fooBar: {
+ type: Object,
+ notify: true,
+ },
+ },
+});
+
+const basicFixture = fixtureFromElement('gr-attrubute-helper-some-element');
+
+suite('gr-attribute-helper tests', () => {
+ let element;
+ let instance;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ instance = new GrAttributeHelper(element);
+ });
+
+ test('resolved on value change from undefined', () => {
+ const promise = instance.get('fooBar').then(value => {
+ assert.equal(value, 'foo! bar!');
+ });
+ element.fooBar = 'foo! bar!';
+ return promise;
+ });
+
+ test('resolves to current attribute value', () => {
+ element.fooBar = 'foo-foo-bar';
+ const promise = instance.get('fooBar').then(value => {
+ assert.equal(value, 'foo-foo-bar');
+ });
+ element.fooBar = 'no bar';
+ return promise;
+ });
+
+ test('bind', () => {
+ const stub = sinon.stub();
+ element.fooBar = 'bar foo';
+ const unbind = instance.bind('fooBar', stub);
+ element.fooBar = 'partridge in a foo tree';
+ element.fooBar = 'five gold bars';
+ assert.equal(stub.callCount, 3);
+ assert.deepEqual(stub.args[0], ['bar foo']);
+ assert.deepEqual(stub.args[1], ['partridge in a foo tree']);
+ assert.deepEqual(stub.args[2], ['five gold bars']);
+ stub.reset();
+ unbind();
+ instance.fooBar = 'ladies dancing';
+ assert.isFalse(stub.called);
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/plugins/gr-dom-hooks/gr-dom-hooks.js b/polygerrit-ui/app/elements/plugins/gr-dom-hooks/gr-dom-hooks.js
index 4822163..93cbcf5 100644
--- a/polygerrit-ui/app/elements/plugins/gr-dom-hooks/gr-dom-hooks.js
+++ b/polygerrit-ui/app/elements/plugins/gr-dom-hooks/gr-dom-hooks.js
@@ -27,7 +27,12 @@
if (opt_moduleName) {
return endpointName + ' ' + opt_moduleName;
} else {
- return this._plugin.getPluginName() + '-autogenerated-' + endpointName;
+ // lowercase in case plugin's name contains uppercase letters
+ // TODO: this still can not prevent if plugin has invalid char
+ // other than uppercase, but is the first step
+ // https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
+ const pluginName = this._plugin.getPluginName() || 'unknown_plugin';
+ return pluginName.toLowerCase() + '-autogenerated-' + endpointName;
}
};
diff --git a/polygerrit-ui/app/elements/plugins/gr-dom-hooks/gr-dom-hooks_test.html b/polygerrit-ui/app/elements/plugins/gr-dom-hooks/gr-dom-hooks_test.js
similarity index 73%
rename from polygerrit-ui/app/elements/plugins/gr-dom-hooks/gr-dom-hooks_test.html
rename to polygerrit-ui/app/elements/plugins/gr-dom-hooks/gr-dom-hooks_test.js
index 17a22e9..a2b92ec 100644
--- a/polygerrit-ui/app/elements/plugins/gr-dom-hooks/gr-dom-hooks_test.html
+++ b/polygerrit-ui/app/elements/plugins/gr-dom-hooks/gr-dom-hooks_test.js
@@ -1,37 +1,21 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<title>gr-dom-hooks</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <div></div>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import '../../shared/gr-js-api-interface/gr-js-api-interface.js';
import {GrDomHook, GrDomHooksManager} from './gr-dom-hooks.js';
import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit.js';
@@ -48,25 +32,20 @@
];
let instance;
- let sandbox;
+
let hook;
let hookInternal;
setup(() => {
- sandbox = sinon.sandbox.create();
let plugin;
pluginApi.install(p => { plugin = p; }, '0.1',
'http://test.com/plugins/testplugin/static/test.js');
instance = new GrDomHooksManager(plugin);
});
- teardown(() => {
- sandbox.restore();
- });
-
suite('placeholder', () => {
setup(()=>{
- sandbox.stub(GrDomHook.prototype, '_createPlaceholder');
+ sinon.stub(GrDomHook.prototype, '_createPlaceholder');
hookInternal = instance.getDomHook('foo-bar');
hook = hookInternal.getPublicAPI();
});
@@ -104,7 +83,7 @@
});
test('onAttached', () => {
- const onAttachedSpy = sandbox.spy();
+ const onAttachedSpy = sinon.spy();
hook.onAttached(onAttachedSpy);
const [el1, el2] = [
document.createElement(hook.getModuleName()),
@@ -117,7 +96,7 @@
});
test('onDetached', () => {
- const onDetachedSpy = sandbox.spy();
+ const onDetachedSpy = sinon.spy();
hook.onDetached(onDetachedSpy);
const [el1, el2] = [
document.createElement(hook.getModuleName()),
@@ -163,4 +142,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator.js b/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator.js
index 4991770..c91819a 100644
--- a/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator.js
+++ b/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator.js
@@ -15,7 +15,6 @@
* limitations under the License.
*/
import '../../shared/gr-js-api-interface/gr-js-api-interface.js';
-import {importHref} from '../../../scripts/import-href.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
@@ -65,15 +64,6 @@
pluginEndpoints.onDetachedEndpoint(this.name, this._endpointCallBack);
}
- /**
- * @suppress {checkTypes}
- */
- _import(url) {
- return new Promise((resolve, reject) => {
- importHref(url, resolve, reject);
- });
- }
-
_initDecoration(name, plugin, slot) {
const el = document.createElement(name);
return this._initProperties(el, plugin,
@@ -133,9 +123,9 @@
`plugin ${plugin.getPluginName()}, endpoint ${this.name}`);
}, INIT_PROPERTIES_TIMEOUT_MS));
return Promise.race([timeout, Promise.all(expectProperties)])
- .then(() => {
- clearTimeout(timeoutId);
- return el;
+ .then(() => el)
+ .finally(() => {
+ if (timeoutId) clearTimeout(timeoutId);
});
}
@@ -174,10 +164,7 @@
pluginEndpoints.onNewEndpoint(this.name, this._endpointCallBack);
if (this.name) {
pluginLoader.awaitPluginsLoaded()
- .then(() => Promise.all(
- pluginEndpoints.getPlugins(this.name).map(
- pluginUrl => this._import(pluginUrl)))
- )
+ .then(() => pluginEndpoints.getAndImportPlugins(this.name))
.then(() =>
pluginEndpoints
.getDetails(this.name)
diff --git a/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator_test.html b/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator_test.js
similarity index 71%
rename from polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator_test.html
rename to polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator_test.js
index 890a457..72c73b7 100644
--- a/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator_test.html
+++ b/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator_test.js
@@ -1,76 +1,64 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<title>gr-endpoint-decorator</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <div>
- <gr-endpoint-decorator name="first">
- <gr-endpoint-param name="someparam" value="barbar"></gr-endpoint-param>
- <p>
- <span>test slot</span>
- <gr-endpoint-slot name="test"></gr-endpoint-slot>
- </p>
- </gr-endpoint-decorator>
- <gr-endpoint-decorator name="second">
- <gr-endpoint-param name="someparam" value="foofoo"></gr-endpoint-param>
- </gr-endpoint-decorator>
- <gr-endpoint-decorator name="banana">
- <gr-endpoint-param name="someParam" value="yes"></gr-endpoint-param>
- </gr-endpoint-decorator>
- </div>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-endpoint-decorator.js';
import '../gr-endpoint-param/gr-endpoint-param.js';
import '../gr-endpoint-slot/gr-endpoint-slot.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
import {resetPlugins} from '../../../test/test-utils.js';
import {pluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
+import {pluginEndpoints} from '../../shared/gr-js-api-interface/gr-plugin-endpoints.js';
import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit.js';
const pluginApi = _testOnly_initGerritPluginApi();
+const basicFixture = fixtureFromTemplate(
+ html`<div>
+ <gr-endpoint-decorator name="first">
+ <gr-endpoint-param name="someparam" value="barbar"></gr-endpoint-param>
+ <p>
+ <span>test slot</span>
+ <gr-endpoint-slot name="test"></gr-endpoint-slot>
+ </p>
+ </gr-endpoint-decorator>
+ <gr-endpoint-decorator name="second">
+ <gr-endpoint-param name="someparam" value="foofoo"></gr-endpoint-param>
+ </gr-endpoint-decorator>
+ <gr-endpoint-decorator name="banana">
+ <gr-endpoint-param name="someParam" value="yes"></gr-endpoint-param>
+ </gr-endpoint-decorator>
+</div>`
+);
+
suite('gr-endpoint-decorator', () => {
let container;
- let sandbox;
+
let plugin;
let decorationHook;
let decorationHookWithSlot;
let replacementHook;
setup(done => {
- sandbox = sinon.sandbox.create();
- stub('gr-endpoint-decorator', {
- _import: sandbox.stub().returns(Promise.resolve()),
- });
resetPlugins();
- container = fixture('basic');
+ container = basicFixture.instantiate();
+ sinon.stub(pluginEndpoints, 'importUrl')
+ .callsFake( url => Promise.resolve());
pluginApi.install(p => plugin = p, '0.1',
'http://some/plugin/url.html');
// Decoration
@@ -89,17 +77,16 @@
});
teardown(() => {
- sandbox.restore();
+ resetPlugins();
});
test('imports plugin-provided modules into endpoints', () => {
const endpoints =
Array.from(container.querySelectorAll('gr-endpoint-decorator'));
assert.equal(endpoints.length, 3);
- endpoints.forEach(element => {
- assert.isTrue(
- element._import.calledWith(new URL('http://some/plugin/url.html')));
- });
+ assert.isTrue(pluginEndpoints.importUrl.calledWith(
+ new URL('http://some/plugin/url.html')
+ ));
});
test('decoration', () => {
@@ -124,7 +111,7 @@
test('decoration with slot', () => {
const element =
container.querySelector('gr-endpoint-decorator[name="first"]');
- const modules = [...dom(element).querySelectorAll('p > some-module-2')];
+ const modules = [...dom(element).querySelectorAll('some-module-2')];
assert.equal(modules.length, 1);
const [module] = modules;
assert.isOk(module);
@@ -225,4 +212,3 @@
});
});
});
-</script>
diff --git a/polygerrit-ui/app/elements/plugins/gr-event-helper/gr-event-helper_test.html b/polygerrit-ui/app/elements/plugins/gr-event-helper/gr-event-helper_test.html
deleted file mode 100644
index a27c817..0000000
--- a/polygerrit-ui/app/elements/plugins/gr-event-helper/gr-event-helper_test.html
+++ /dev/null
@@ -1,138 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<title>gr-event-helper</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<dom-element id="some-element">
- <script type="module">
-import '../../../test/common-test-setup.js';
-import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
-Polymer({
- is: 'some-element',
-
- properties: {
- fooBar: {
- type: Object,
- notify: true,
- },
- },
-});
-</script>
-
-</dom-element>
-
-<test-fixture id="basic">
- <template>
- <some-element></some-element>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import {addListener} from '@polymer/polymer/lib/utils/gestures.js';
-import {GrEventHelper} from './gr-event-helper.js';
-
-suite('gr-event-helper tests', () => {
- let element;
- let instance;
- let sandbox;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- instance = new GrEventHelper(element);
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('onTap()', done => {
- instance.onTap(() => {
- done();
- });
- MockInteractions.tap(element);
- });
-
- test('onTap() cancel', () => {
- const tapStub = sandbox.stub();
- addListener(element.parentElement, 'tap', tapStub);
- instance.onTap(() => false);
- MockInteractions.tap(element);
- flushAsynchronousOperations();
- assert.isFalse(tapStub.called);
- });
-
- test('onClick() cancel', () => {
- const tapStub = sandbox.stub();
- element.parentElement.addEventListener('click', tapStub);
- instance.onTap(() => false);
- MockInteractions.tap(element);
- flushAsynchronousOperations();
- assert.isFalse(tapStub.called);
- });
-
- test('captureTap()', done => {
- instance.captureTap(() => {
- done();
- });
- MockInteractions.tap(element);
- });
-
- test('captureClick()', done => {
- instance.captureClick(() => {
- done();
- });
- MockInteractions.tap(element);
- });
-
- test('captureTap() cancels tap()', () => {
- const tapStub = sandbox.stub();
- addListener(element.parentElement, 'tap', tapStub);
- instance.captureTap(() => false);
- MockInteractions.tap(element);
- flushAsynchronousOperations();
- assert.isFalse(tapStub.called);
- });
-
- test('captureClick() cancels click()', () => {
- const tapStub = sandbox.stub();
- element.addEventListener('click', tapStub);
- instance.captureTap(() => false);
- MockInteractions.tap(element);
- flushAsynchronousOperations();
- assert.isFalse(tapStub.called);
- });
-
- test('on()', done => {
- instance.on('foo', () => {
- done();
- });
- element.dispatchEvent(
- new CustomEvent('foo', {
- composed: true, bubbles: true,
- }));
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/plugins/gr-event-helper/gr-event-helper_test.js b/polygerrit-ui/app/elements/plugins/gr-event-helper/gr-event-helper_test.js
new file mode 100644
index 0000000..e56278f
--- /dev/null
+++ b/polygerrit-ui/app/elements/plugins/gr-event-helper/gr-event-helper_test.js
@@ -0,0 +1,112 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import {addListener} from '@polymer/polymer/lib/utils/gestures.js';
+import {GrEventHelper} from './gr-event-helper.js';
+import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
+
+Polymer({
+ is: 'gr-event-helper-some-element',
+
+ properties: {
+ fooBar: {
+ type: Object,
+ notify: true,
+ },
+ },
+});
+
+const basicFixture = fixtureFromElement('gr-event-helper-some-element');
+
+suite('gr-event-helper tests', () => {
+ let element;
+ let instance;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ instance = new GrEventHelper(element);
+ });
+
+ test('onTap()', done => {
+ instance.onTap(() => {
+ done();
+ });
+ MockInteractions.tap(element);
+ });
+
+ test('onTap() cancel', () => {
+ const tapStub = sinon.stub();
+ addListener(element.parentElement, 'tap', tapStub);
+ instance.onTap(() => false);
+ MockInteractions.tap(element);
+ flushAsynchronousOperations();
+ assert.isFalse(tapStub.called);
+ });
+
+ test('onClick() cancel', () => {
+ const tapStub = sinon.stub();
+ element.parentElement.addEventListener('click', tapStub);
+ instance.onTap(() => false);
+ MockInteractions.tap(element);
+ flushAsynchronousOperations();
+ assert.isFalse(tapStub.called);
+ });
+
+ test('captureTap()', done => {
+ instance.captureTap(() => {
+ done();
+ });
+ MockInteractions.tap(element);
+ });
+
+ test('captureClick()', done => {
+ instance.captureClick(() => {
+ done();
+ });
+ MockInteractions.tap(element);
+ });
+
+ test('captureTap() cancels tap()', () => {
+ const tapStub = sinon.stub();
+ addListener(element.parentElement, 'tap', tapStub);
+ instance.captureTap(() => false);
+ MockInteractions.tap(element);
+ flushAsynchronousOperations();
+ assert.isFalse(tapStub.called);
+ });
+
+ test('captureClick() cancels click()', () => {
+ const tapStub = sinon.stub();
+ element.addEventListener('click', tapStub);
+ instance.captureTap(() => false);
+ MockInteractions.tap(element);
+ flushAsynchronousOperations();
+ assert.isFalse(tapStub.called);
+ });
+
+ test('on()', done => {
+ instance.on('foo', () => {
+ done();
+ });
+ element.dispatchEvent(
+ new CustomEvent('foo', {
+ composed: true, bubbles: true,
+ }));
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/plugins/gr-external-style/gr-external-style.js b/polygerrit-ui/app/elements/plugins/gr-external-style/gr-external-style.js
index f27053d..16176b3 100644
--- a/polygerrit-ui/app/elements/plugins/gr-external-style/gr-external-style.js
+++ b/polygerrit-ui/app/elements/plugins/gr-external-style/gr-external-style.js
@@ -15,7 +15,6 @@
* limitations under the License.
*/
import '../../shared/gr-js-api-interface/gr-js-api-interface.js';
-import {importHref} from '../../../scripts/import-href.js';
import {updateStyles} from '@polymer/polymer/lib/mixins/element-mixin.js';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
@@ -35,10 +34,6 @@
static get properties() {
return {
name: String,
- _urlsImported: {
- type: Array,
- value() { return []; },
- },
_stylesApplied: {
type: Array,
value() { return []; },
@@ -46,23 +41,6 @@
};
}
- _importHref(url, resolve, reject) {
- // It is impossible to mock es6-module imported function.
- // The _importHref function is mocked in test.
- importHref(url, resolve, reject);
- }
-
- /**
- * @suppress {checkTypes}
- */
- _import(url) {
- if (this._urlsImported.includes(url)) { return Promise.resolve(); }
- this._urlsImported.push(url);
- return new Promise((resolve, reject) => {
- this._importHref(url, resolve, reject);
- });
- }
-
_applyStyle(name) {
if (this._stylesApplied.includes(name)) { return; }
this._stylesApplied.push(name);
@@ -79,14 +57,13 @@
}
_importAndApply() {
- Promise.all(pluginEndpoints.getPlugins(this.name).map(
- pluginUrl => this._import(pluginUrl))
- ).then(() => {
- const moduleNames = pluginEndpoints.getModules(this.name);
- for (const name of moduleNames) {
- this._applyStyle(name);
- }
- });
+ pluginEndpoints.getAndImportPlugins(this.name)
+ .then(() => {
+ const moduleNames = pluginEndpoints.getModules(this.name);
+ for (const name of moduleNames) {
+ this._applyStyle(name);
+ }
+ });
}
/** @override */
diff --git a/polygerrit-ui/app/elements/plugins/gr-external-style/gr-external-style_test.html b/polygerrit-ui/app/elements/plugins/gr-external-style/gr-external-style_test.html
deleted file mode 100644
index 8f85348..0000000
--- a/polygerrit-ui/app/elements/plugins/gr-external-style/gr-external-style_test.html
+++ /dev/null
@@ -1,133 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<title>gr-external-style</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<test-fixture id="basic">
- <template>
- <gr-external-style name="foo"></gr-external-style>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-external-style.js';
-import {pluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
-import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit.js';
-
-const pluginApi = _testOnly_initGerritPluginApi();
-
-suite('gr-external-style integration tests', () => {
- const TEST_URL = 'http://some/plugin/url.html';
-
- let sandbox;
- let element;
- let plugin;
- let importHrefStub;
-
- const installPlugin = () => {
- if (plugin) { return; }
- pluginApi.install(p => {
- plugin = p;
- }, '0.1', TEST_URL);
- };
-
- const createElement = () => {
- element = fixture('basic');
- sandbox.spy(element, '_applyStyle');
- };
-
- /**
- * Installs the plugin, creates the element, registers style module.
- */
- const lateRegister = () => {
- installPlugin();
- createElement();
- plugin.registerStyleModule('foo', 'some-module');
- };
-
- /**
- * Installs the plugin, registers style module, creates the element.
- */
- const earlyRegister = () => {
- installPlugin();
- plugin.registerStyleModule('foo', 'some-module');
- createElement();
- };
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- importHrefStub = sandbox.stub().callsArg(1);
- stub('gr-external-style', {
- _importHref: (url, resolve, reject) => {
- importHrefStub(url, resolve, reject);
- },
- });
- sandbox.stub(pluginLoader, 'awaitPluginsLoaded')
- .returns(Promise.resolve());
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('imports plugin-provided module', async () => {
- lateRegister();
- await new Promise(flush);
- assert.isTrue(importHrefStub.calledWith(new URL(TEST_URL)));
- });
-
- test('applies plugin-provided styles', async () => {
- lateRegister();
- await new Promise(flush);
- assert.isTrue(element._applyStyle.calledWith('some-module'));
- });
-
- test('does not double import', async () => {
- earlyRegister();
- await new Promise(flush);
- plugin.registerStyleModule('foo', 'some-module');
- await new Promise(flush);
- const urlsImported =
- element._urlsImported.filter(url => url.toString() === TEST_URL);
- assert.strictEqual(urlsImported.length, 1);
- });
-
- test('does not double apply', async () => {
- earlyRegister();
- await new Promise(flush);
- plugin.registerStyleModule('foo', 'some-module');
- await new Promise(flush);
- const stylesApplied =
- element._stylesApplied.filter(name => name === 'some-module');
- assert.strictEqual(stylesApplied.length, 1);
- });
-
- test('loads and applies preloaded modules', async () => {
- earlyRegister();
- await new Promise(flush);
- assert.isTrue(importHrefStub.calledWith(new URL(TEST_URL)));
- assert.isTrue(element._applyStyle.calledWith('some-module'));
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/plugins/gr-external-style/gr-external-style_test.js b/polygerrit-ui/app/elements/plugins/gr-external-style/gr-external-style_test.js
new file mode 100644
index 0000000..6659207
--- /dev/null
+++ b/polygerrit-ui/app/elements/plugins/gr-external-style/gr-external-style_test.js
@@ -0,0 +1,117 @@
+/**
+ * @license
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import '../../../test/common-test-setup-karma.js';
+import {resetPlugins} from '../../../test/test-utils.js';
+import './gr-external-style.js';
+import {pluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
+import {pluginEndpoints} from '../../shared/gr-js-api-interface/gr-plugin-endpoints.js';
+import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const pluginApi = _testOnly_initGerritPluginApi();
+
+const basicFixture = fixtureFromTemplate(
+ html`<gr-external-style name="foo"></gr-external-style>`
+);
+
+suite('gr-external-style integration tests', () => {
+ const TEST_URL = 'http://some.com/plugins/url.html';
+
+ let element;
+ let plugin;
+
+ const installPlugin = () => {
+ if (plugin) { return; }
+ pluginApi.install(p => {
+ plugin = p;
+ }, '0.1', TEST_URL);
+ };
+
+ const createElement = () => {
+ element = basicFixture.instantiate();
+ sinon.spy(element, '_applyStyle');
+ };
+
+ /**
+ * Installs the plugin, creates the element, registers style module.
+ */
+ const lateRegister = () => {
+ installPlugin();
+ createElement();
+ plugin.registerStyleModule('foo', 'some-module');
+ };
+
+ /**
+ * Installs the plugin, registers style module, creates the element.
+ */
+ const earlyRegister = () => {
+ installPlugin();
+ plugin.registerStyleModule('foo', 'some-module');
+ createElement();
+ };
+
+ setup(() => {
+ sinon.stub(pluginEndpoints, 'importUrl')
+ .callsFake( url => Promise.resolve());
+ sinon.stub(pluginLoader, 'awaitPluginsLoaded')
+ .returns(Promise.resolve());
+ });
+
+ teardown(() => {
+ resetPlugins();
+ document.body.querySelectorAll('custom-style')
+ .forEach(style => style.remove());
+ });
+
+ test('imports plugin-provided module', async () => {
+ lateRegister();
+ await new Promise(flush);
+ assert.isTrue(pluginEndpoints.importUrl.calledWith(new URL(TEST_URL)));
+ });
+
+ test('applies plugin-provided styles', async () => {
+ lateRegister();
+ await new Promise(flush);
+ assert.isTrue(element._applyStyle.calledWith('some-module'));
+ });
+
+ test('does not double import', async () => {
+ earlyRegister();
+ await new Promise(flush);
+ plugin.registerStyleModule('foo', 'some-module');
+ await new Promise(flush);
+ // since loaded, should not call again
+ assert.isFalse(pluginEndpoints.importUrl.calledOnce);
+ });
+
+ test('does not double apply', async () => {
+ earlyRegister();
+ await new Promise(flush);
+ plugin.registerStyleModule('foo', 'some-module');
+ await new Promise(flush);
+ const stylesApplied =
+ element._stylesApplied.filter(name => name === 'some-module');
+ assert.strictEqual(stylesApplied.length, 1);
+ });
+
+ test('loads and applies preloaded modules', async () => {
+ earlyRegister();
+ await new Promise(flush);
+ assert.isTrue(element._applyStyle.calledWith('some-module'));
+ });
+});
diff --git a/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host.js b/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host.js
index 1833efa..46e37e1 100644
--- a/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host.js
+++ b/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host.js
@@ -37,9 +37,10 @@
_configChanged(config) {
const plugins = config.plugin;
- const htmlPlugins = (plugins.html_resource_paths || []);
- const jsPlugins =
- this._handleMigrations(plugins.js_resource_paths || [], htmlPlugins);
+ const htmlPlugins = (plugins && plugins.html_resource_paths || []);
+ const jsPlugins = this._handleMigrations(
+ plugins && plugins.js_resource_paths || [], htmlPlugins
+ );
const shouldLoadTheme = config.default_theme &&
!pluginLoader.isPluginPreloaded('preloaded:gerrit-theme');
const themeToLoad =
diff --git a/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host_test.html b/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host_test.html
deleted file mode 100644
index 2c8a8c0..0000000
--- a/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host_test.html
+++ /dev/null
@@ -1,94 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<title>gr-plugin-host</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-plugin-host></gr-plugin-host>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-plugin-host.js';
-import {pluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
-
-suite('gr-plugin-host tests', () => {
- let element;
- let sandbox;
-
- setup(() => {
- element = fixture('basic');
- sandbox = sinon.sandbox.create();
- sandbox.stub(document.body, 'appendChild');
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('load plugins should be called', () => {
- sandbox.stub(pluginLoader, 'loadPlugins');
- element.config = {
- plugin: {
- html_resource_paths: ['plugins/foo/bar', 'plugins/baz'],
- js_resource_paths: ['plugins/42'],
- },
- };
- assert.isTrue(pluginLoader.loadPlugins.calledOnce);
- assert.isTrue(pluginLoader.loadPlugins.calledWith([
- 'plugins/42', 'plugins/foo/bar', 'plugins/baz',
- ], {}));
- });
-
- test('theme plugins should be loaded if enabled', () => {
- sandbox.stub(pluginLoader, 'loadPlugins');
- element.config = {
- default_theme: 'gerrit-theme.html',
- plugin: {
- html_resource_paths: ['plugins/foo/bar', 'plugins/baz'],
- js_resource_paths: ['plugins/42'],
- },
- };
- assert.isTrue(pluginLoader.loadPlugins.calledOnce);
- assert.isTrue(pluginLoader.loadPlugins.calledWith([
- 'gerrit-theme.html', 'plugins/42', 'plugins/foo/bar', 'plugins/baz',
- ], {'gerrit-theme.html': {sync: true}}));
- });
-
- test('skip theme if preloaded', () => {
- sandbox.stub(pluginLoader, 'isPluginPreloaded')
- .withArgs('preloaded:gerrit-theme')
- .returns(true);
- sandbox.stub(pluginLoader, 'loadPlugins');
- element.config = {
- default_theme: '/oof',
- plugin: {},
- };
- assert.isTrue(pluginLoader.loadPlugins.calledOnce);
- assert.isTrue(pluginLoader.loadPlugins.calledWith([], {}));
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host_test.js b/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host_test.js
new file mode 100644
index 0000000..83e0a84
--- /dev/null
+++ b/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host_test.js
@@ -0,0 +1,75 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-plugin-host.js';
+import {pluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
+
+const basicFixture = fixtureFromElement('gr-plugin-host');
+
+suite('gr-plugin-host tests', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+
+ sinon.stub(document.body, 'appendChild');
+ });
+
+ test('load plugins should be called', () => {
+ sinon.stub(pluginLoader, 'loadPlugins');
+ element.config = {
+ plugin: {
+ html_resource_paths: ['plugins/foo/bar', 'plugins/baz'],
+ js_resource_paths: ['plugins/42'],
+ },
+ };
+ assert.isTrue(pluginLoader.loadPlugins.calledOnce);
+ assert.isTrue(pluginLoader.loadPlugins.calledWith([
+ 'plugins/42', 'plugins/foo/bar', 'plugins/baz',
+ ], {}));
+ });
+
+ test('theme plugins should be loaded if enabled', () => {
+ sinon.stub(pluginLoader, 'loadPlugins');
+ element.config = {
+ default_theme: 'gerrit-theme.html',
+ plugin: {
+ html_resource_paths: ['plugins/foo/bar', 'plugins/baz'],
+ js_resource_paths: ['plugins/42'],
+ },
+ };
+ assert.isTrue(pluginLoader.loadPlugins.calledOnce);
+ assert.isTrue(pluginLoader.loadPlugins.calledWith([
+ 'gerrit-theme.html', 'plugins/42', 'plugins/foo/bar', 'plugins/baz',
+ ], {'gerrit-theme.html': {sync: true}}));
+ });
+
+ test('skip theme if preloaded', () => {
+ sinon.stub(pluginLoader, 'isPluginPreloaded')
+ .withArgs('preloaded:gerrit-theme')
+ .returns(true);
+ sinon.stub(pluginLoader, 'loadPlugins');
+ element.config = {
+ default_theme: '/oof',
+ plugin: {},
+ };
+ assert.isTrue(pluginLoader.loadPlugins.calledOnce);
+ assert.isTrue(pluginLoader.loadPlugins.calledWith([], {}));
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-plugin-popup_test.html b/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-plugin-popup_test.html
deleted file mode 100644
index 2e65365..0000000
--- a/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-plugin-popup_test.html
+++ /dev/null
@@ -1,69 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<title>gr-plugin-popup</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-plugin-popup></gr-plugin-popup>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-plugin-popup.js';
-suite('gr-plugin-popup tests', () => {
- let element;
- let sandbox;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- stub('gr-overlay', {
- open: sandbox.stub().returns(Promise.resolve()),
- close: sandbox.stub(),
- });
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('exists', () => {
- assert.isOk(element);
- });
-
- test('open uses open() from gr-overlay', done => {
- element.open().then(() => {
- assert.isTrue(element.$.overlay.open.called);
- done();
- });
- });
-
- test('close uses close() from gr-overlay', () => {
- element.close();
- assert.isTrue(element.$.overlay.close.called);
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-plugin-popup_test.js b/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-plugin-popup_test.js
new file mode 100644
index 0000000..f2d83e8
--- /dev/null
+++ b/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-plugin-popup_test.js
@@ -0,0 +1,50 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-plugin-popup.js';
+
+const basicFixture = fixtureFromElement('gr-plugin-popup');
+
+suite('gr-plugin-popup tests', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ stub('gr-overlay', {
+ open: sinon.stub().returns(Promise.resolve()),
+ close: sinon.stub(),
+ });
+ });
+
+ test('exists', () => {
+ assert.isOk(element);
+ });
+
+ test('open uses open() from gr-overlay', done => {
+ element.open().then(() => {
+ assert.isTrue(element.$.overlay.open.called);
+ done();
+ });
+ });
+
+ test('close uses close() from gr-overlay', () => {
+ element.close();
+ assert.isTrue(element.$.overlay.close.called);
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-popup-interface_test.html b/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-popup-interface_test.html
deleted file mode 100644
index 62ab0e7..0000000
--- a/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-popup-interface_test.html
+++ /dev/null
@@ -1,127 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<title>gr-popup-interface</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="container">
- <template>
- <div></div>
- </template>
-</test-fixture>
-
-<dom-module id="gr-user-test-popup">
- <template>
- <div id="barfoo">some test module</div>
- </template>
- <script type="module">
-import '../../../test/common-test-setup.js';
-import '../../shared/gr-js-api-interface/gr-js-api-interface.js';
-import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
-Polymer({is: 'gr-user-test-popup'});
-</script>
-</dom-module>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import '../../shared/gr-js-api-interface/gr-js-api-interface.js';
-import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
-import {GrPopupInterface} from './gr-popup-interface.js';
-import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit.js';
-
-const pluginApi = _testOnly_initGerritPluginApi();
-suite('gr-popup-interface tests', () => {
- let container;
- let instance;
- let plugin;
- let sandbox;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- pluginApi.install(p => { plugin = p; }, '0.1',
- 'http://test.com/plugins/testplugin/static/test.js');
- container = fixture('container');
- sandbox.stub(plugin, 'hook').returns({
- getLastAttached() {
- return Promise.resolve(container);
- },
- });
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- suite('manual', () => {
- setup(() => {
- instance = new GrPopupInterface(plugin);
- });
-
- test('open', done => {
- instance.open().then(api => {
- assert.strictEqual(api, instance);
- const manual = document.createElement('div');
- manual.id = 'foobar';
- manual.innerHTML = 'manual content';
- api._getElement().appendChild(manual);
- flushAsynchronousOperations();
- assert.equal(
- container.querySelector('#foobar').textContent, 'manual content');
- done();
- });
- });
-
- test('close', done => {
- instance.open().then(api => {
- assert.isTrue(api._getElement().node.opened);
- api.close();
- assert.isFalse(api._getElement().node.opened);
- done();
- });
- });
- });
-
- suite('components', () => {
- setup(() => {
- instance = new GrPopupInterface(plugin, 'gr-user-test-popup');
- });
-
- test('open', done => {
- instance.open().then(api => {
- assert.isNotNull(
- dom(container).querySelector('gr-user-test-popup'));
- done();
- });
- });
-
- test('close', done => {
- instance.open().then(api => {
- assert.isTrue(api._getElement().node.opened);
- api.close();
- assert.isFalse(api._getElement().node.opened);
- done();
- });
- });
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-popup-interface_test.js b/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-popup-interface_test.js
new file mode 100644
index 0000000..9312332
--- /dev/null
+++ b/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-popup-interface_test.js
@@ -0,0 +1,107 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import '../../shared/gr-js-api-interface/gr-js-api-interface.js';
+import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+import {GrPopupInterface} from './gr-popup-interface.js';
+import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+import {PolymerElement} from '@polymer/polymer/polymer-element.js';
+
+class GrUserTestPopupElement extends PolymerElement {
+ static get is() { return 'gr-user-test-popup'; }
+
+ static get template() {
+ return html`<div id="barfoo">some test module</div>`;
+ }
+}
+
+customElements.define(GrUserTestPopupElement.is, GrUserTestPopupElement);
+
+const containerFixture = fixtureFromElement('div');
+
+const pluginApi = _testOnly_initGerritPluginApi();
+suite('gr-popup-interface tests', () => {
+ let container;
+ let instance;
+ let plugin;
+
+ setup(() => {
+ pluginApi.install(p => { plugin = p; }, '0.1',
+ 'http://test.com/plugins/testplugin/static/test.js');
+ container = containerFixture.instantiate();
+ sinon.stub(plugin, 'hook').returns({
+ getLastAttached() {
+ return Promise.resolve(container);
+ },
+ });
+ });
+
+ suite('manual', () => {
+ setup(() => {
+ instance = new GrPopupInterface(plugin);
+ });
+
+ test('open', done => {
+ instance.open().then(api => {
+ assert.strictEqual(api, instance);
+ const manual = document.createElement('div');
+ manual.id = 'foobar';
+ manual.innerHTML = 'manual content';
+ api._getElement().appendChild(manual);
+ flushAsynchronousOperations();
+ assert.equal(
+ container.querySelector('#foobar').textContent, 'manual content');
+ done();
+ });
+ });
+
+ test('close', done => {
+ instance.open().then(api => {
+ assert.isTrue(api._getElement().node.opened);
+ api.close();
+ assert.isFalse(api._getElement().node.opened);
+ done();
+ });
+ });
+ });
+
+ suite('components', () => {
+ setup(() => {
+ instance = new GrPopupInterface(plugin, 'gr-user-test-popup');
+ });
+
+ test('open', done => {
+ instance.open().then(api => {
+ assert.isNotNull(
+ dom(container).querySelector('gr-user-test-popup'));
+ done();
+ });
+ });
+
+ test('close', done => {
+ instance.open().then(api => {
+ assert.isTrue(api._getElement().node.opened);
+ api.close();
+ assert.isFalse(api._getElement().node.opened);
+ done();
+ });
+ });
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/plugins/gr-repo-api/gr-repo-api_test.html b/polygerrit-ui/app/elements/plugins/gr-repo-api/gr-repo-api_test.html
deleted file mode 100644
index 1af91fd..0000000
--- a/polygerrit-ui/app/elements/plugins/gr-repo-api/gr-repo-api_test.html
+++ /dev/null
@@ -1,87 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<title>gr-repo-api</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-endpoint-decorator name="repo-command">
- </gr-endpoint-decorator>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import '../gr-endpoint-decorator/gr-endpoint-decorator.js';
-import {pluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
-import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit.js';
-
-const pluginApi = _testOnly_initGerritPluginApi();
-
-suite('gr-repo-api tests', () => {
- let sandbox;
- let repoApi;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- let plugin;
- pluginApi.install(p => { plugin = p; }, '0.1',
- 'http://test.com/plugins/testplugin/static/test.js');
- pluginLoader.loadPlugins([]);
- repoApi = plugin.project();
- });
-
- teardown(() => {
- repoApi = null;
- sandbox.restore();
- });
-
- test('exists', () => {
- assert.isOk(repoApi);
- });
-
- test('works', done => {
- const attachedStub = sandbox.stub();
- const tapStub = sandbox.stub();
- repoApi
- .createCommand('foo', attachedStub)
- .onTap(tapStub);
- const element = fixture('basic');
- flush(() => {
- assert.isTrue(attachedStub.called);
- const pluginCommand = element.shadowRoot
- .querySelector('gr-plugin-repo-command');
- assert.isOk(pluginCommand);
- const btn = pluginCommand.shadowRoot
- .querySelector('gr-button');
- assert.isOk(btn);
- assert.equal(btn.textContent, 'foo');
- assert.isFalse(tapStub.called);
- MockInteractions.tap(btn);
- assert.isTrue(tapStub.called);
- done();
- });
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/plugins/gr-repo-api/gr-repo-api_test.js b/polygerrit-ui/app/elements/plugins/gr-repo-api/gr-repo-api_test.js
new file mode 100644
index 0000000..c7f1b06
--- /dev/null
+++ b/polygerrit-ui/app/elements/plugins/gr-repo-api/gr-repo-api_test.js
@@ -0,0 +1,73 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import '../gr-endpoint-decorator/gr-endpoint-decorator.js';
+import {pluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
+import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const basicFixture = fixtureFromTemplate(html`
+<gr-endpoint-decorator name="repo-command">
+ </gr-endpoint-decorator>
+`);
+
+const pluginApi = _testOnly_initGerritPluginApi();
+
+suite('gr-repo-api tests', () => {
+ let repoApi;
+
+ setup(() => {
+ let plugin;
+ pluginApi.install(p => { plugin = p; }, '0.1',
+ 'http://test.com/plugins/testplugin/static/test.js');
+ pluginLoader.loadPlugins([]);
+ repoApi = plugin.project();
+ });
+
+ teardown(() => {
+ repoApi = null;
+ });
+
+ test('exists', () => {
+ assert.isOk(repoApi);
+ });
+
+ test('works', done => {
+ const attachedStub = sinon.stub();
+ const tapStub = sinon.stub();
+ repoApi
+ .createCommand('foo', attachedStub)
+ .onTap(tapStub);
+ const element = basicFixture.instantiate();
+ flush(() => {
+ assert.isTrue(attachedStub.called);
+ const pluginCommand = element.shadowRoot
+ .querySelector('gr-plugin-repo-command');
+ assert.isOk(pluginCommand);
+ const btn = pluginCommand.shadowRoot
+ .querySelector('gr-button');
+ assert.isOk(btn);
+ assert.equal(btn.textContent, 'foo');
+ assert.isFalse(tapStub.called);
+ MockInteractions.tap(btn);
+ assert.isTrue(tapStub.called);
+ done();
+ });
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/plugins/gr-settings-api/gr-settings-api_test.html b/polygerrit-ui/app/elements/plugins/gr-settings-api/gr-settings-api_test.html
deleted file mode 100644
index 5057992..0000000
--- a/polygerrit-ui/app/elements/plugins/gr-settings-api/gr-settings-api_test.html
+++ /dev/null
@@ -1,89 +0,0 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Settings
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<title>gr-settings-api</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-endpoint-decorator name="settings-menu-item">
- </gr-endpoint-decorator>
- <gr-endpoint-decorator name="settings-screen">
- </gr-endpoint-decorator>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import '../gr-endpoint-decorator/gr-endpoint-decorator.js';
-import {pluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
-import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit.js';
-
-const pluginApi = _testOnly_initGerritPluginApi();
-
-suite('gr-settings-api tests', () => {
- let sandbox;
- let settingsApi;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- let plugin;
- pluginApi.install(p => { plugin = p; }, '0.1',
- 'http://test.com/plugins/testplugin/static/test.js');
- pluginLoader.loadPlugins([]);
- settingsApi = plugin.settings();
- });
-
- teardown(() => {
- settingsApi = null;
- sandbox.restore();
- });
-
- test('exists', () => {
- assert.isOk(settingsApi);
- });
-
- test('works', done => {
- settingsApi
- .title('foo')
- .token('bar')
- .module('some-settings-screen')
- .build();
- const element = fixture('basic');
- flush(() => {
- const [menuItemEl, itemEl] = element;
- const menuItem = menuItemEl.shadowRoot
- .querySelector('gr-settings-menu-item');
- assert.isOk(menuItem);
- assert.equal(menuItem.title, 'foo');
- assert.equal(menuItem.href, '#x/testplugin/bar');
- const item = itemEl.shadowRoot
- .querySelector('gr-settings-item');
- assert.isOk(item);
- assert.equal(item.title, 'foo');
- assert.equal(item.anchor, 'x/testplugin/bar');
- done();
- });
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/plugins/gr-settings-api/gr-settings-api_test.js b/polygerrit-ui/app/elements/plugins/gr-settings-api/gr-settings-api_test.js
new file mode 100644
index 0000000..82d58fe
--- /dev/null
+++ b/polygerrit-ui/app/elements/plugins/gr-settings-api/gr-settings-api_test.js
@@ -0,0 +1,75 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import '../gr-endpoint-decorator/gr-endpoint-decorator.js';
+import {pluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
+import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const basicFixture = fixtureFromTemplate(html`
+<gr-endpoint-decorator name="settings-menu-item">
+ </gr-endpoint-decorator>
+ <gr-endpoint-decorator name="settings-screen">
+ </gr-endpoint-decorator>
+`);
+
+const pluginApi = _testOnly_initGerritPluginApi();
+
+suite('gr-settings-api tests', () => {
+ let settingsApi;
+
+ setup(() => {
+ let plugin;
+ pluginApi.install(p => { plugin = p; }, '0.1',
+ 'http://test.com/plugins/testplugin/static/test.js');
+ pluginLoader.loadPlugins([]);
+ settingsApi = plugin.settings();
+ });
+
+ teardown(() => {
+ settingsApi = null;
+ });
+
+ test('exists', () => {
+ assert.isOk(settingsApi);
+ });
+
+ test('works', done => {
+ settingsApi
+ .title('foo')
+ .token('bar')
+ .module('some-settings-screen')
+ .build();
+ const element = basicFixture.instantiate();
+ flush(() => {
+ const [menuItemEl, itemEl] = element;
+ const menuItem = menuItemEl.shadowRoot
+ .querySelector('gr-settings-menu-item');
+ assert.isOk(menuItem);
+ assert.equal(menuItem.title, 'foo');
+ assert.equal(menuItem.href, '#x/testplugin/bar');
+ const item = itemEl.shadowRoot
+ .querySelector('gr-settings-item');
+ assert.isOk(item);
+ assert.equal(item.title, 'foo');
+ assert.equal(item.anchor, 'x/testplugin/bar');
+ done();
+ });
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/plugins/gr-styles-api/gr-styles-api_test.html b/polygerrit-ui/app/elements/plugins/gr-styles-api/gr-styles-api_test.js
similarity index 73%
rename from polygerrit-ui/app/elements/plugins/gr-styles-api/gr-styles-api_test.html
rename to polygerrit-ui/app/elements/plugins/gr-styles-api/gr-styles-api_test.js
index d6bae9b..5ccda28 100644
--- a/polygerrit-ui/app/elements/plugins/gr-styles-api/gr-styles-api_test.html
+++ b/polygerrit-ui/app/elements/plugins/gr-styles-api/gr-styles-api_test.js
@@ -1,56 +1,44 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2019 The Android Open Source Project
+/**
+ * @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.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<title>gr-admin-api</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<dom-module id="gr-style-test-element">
- <template>
- <div id="wrapper"></div>
- </template>
- <script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import '../../shared/gr-js-api-interface/gr-js-api-interface.js';
-import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
-Polymer({is: 'gr-style-test-element'});
-</script>
-</dom-module>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import '../../shared/gr-js-api-interface/gr-js-api-interface.js';
+import {PolymerElement} from '@polymer/polymer/polymer-element.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {pluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+class GrStyleTestElement extends PolymerElement {
+ static get is() { return 'gr-style-test-element'; }
+
+ static get template() {
+ return html`<div id="wrapper"></div>`;
+ }
+}
+
+customElements.define(GrStyleTestElement.is, GrStyleTestElement);
const pluginApi = _testOnly_initGerritPluginApi();
suite('gr-styles-api tests', () => {
- let sandbox;
let stylesApi;
setup(() => {
- sandbox = sinon.sandbox.create();
let plugin;
pluginApi.install(p => { plugin = p; }, '0.1',
'http://test.com/plugins/testplugin/static/test.js');
@@ -60,7 +48,6 @@
teardown(() => {
stylesApi = null;
- sandbox.restore();
});
test('exists', () => {
@@ -73,13 +60,12 @@
});
suite('GrStyleObject tests', () => {
- let sandbox;
let stylesApi;
let displayInlineStyle;
let displayNoneStyle;
+ let elementsToRemove;
setup(() => {
- sandbox = sinon.sandbox.create();
let plugin;
pluginApi.install(p => { plugin = p; }, '0.1',
'http://test.com/plugins/testplugin/static/test.js');
@@ -87,13 +73,18 @@
stylesApi = plugin.styles();
displayInlineStyle = stylesApi.css('display: inline');
displayNoneStyle = stylesApi.css('display: none');
+ elementsToRemove = [];
});
teardown(() => {
displayInlineStyle = null;
displayNoneStyle = null;
stylesApi = null;
- sandbox.restore();
+ elementsToRemove.forEach(element => {
+ element.remove();
+ });
+ elementsToRemove = null;
+ sinon.restore();
});
function createNestedElements(parentElement) {
@@ -109,6 +100,11 @@
dom(parentElement).appendChild(element2);
dom(element2).appendChild(element3);
+ if (parentElement === document.body) {
+ elementsToRemove.push(element1);
+ elementsToRemove.push(element2);
+ }
+
return [element1, element2, element3];
}
@@ -121,6 +117,7 @@
test('getClassName - elements inside polymer element', () => {
const polymerElement = document.createElement('gr-style-test-element');
dom(document.body).appendChild(polymerElement);
+ elementsToRemove.push(polymerElement);
const contentElements = createNestedElements(polymerElement.$.wrapper);
testGetClassName(contentElements);
@@ -154,6 +151,7 @@
test('apply - elements inside polymer element', () => {
const polymerElement = document.createElement('gr-style-test-element');
dom(document.body).appendChild(polymerElement);
+ elementsToRemove.push(polymerElement);
const contentElements = createNestedElements(polymerElement.$.wrapper);
testApply(contentElements);
@@ -185,4 +183,4 @@
}
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/plugins/gr-theme-api/gr-theme-api_test.html b/polygerrit-ui/app/elements/plugins/gr-theme-api/gr-theme-api_test.html
deleted file mode 100644
index 9e2e190..0000000
--- a/polygerrit-ui/app/elements/plugins/gr-theme-api/gr-theme-api_test.html
+++ /dev/null
@@ -1,87 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<title>gr-theme-api</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="header-title">
- <template>
- <gr-endpoint-decorator name="header-title">
- <span class="titleText"></span>
- </gr-endpoint-decorator>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import '../gr-endpoint-decorator/gr-endpoint-decorator.js';
-import {pluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
-import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit.js';
-
-const pluginApi = _testOnly_initGerritPluginApi();
-
-suite('gr-theme-api tests', () => {
- let sandbox;
- let theme;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- let plugin;
- pluginApi.install(p => { plugin = p; }, '0.1',
- 'http://test.com/plugins/testplugin/static/test.js');
- theme = plugin.theme();
- });
-
- teardown(() => {
- theme = null;
- sandbox.restore();
- });
-
- test('exists', () => {
- assert.isOk(theme);
- });
-
- suite('header-title', () => {
- let customHeader;
-
- setup(() => {
- fixture('header-title');
- stub('gr-custom-plugin-header', {
- /** @override */
- ready() { customHeader = this; },
- });
- pluginLoader.loadPlugins([]);
- });
-
- test('sets logo and title', done => {
- theme.setHeaderLogoAndTitle('foo.jpg', 'bar');
- flush(() => {
- assert.isNotNull(customHeader);
- assert.equal(customHeader.logoUrl, 'foo.jpg');
- assert.equal(customHeader.title, 'bar');
- done();
- });
- });
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/plugins/gr-theme-api/gr-theme-api_test.js b/polygerrit-ui/app/elements/plugins/gr-theme-api/gr-theme-api_test.js
new file mode 100644
index 0000000..8a70303
--- /dev/null
+++ b/polygerrit-ui/app/elements/plugins/gr-theme-api/gr-theme-api_test.js
@@ -0,0 +1,73 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import '../gr-endpoint-decorator/gr-endpoint-decorator.js';
+import {pluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
+import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const headerTitleFixture = fixtureFromTemplate(html`
+<gr-endpoint-decorator name="header-title">
+ <span class="titleText"></span>
+ </gr-endpoint-decorator>
+`);
+
+const pluginApi = _testOnly_initGerritPluginApi();
+
+suite('gr-theme-api tests', () => {
+ let theme;
+
+ setup(() => {
+ let plugin;
+ pluginApi.install(p => { plugin = p; }, '0.1',
+ 'http://test.com/plugins/testplugin/static/test.js');
+ theme = plugin.theme();
+ });
+
+ teardown(() => {
+ theme = null;
+ });
+
+ test('exists', () => {
+ assert.isOk(theme);
+ });
+
+ suite('header-title', () => {
+ let customHeader;
+
+ setup(() => {
+ headerTitleFixture.instantiate();
+ stub('gr-custom-plugin-header', {
+ /** @override */
+ ready() { customHeader = this; },
+ });
+ pluginLoader.loadPlugins([]);
+ });
+
+ test('sets logo and title', done => {
+ theme.setHeaderLogoAndTitle('foo.jpg', 'bar');
+ flush(() => {
+ assert.isNotNull(customHeader);
+ assert.equal(customHeader.logoUrl, 'foo.jpg');
+ assert.equal(customHeader.title, 'bar');
+ done();
+ });
+ });
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.js b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.js
index 14b6cfe..32921d9 100644
--- a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.js
+++ b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.js
@@ -180,7 +180,7 @@
if ([
config,
username,
- ].some(arg => arg === undefined)) {
+ ].includes(undefined)) {
return undefined;
}
diff --git a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info_test.html b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info_test.js
similarity index 79%
rename from polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info_test.html
rename to polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info_test.js
index 53641d9..4a62bab 100644
--- a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info_test.js
@@ -1,45 +1,30 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-account-info</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-account-info></gr-account-info>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-account-info.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+
+const basicFixture = fixtureFromElement('gr-account-info');
+
suite('gr-account-info tests', () => {
let element;
let account;
let config;
- let sandbox;
function valueOf(title) {
const sections = dom(element.root).querySelectorAll('section');
@@ -53,7 +38,6 @@
}
setup(done => {
- sandbox = sinon.sandbox.create();
account = {
_account_id: 123,
name: 'user name',
@@ -70,15 +54,11 @@
return Promise.resolve({time_format: 'HHMM_12'});
},
});
- element = fixture('basic');
+ element = basicFixture.instantiate();
// Allow the element to render.
element.loadData().then(() => { flush(done); });
});
- teardown(() => {
- sandbox.restore();
- });
-
test('basic account info render', () => {
assert.isFalse(element._loading);
@@ -148,17 +128,17 @@
let statusStub;
setup(() => {
- nameChangedSpy = sandbox.spy(element, '_nameChanged');
- usernameChangedSpy = sandbox.spy(element, '_usernameChanged');
- statusChangedSpy = sandbox.spy(element, '_statusChanged');
+ nameChangedSpy = sinon.spy(element, '_nameChanged');
+ usernameChangedSpy = sinon.spy(element, '_usernameChanged');
+ statusChangedSpy = sinon.spy(element, '_statusChanged');
element.set('_serverConfig',
{auth: {editable_account_fields: ['FULL_NAME', 'USER_NAME']}});
- nameStub = sandbox.stub(element.$.restAPI, 'setAccountName',
+ nameStub = sinon.stub(element.$.restAPI, 'setAccountName').callsFake(
name => Promise.resolve());
- usernameStub = sandbox.stub(element.$.restAPI, 'setAccountUsername',
- username => Promise.resolve());
- statusStub = sandbox.stub(element.$.restAPI, 'setAccountStatus',
+ usernameStub = sinon.stub(element.$.restAPI, 'setAccountUsername')
+ .callsFake(username => Promise.resolve());
+ statusStub = sinon.stub(element.$.restAPI, 'setAccountStatus').callsFake(
status => Promise.resolve());
});
@@ -233,16 +213,16 @@
let statusStub;
setup(() => {
- nameChangedSpy = sandbox.spy(element, '_nameChanged');
- statusChangedSpy = sandbox.spy(element, '_statusChanged');
+ nameChangedSpy = sinon.spy(element, '_nameChanged');
+ statusChangedSpy = sinon.spy(element, '_statusChanged');
element.set('_serverConfig',
{auth: {editable_account_fields: ['FULL_NAME']}});
- nameStub = sandbox.stub(element.$.restAPI, 'setAccountName',
+ nameStub = sinon.stub(element.$.restAPI, 'setAccountName').callsFake(
name => Promise.resolve());
- statusStub = sandbox.stub(element.$.restAPI, 'setAccountStatus',
+ statusStub = sinon.stub(element.$.restAPI, 'setAccountStatus').callsFake(
status => Promise.resolve());
- sandbox.stub(element.$.restAPI, 'setAccountUsername',
+ sinon.stub(element.$.restAPI, 'setAccountUsername').callsFake(
username => Promise.resolve());
});
@@ -278,11 +258,11 @@
let statusStub;
setup(() => {
- statusChangedSpy = sandbox.spy(element, '_statusChanged');
+ statusChangedSpy = sinon.spy(element, '_statusChanged');
element.set('_serverConfig',
{auth: {editable_account_fields: []}});
- statusStub = sandbox.stub(element.$.restAPI, 'setAccountStatus',
+ statusStub = sinon.stub(element.$.restAPI, 'setAccountStatus').callsFake(
status => Promise.resolve());
});
@@ -339,4 +319,4 @@
assert.equal(element._hideAvatarChangeUrl('https://example.com'), '');
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/settings/gr-agreements-list/gr-agreements-list_test.html b/polygerrit-ui/app/elements/settings/gr-agreements-list/gr-agreements-list_test.html
deleted file mode 100644
index 3a2b86d..0000000
--- a/polygerrit-ui/app/elements/settings/gr-agreements-list/gr-agreements-list_test.html
+++ /dev/null
@@ -1,70 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-settings-view</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-agreements-list></gr-agreements-list>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-agreements-list.js';
-import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
-suite('gr-agreements-list tests', () => {
- let element;
- let agreements;
-
- setup(done => {
- agreements = [{
- url: 'some url',
- description: 'Agreements 1 description',
- name: 'Agreements 1',
- }];
-
- stub('gr-rest-api-interface', {
- getAccountAgreements() { return Promise.resolve(agreements); },
- });
-
- element = fixture('basic');
-
- element.loadData().then(() => { flush(done); });
- });
-
- test('renders', () => {
- const rows = dom(element.root).querySelectorAll('tbody tr');
-
- assert.equal(rows.length, 1);
-
- const nameCells = Array.from(rows).map(row =>
- row.querySelectorAll('td')[0].textContent.trim()
- );
-
- assert.equal(nameCells[0], 'Agreements 1');
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/settings/gr-agreements-list/gr-agreements-list_test.js b/polygerrit-ui/app/elements/settings/gr-agreements-list/gr-agreements-list_test.js
new file mode 100644
index 0000000..ed0bdb3
--- /dev/null
+++ b/polygerrit-ui/app/elements/settings/gr-agreements-list/gr-agreements-list_test.js
@@ -0,0 +1,56 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-agreements-list.js';
+import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+
+const basicFixture = fixtureFromElement('gr-agreements-list');
+
+suite('gr-agreements-list tests', () => {
+ let element;
+ let agreements;
+
+ setup(done => {
+ agreements = [{
+ url: 'some url',
+ description: 'Agreements 1 description',
+ name: 'Agreements 1',
+ }];
+
+ stub('gr-rest-api-interface', {
+ getAccountAgreements() { return Promise.resolve(agreements); },
+ });
+
+ element = basicFixture.instantiate();
+
+ element.loadData().then(() => { flush(done); });
+ });
+
+ test('renders', () => {
+ const rows = dom(element.root).querySelectorAll('tbody tr');
+
+ assert.equal(rows.length, 1);
+
+ const nameCells = Array.from(rows).map(row =>
+ row.querySelectorAll('td')[0].textContent.trim()
+ );
+
+ assert.equal(nameCells[0], 'Agreements 1');
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_test.html b/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_test.js
similarity index 70%
rename from polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_test.html
rename to polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_test.js
index 27532b4..3fca9d2 100644
--- a/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_test.js
@@ -1,47 +1,31 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-settings-view</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-change-table-editor></gr-change-table-editor>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-change-table-editor.js';
+
+const basicFixture = fixtureFromElement('gr-change-table-editor');
+
suite('gr-change-table-editor tests', () => {
let element;
let columns;
- let sandbox;
setup(() => {
- element = fixture('basic');
- sandbox = sinon.sandbox.create();
+ element = basicFixture.instantiate();
columns = [
'Subject',
@@ -60,10 +44,6 @@
flushAsynchronousOperations();
});
- teardown(() => {
- sandbox.restore();
- });
-
test('renders', () => {
const rows = element.shadowRoot
.querySelector('tbody').querySelectorAll('tr');
@@ -126,8 +106,8 @@
});
test('_handleCheckboxContainerClick relays taps to checkboxes', () => {
- sandbox.stub(element, '_handleNumberCheckboxClick');
- sandbox.stub(element, '_handleTargetClick');
+ sinon.stub(element, '_handleNumberCheckboxClick');
+ sinon.stub(element, '_handleTargetClick');
MockInteractions.tap(
element.shadowRoot
@@ -143,7 +123,7 @@
});
test('_handleNumberCheckboxClick', () => {
- sandbox.spy(element, '_handleNumberCheckboxClick');
+ sinon.spy(element, '_handleNumberCheckboxClick');
MockInteractions
.tap(element.shadowRoot
@@ -159,7 +139,7 @@
});
test('_handleTargetClick', () => {
- sandbox.spy(element, '_handleTargetClick');
+ sinon.spy(element, '_handleTargetClick');
assert.include(element.displayedColumns, 'Assignee');
MockInteractions
.tap(element.shadowRoot
@@ -168,4 +148,4 @@
assert.notInclude(element.displayedColumns, 'Assignee');
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/settings/gr-cla-view/gr-cla-view_test.html b/polygerrit-ui/app/elements/settings/gr-cla-view/gr-cla-view_test.js
similarity index 80%
rename from polygerrit-ui/app/elements/settings/gr-cla-view/gr-cla-view_test.html
rename to polygerrit-ui/app/elements/settings/gr-cla-view/gr-cla-view_test.js
index bc3c10c..6f89c49 100644
--- a/polygerrit-ui/app/elements/settings/gr-cla-view/gr-cla-view_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-cla-view/gr-cla-view_test.js
@@ -1,40 +1,26 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2018 The Android Open Source Project
+/**
+ * @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.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-cla-view</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-cla-view></gr-cla-view>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-cla-view.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+
+const basicFixture = fixtureFromElement('gr-cla-view');
+
suite('gr-cla-view tests', () => {
let element;
const signedAgreements = [{
@@ -124,7 +110,7 @@
getAccountGroups() { return Promise.resolve(groups); },
getAccountAgreements() { return Promise.resolve(signedAgreements); },
});
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.loadData().then(() => { flush(done); });
});
@@ -191,4 +177,4 @@
'test_cla.html'), '/test_cla.html');
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/settings/gr-edit-preferences/gr-edit-preferences_test.html b/polygerrit-ui/app/elements/settings/gr-edit-preferences/gr-edit-preferences_test.js
similarity index 66%
rename from polygerrit-ui/app/elements/settings/gr-edit-preferences/gr-edit-preferences_test.html
rename to polygerrit-ui/app/elements/settings/gr-edit-preferences/gr-edit-preferences_test.js
index 3cc7bfe..b1b8b61 100644
--- a/polygerrit-ui/app/elements/settings/gr-edit-preferences/gr-edit-preferences_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-edit-preferences/gr-edit-preferences_test.js
@@ -1,42 +1,28 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2018 The Android Open Source Project
+/**
+ * @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.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-edit-preferences</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-edit-preferences></gr-edit-preferences>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-edit-preferences.js';
+
+const basicFixture = fixtureFromElement('gr-edit-preferences');
+
suite('gr-edit-preferences tests', () => {
let element;
- let sandbox;
+
let editPreferences;
function valueOf(title, fieldsetid) {
@@ -76,13 +62,11 @@
},
});
- element = fixture('basic');
- sandbox = sinon.sandbox.create();
+ element = basicFixture.instantiate();
+
return element.loadData();
});
- teardown(() => { sandbox.restore(); });
-
test('renders', () => {
// Rendered with the expected preferences selected.
assert.equal(valueOf('Tab width', 'editPreferences')
@@ -108,7 +92,7 @@
});
test('save changes', () => {
- sandbox.stub(element.$.restAPI, 'saveEditPreferences')
+ sinon.stub(element.$.restAPI, 'saveEditPreferences')
.returns(Promise.resolve());
const showTabsCheckbox = valueOf('Show tabs', 'editPreferences')
.firstElementChild;
@@ -123,4 +107,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/settings/gr-email-editor/gr-email-editor_test.html b/polygerrit-ui/app/elements/settings/gr-email-editor/gr-email-editor_test.js
similarity index 75%
rename from polygerrit-ui/app/elements/settings/gr-email-editor/gr-email-editor_test.html
rename to polygerrit-ui/app/elements/settings/gr-email-editor/gr-email-editor_test.js
index ad2553d..805b8c8 100644
--- a/polygerrit-ui/app/elements/settings/gr-email-editor/gr-email-editor_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-email-editor/gr-email-editor_test.js
@@ -1,39 +1,25 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-email-editor</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-email-editor></gr-email-editor>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-email-editor.js';
+
+const basicFixture = fixtureFromElement('gr-email-editor');
+
suite('gr-email-editor tests', () => {
let element;
@@ -48,7 +34,7 @@
getAccountEmails() { return Promise.resolve(emails); },
});
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.loadData().then(flush(done));
});
@@ -149,4 +135,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor_test.html b/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor_test.js
similarity index 77%
rename from polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor_test.html
rename to polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor_test.js
index 4a0af5b..5281e17 100644
--- a/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor_test.js
@@ -1,40 +1,26 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-gpg-editor</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-gpg-editor></gr-gpg-editor>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-gpg-editor.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+
+const basicFixture = fixtureFromElement('gr-gpg-editor');
+
suite('gr-gpg-editor tests', () => {
let element;
let keys;
@@ -69,7 +55,7 @@
getAccountGPGKeys() { return Promise.resolve(keys); },
});
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.loadData().then(() => { flush(done); });
});
@@ -89,8 +75,8 @@
test('remove key', done => {
const lastKey = keys[Object.keys(keys)[1]];
- const saveStub = sinon.stub(element.$.restAPI, 'deleteAccountGPGKey',
- () => Promise.resolve());
+ const saveStub = sinon.stub(element.$.restAPI, 'deleteAccountGPGKey')
+ .callsFake(() => Promise.resolve());
assert.equal(element._keysToRemove.length, 0);
assert.isFalse(element.hasUnsavedChanges);
@@ -145,7 +131,7 @@
},
};
- const addStub = sinon.stub(element.$.restAPI, 'addAccountGPGKey',
+ const addStub = sinon.stub(element.$.restAPI, 'addAccountGPGKey').callsFake(
() => Promise.resolve(newKeyObject));
element._newKey = newKeyString;
@@ -170,7 +156,7 @@
test('add invalid key', done => {
const newKeyString = 'not even close to valid';
- const addStub = sinon.stub(element.$.restAPI, 'addAccountGPGKey',
+ const addStub = sinon.stub(element.$.restAPI, 'addAccountGPGKey').callsFake(
() => Promise.reject(new Error('error')));
element._newKey = newKeyString;
@@ -192,4 +178,4 @@
assert.deepEqual(addStub.lastCall.args[0], {add: [newKeyString]});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list_test.html b/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list_test.html
deleted file mode 100644
index 2fdc7b3..0000000
--- a/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list_test.html
+++ /dev/null
@@ -1,124 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-settings-view</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-group-list></gr-group-list>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-group-list.js';
-import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
-import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
-
-suite('gr-group-list tests', () => {
- let sandbox;
- let element;
- let groups;
-
- setup(done => {
- sandbox = sinon.sandbox.create();
- groups = [{
- url: 'some url',
- options: {},
- description: 'Group 1 description',
- group_id: 1,
- owner: 'Administrators',
- owner_id: '123',
- id: 'abc',
- name: 'Group 1',
- }, {
- options: {visible_to_all: true},
- id: '456',
- name: 'Group 2',
- }, {
- options: {},
- id: '789',
- name: 'Group 3',
- }];
-
- stub('gr-rest-api-interface', {
- getAccountGroups() { return Promise.resolve(groups); },
- });
-
- element = fixture('basic');
-
- element.loadData().then(() => { flush(done); });
- });
-
- teardown(() => { sandbox.restore(); });
-
- test('renders', () => {
- const rows = Array.from(
- dom(element.root).querySelectorAll('tbody tr'));
-
- assert.equal(rows.length, 3);
-
- const nameCells = rows.map(row =>
- row.querySelectorAll('td a')[0].textContent.trim()
- );
-
- assert.equal(nameCells[0], 'Group 1');
- assert.equal(nameCells[1], 'Group 2');
- assert.equal(nameCells[2], 'Group 3');
- });
-
- test('_computeVisibleToAll', () => {
- assert.equal(element._computeVisibleToAll(groups[0]), 'No');
- assert.equal(element._computeVisibleToAll(groups[1]), 'Yes');
- });
-
- test('_computeGroupPath', () => {
- let urlStub = sandbox.stub(GerritNav, 'getUrlForGroup',
- () => '/admin/groups/e2cd66f88a2db4d391ac068a92d987effbe872f5');
-
- let group = {
- id: 'e2cd66f88a2db4d391ac068a92d987effbe872f5',
- };
- assert.equal(element._computeGroupPath(group),
- '/admin/groups/e2cd66f88a2db4d391ac068a92d987effbe872f5');
-
- group = {
- name: 'admin',
- };
- assert.isUndefined(element._computeGroupPath(group));
-
- urlStub.restore();
-
- urlStub = sandbox.stub(GerritNav, 'getUrlForGroup',
- () => '/admin/groups/user/test');
-
- group = {
- id: 'user%2Ftest',
- };
- assert.equal(element._computeGroupPath(group),
- '/admin/groups/user/test');
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list_test.js b/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list_test.js
new file mode 100644
index 0000000..bfd42ac
--- /dev/null
+++ b/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list_test.js
@@ -0,0 +1,105 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-group-list.js';
+import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
+
+const basicFixture = fixtureFromElement('gr-group-list');
+
+suite('gr-group-list tests', () => {
+ let element;
+ let groups;
+
+ setup(done => {
+ groups = [{
+ url: 'some url',
+ options: {},
+ description: 'Group 1 description',
+ group_id: 1,
+ owner: 'Administrators',
+ owner_id: '123',
+ id: 'abc',
+ name: 'Group 1',
+ }, {
+ options: {visible_to_all: true},
+ id: '456',
+ name: 'Group 2',
+ }, {
+ options: {},
+ id: '789',
+ name: 'Group 3',
+ }];
+
+ stub('gr-rest-api-interface', {
+ getAccountGroups() { return Promise.resolve(groups); },
+ });
+
+ element = basicFixture.instantiate();
+
+ element.loadData().then(() => { flush(done); });
+ });
+
+ test('renders', () => {
+ const rows = Array.from(
+ dom(element.root).querySelectorAll('tbody tr'));
+
+ assert.equal(rows.length, 3);
+
+ const nameCells = rows.map(row =>
+ row.querySelectorAll('td a')[0].textContent.trim()
+ );
+
+ assert.equal(nameCells[0], 'Group 1');
+ assert.equal(nameCells[1], 'Group 2');
+ assert.equal(nameCells[2], 'Group 3');
+ });
+
+ test('_computeVisibleToAll', () => {
+ assert.equal(element._computeVisibleToAll(groups[0]), 'No');
+ assert.equal(element._computeVisibleToAll(groups[1]), 'Yes');
+ });
+
+ test('_computeGroupPath', () => {
+ let urlStub = sinon.stub(GerritNav, 'getUrlForGroup').callsFake(
+ () => '/admin/groups/e2cd66f88a2db4d391ac068a92d987effbe872f5');
+
+ let group = {
+ id: 'e2cd66f88a2db4d391ac068a92d987effbe872f5',
+ };
+ assert.equal(element._computeGroupPath(group),
+ '/admin/groups/e2cd66f88a2db4d391ac068a92d987effbe872f5');
+
+ group = {
+ name: 'admin',
+ };
+ assert.isUndefined(element._computeGroupPath(group));
+
+ urlStub.restore();
+
+ urlStub = sinon.stub(GerritNav, 'getUrlForGroup').callsFake(
+ () => '/admin/groups/user/test');
+
+ group = {
+ id: 'user%2Ftest',
+ };
+ assert.equal(element._computeGroupPath(group),
+ '/admin/groups/user/test');
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password_test.html b/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password_test.html
deleted file mode 100644
index 26fa84d..0000000
--- a/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password_test.html
+++ /dev/null
@@ -1,91 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-settings-view</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-http-password></gr-http-password>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-http-password.js';
-suite('gr-http-password tests', () => {
- let element;
- let account;
- let config;
-
- setup(done => {
- account = {username: 'user name'};
- config = {auth: {}};
-
- stub('gr-rest-api-interface', {
- getAccount() { return Promise.resolve(account); },
- getConfig() { return Promise.resolve(config); },
- });
-
- element = fixture('basic');
- element.loadData().then(() => { flush(done); });
- });
-
- test('generate password', () => {
- const button = element.$.generateButton;
- const nextPassword = 'the new password';
- let generateResolve;
- const generateStub = sinon.stub(element.$.restAPI,
- 'generateAccountHttpPassword', () => new Promise(resolve => {
- generateResolve = resolve;
- }));
-
- assert.isNotOk(element._generatedPassword);
-
- MockInteractions.tap(button);
-
- assert.isTrue(generateStub.called);
- assert.equal(element._generatedPassword, 'Generating...');
-
- generateResolve(nextPassword);
-
- generateStub.lastCall.returnValue.then(() => {
- assert.equal(element._generatedPassword, nextPassword);
- });
- });
-
- test('without http_password_url', () => {
- assert.isNull(element._passwordUrl);
- });
-
- test('with http_password_url', done => {
- config.auth.http_password_url = 'http://example.com/';
- element.loadData().then(() => {
- assert.isNotNull(element._passwordUrl);
- assert.equal(element._passwordUrl, config.auth.http_password_url);
- done();
- });
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password_test.js b/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password_test.js
new file mode 100644
index 0000000..920ad48
--- /dev/null
+++ b/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password_test.js
@@ -0,0 +1,78 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-http-password.js';
+
+const basicFixture = fixtureFromElement('gr-http-password');
+
+suite('gr-http-password tests', () => {
+ let element;
+ let account;
+ let config;
+
+ setup(done => {
+ account = {username: 'user name'};
+ config = {auth: {}};
+
+ stub('gr-rest-api-interface', {
+ getAccount() { return Promise.resolve(account); },
+ getConfig() { return Promise.resolve(config); },
+ });
+
+ element = basicFixture.instantiate();
+ element.loadData().then(() => { flush(done); });
+ });
+
+ test('generate password', () => {
+ const button = element.$.generateButton;
+ const nextPassword = 'the new password';
+ let generateResolve;
+ const generateStub = sinon.stub(element.$.restAPI,
+ 'generateAccountHttpPassword')
+ .callsFake(() => new Promise(resolve => {
+ generateResolve = resolve;
+ }));
+
+ assert.isNotOk(element._generatedPassword);
+
+ MockInteractions.tap(button);
+
+ assert.isTrue(generateStub.called);
+ assert.equal(element._generatedPassword, 'Generating...');
+
+ generateResolve(nextPassword);
+
+ generateStub.lastCall.returnValue.then(() => {
+ assert.equal(element._generatedPassword, nextPassword);
+ });
+ });
+
+ test('without http_password_url', () => {
+ assert.isNull(element._passwordUrl);
+ });
+
+ test('with http_password_url', done => {
+ config.auth.http_password_url = 'http://example.com/';
+ element.loadData().then(() => {
+ assert.isNotNull(element._passwordUrl);
+ assert.equal(element._passwordUrl, config.auth.http_password_url);
+ done();
+ });
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/settings/gr-identities/gr-identities_test.html b/polygerrit-ui/app/elements/settings/gr-identities/gr-identities_test.js
similarity index 70%
rename from polygerrit-ui/app/elements/settings/gr-identities/gr-identities_test.html
rename to polygerrit-ui/app/elements/settings/gr-identities/gr-identities_test.js
index 0965826..e01c58b 100644
--- a/polygerrit-ui/app/elements/settings/gr-identities/gr-identities_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-identities/gr-identities_test.js
@@ -1,43 +1,29 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-identities</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-identities></gr-identities>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-identities.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+
+const basicFixture = fixtureFromElement('gr-identities');
+
suite('gr-identities tests', () => {
let element;
- let sandbox;
+
const ids = [
{
identity: 'username:john',
@@ -55,21 +41,15 @@
];
setup(done => {
- sandbox = sinon.sandbox.create();
-
stub('gr-rest-api-interface', {
getExternalIds() { return Promise.resolve(ids); },
});
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.loadData().then(() => { flush(done); });
});
- teardown(() => {
- sandbox.restore();
- });
-
test('renders', () => {
const rows = Array.from(
dom(element.root).querySelectorAll('tbody tr'));
@@ -112,7 +92,7 @@
test('delete id', done => {
element._idName = 'mailto:gerrit2@example.com';
- const loadDataStub = sandbox.stub(element, 'loadData');
+ const loadDataStub = sinon.stub(element, 'loadData');
element._handleDeleteItemConfirm().then(() => {
assert.isTrue(loadDataStub.called);
done();
@@ -122,7 +102,7 @@
test('_handleDeleteItem opens modal', () => {
const deleteBtn =
dom(element.root).querySelector('.deleteButton');
- const deleteItem = sandbox.stub(element, '_handleDeleteItem');
+ const deleteItem = sinon.stub(element, '_handleDeleteItem');
MockInteractions.tap(deleteBtn);
assert.isTrue(deleteItem.called);
});
@@ -187,4 +167,4 @@
assert.isFalse(element._showLinkAnotherIdentity);
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/settings/gr-menu-editor/gr-menu-editor_test.html b/polygerrit-ui/app/elements/settings/gr-menu-editor/gr-menu-editor_test.js
similarity index 77%
rename from polygerrit-ui/app/elements/settings/gr-menu-editor/gr-menu-editor_test.html
rename to polygerrit-ui/app/elements/settings/gr-menu-editor/gr-menu-editor_test.js
index 9c8db6d..19852d9 100644
--- a/polygerrit-ui/app/elements/settings/gr-menu-editor/gr-menu-editor_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-menu-editor/gr-menu-editor_test.js
@@ -1,40 +1,26 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-settings-view</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-menu-editor></gr-menu-editor>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-menu-editor.js';
import {flush as flush$0} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+
+const basicFixture = fixtureFromElement('gr-menu-editor');
+
suite('gr-menu-editor tests', () => {
let element;
let menu;
@@ -61,7 +47,7 @@
}
setup(done => {
- element = fixture('basic');
+ element = basicFixture.instantiate();
menu = [
{url: '/first/url', name: 'first name', target: '_blank'},
{url: '/second/url', name: 'second name', target: '_blank'},
@@ -175,4 +161,4 @@
assertMenuNamesEqual(element, ['new name']);
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog.js b/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog.js
index 1da513b..fe4a61c 100644
--- a/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog.js
+++ b/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog.js
@@ -143,7 +143,7 @@
if ([
config,
username,
- ].some(arg => arg === undefined)) {
+ ].includes(undefined)) {
return undefined;
}
diff --git a/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog_test.html b/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog_test.js
similarity index 72%
rename from polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog_test.html
rename to polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog_test.js
index a3f8548..468ef57 100644
--- a/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog_test.js
@@ -1,53 +1,31 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-registration-dialog</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-registration-dialog></gr-registration-dialog>
- </template>
-</test-fixture>
-
-<test-fixture id="blank">
- <template>
- <div></div>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
import './gr-registration-dialog.js';
+
+const basicFixture = fixtureFromElement('gr-registration-dialog');
+
suite('gr-registration-dialog tests', () => {
let element;
let account;
- let sandbox;
+
let _listeners;
setup(() => {
- sandbox = sinon.sandbox.create();
_listeners = {};
account = {
@@ -82,13 +60,12 @@
},
});
- element = fixture('basic');
+ element = basicFixture.instantiate();
return element.loadData();
});
teardown(() => {
- sandbox.restore();
for (const eventType in _listeners) {
if (_listeners.hasOwnProperty(eventType)) {
element.removeEventListener(eventType, _listeners[eventType]);
@@ -183,4 +160,4 @@
{auth: {editable_account_fields: []}}, 'abc'));
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.js b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.js
index 95f7a2c..3b889c4 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.js
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.js
@@ -20,6 +20,7 @@
import '../../../styles/gr-menu-page-styles.js';
import '../../../styles/gr-page-nav-styles.js';
import '../../../styles/shared-styles.js';
+import {applyTheme as applyDarkTheme, removeTheme as removeDarkTheme} from '../../../styles/themes/dark-theme.js';
import '../../plugins/gr-endpoint-decorator/gr-endpoint-decorator.js';
import '../gr-change-table-editor/gr-change-table-editor.js';
import '../../shared/gr-button/gr-button.js';
@@ -68,8 +69,6 @@
const ABSOLUTE_URL_PATTERN = /^https?:/;
const TRAILING_SLASH_PATTERN = /\/$/;
-const RELOAD_MESSAGE = 'Reloading...';
-
const HTTP_AUTH = [
'HTTP',
'HTTP_LDAP',
@@ -475,17 +474,19 @@
_handleToggleDark() {
if (this._isDark) {
window.localStorage.removeItem('dark-theme');
+ removeDarkTheme();
} else {
window.localStorage.setItem('dark-theme', 'true');
+ applyDarkTheme();
}
+ this._isDark = !!window.localStorage.getItem('dark-theme');
this.dispatchEvent(new CustomEvent('show-alert', {
- detail: {message: RELOAD_MESSAGE},
+ detail: {
+ message: `Theme changed to ${this._isDark ? 'dark' : 'light'}.`,
+ },
bubbles: true,
composed: true,
}));
- this.async(() => {
- window.location.reload();
- }, 1);
}
_showHttpAuth(config) {
@@ -497,6 +498,13 @@
return false;
}
+
+ /**
+ * Work around a issue on iOS when clicking turns into double tap
+ */
+ _onTapDarkToggle(e) {
+ e.preventDefault();
+ }
}
customElements.define(GrSettingsView.is, GrSettingsView);
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.js b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.js
index e32a551..0e0f86c 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.js
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.js
@@ -107,6 +107,7 @@
aria-labelledby="darkThemeToggleLabel"
checked="[[_isDark]]"
on-change="_handleToggleDark"
+ on-tap="_onTapDarkToggle"
></paper-toggle-button>
<div id="darkThemeToggleLabel">Dark theme (alpha)</div>
</div>
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.html b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.js
similarity index 87%
rename from polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.html
rename to polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.js
index e430ecb..c0ec344 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.js
@@ -1,52 +1,33 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-settings-view</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-settings-view></gr-settings-view>
- </template>
-</test-fixture>
-
-<test-fixture id="blank">
- <template>
- <div></div>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
+import {getComputedStyleValue} from '../../../utils/dom-util.js';
import './gr-settings-view.js';
import {flush, dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+
+const basicFixture = fixtureFromElement('gr-settings-view');
+const blankFixture = fixtureFromElement('div');
+
suite('gr-settings-view tests', () => {
let element;
let account;
let preferences;
let config;
- let sandbox;
function valueOf(title, fieldsetid) {
const sections = element.$[fieldsetid].querySelectorAll('section');
@@ -69,12 +50,11 @@
}
function stubAddAccountEmail(statusCode) {
- return sandbox.stub(element.$.restAPI, 'addAccountEmail',
+ return sinon.stub(element.$.restAPI, 'addAccountEmail').callsFake(
() => Promise.resolve({status: statusCode}));
}
setup(done => {
- sandbox = sinon.sandbox.create();
account = {
_account_id: 123,
name: 'user name',
@@ -112,25 +92,34 @@
getConfig() { return Promise.resolve(config); },
getAccountGroups() { return Promise.resolve([]); },
});
- element = fixture('basic');
+ element = basicFixture.instantiate();
// Allow the element to render.
element._loadingPromise.then(done);
});
- teardown(() => {
- sandbox.restore();
+ test('theme changing', () => {
+ window.localStorage.removeItem('dark-theme');
+ assert.isFalse(window.localStorage.getItem('dark-theme') === 'true');
+ const themeToggle = element.shadowRoot
+ .querySelector('.darkToggle paper-toggle-button');
+ MockInteractions.tap(themeToggle);
+ assert.isTrue(window.localStorage.getItem('dark-theme') === 'true');
+ assert.equal(
+ getComputedStyleValue('--primary-text-color', document.body), '#e8eaed'
+ );
+ MockInteractions.tap(themeToggle);
+ assert.isFalse(window.localStorage.getItem('dark-theme') === 'true');
});
test('calls the title-change event', () => {
- const titleChangedStub = sandbox.stub();
+ const titleChangedStub = sinon.stub();
// Create a new view.
const newElement = document.createElement('gr-settings-view');
newElement.addEventListener('title-change', titleChangedStub);
- // Attach it to the fixture.
- const blank = fixture('blank');
+ const blank = blankFixture.instantiate();
blank.appendChild(newElement);
flush();
@@ -351,7 +340,7 @@
});
test('emails are loaded without emailToken', () => {
- sandbox.stub(element.$.emailEditor, 'loadData');
+ sinon.stub(element.$.emailEditor, 'loadData');
element.params = {};
element.attached();
assert.isTrue(element.$.emailEditor.loadData.calledOnce);
@@ -361,7 +350,7 @@
let newColumns = ['Owner', 'Project', 'Branch'];
element._localChangeTableColumns = newColumns.slice(0);
element._showNumber = false;
- const cloneStub = sandbox.stub(element, '_cloneChangeTableColumns');
+ const cloneStub = sinon.stub(element, '_cloneChangeTableColumns');
element._handleSaveChangeTable();
assert.isTrue(cloneStub.calledOnce);
assert.deepEqual(element.prefs.change_table, newColumns);
@@ -405,7 +394,7 @@
});
test('test that reset button is called', () => {
- const overlayOpen = sandbox.stub(element, '_handleResetMenuButton');
+ const overlayOpen = sinon.stub(element, '_handleResetMenuButton');
MockInteractions.tap(element.$.resetMenu);
@@ -489,11 +478,13 @@
let resolveConfirm;
setup(() => {
- sandbox.stub(element.$.emailEditor, 'loadData');
- sandbox.stub(
+ sinon.stub(element.$.emailEditor, 'loadData');
+ sinon.stub(
element.$.restAPI,
- 'confirmEmail',
- () => new Promise(resolve => { resolveConfirm = resolve; }));
+ 'confirmEmail')
+ .callsFake(
+ () => new Promise(
+ resolve => { resolveConfirm = resolve; }));
element.params = {emailToken: 'foo'};
element.attached();
});
@@ -516,7 +507,7 @@
});
test('show-alert is fired when email is confirmed', done => {
- sandbox.spy(element, 'dispatchEvent');
+ sinon.spy(element, 'dispatchEvent');
element._loadingPromise.then(() => {
assert.equal(
element.dispatchEvent.lastCall.args[0].type, 'show-alert');
@@ -529,4 +520,3 @@
});
});
});
-</script>
diff --git a/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor_test.html b/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor_test.js
similarity index 75%
rename from polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor_test.html
rename to polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor_test.js
index 56625ae..d4a0372 100644
--- a/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor_test.js
@@ -1,40 +1,26 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-ssh-editor</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-ssh-editor></gr-ssh-editor>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-ssh-editor.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+
+const basicFixture = fixtureFromElement('gr-ssh-editor');
+
suite('gr-ssh-editor tests', () => {
let element;
let keys;
@@ -60,7 +46,7 @@
getAccountSSHKeys() { return Promise.resolve(keys); },
});
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.loadData().then(() => { flush(done); });
});
@@ -80,8 +66,8 @@
test('remove key', done => {
const lastKey = keys[1];
- const saveStub = sinon.stub(element.$.restAPI, 'deleteAccountSSHKey',
- () => Promise.resolve());
+ const saveStub = sinon.stub(element.$.restAPI, 'deleteAccountSSHKey')
+ .callsFake(() => Promise.resolve());
assert.equal(element._keysToRemove.length, 0);
assert.isFalse(element.hasUnsavedChanges);
@@ -131,7 +117,7 @@
valid: true,
};
- const addStub = sinon.stub(element.$.restAPI, 'addAccountSSHKey',
+ const addStub = sinon.stub(element.$.restAPI, 'addAccountSSHKey').callsFake(
() => Promise.resolve(newKeyObject));
element._newKey = newKeyString;
@@ -156,7 +142,7 @@
test('add invalid key', done => {
const newKeyString = 'not even close to valid';
- const addStub = sinon.stub(element.$.restAPI, 'addAccountSSHKey',
+ const addStub = sinon.stub(element.$.restAPI, 'addAccountSSHKey').callsFake(
() => Promise.reject(new Error('error')));
element._newKey = newKeyString;
@@ -178,4 +164,4 @@
assert.equal(addStub.lastCall.args[0], newKeyString);
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor_test.html b/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor_test.js
similarity index 81%
rename from polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor_test.html
rename to polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor_test.js
index 2a08e4f..d42f579 100644
--- a/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor_test.js
@@ -1,39 +1,25 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-settings-view</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-watched-projects-editor></gr-watched-projects-editor>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-watched-projects-editor.js';
+
+const basicFixture = fixtureFromElement('gr-watched-projects-editor');
+
suite('gr-watched-projects-editor tests', () => {
let element;
@@ -75,7 +61,7 @@
},
});
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.loadData().then(() => { flush(done); });
});
@@ -212,4 +198,4 @@
assert.equal(element._projectsToRemove[0].project, 'project b');
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip.js b/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip.js
index c74a396..7e40f48 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip.js
+++ b/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip.js
@@ -48,6 +48,12 @@
static get properties() {
return {
account: Object,
+ /**
+ * Optional ChangeInfo object, typically comes from the change page or
+ * from a row in a list of search results. This is needed for some change
+ * related features like adding the user as a reviewer.
+ */
+ change: Object,
voteableText: String,
disabled: {
type: Boolean,
@@ -58,7 +64,12 @@
type: Boolean,
value: false,
},
- showAttention: {
+ /**
+ * Should attention set related features be shown in the component? Note
+ * that the information whether the user is in the attention set or not is
+ * part of the ChangeInfo object in the change property.
+ */
+ highlightAttention: {
type: Boolean,
value: false,
},
diff --git a/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip_html.js b/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip_html.js
index ee19374..7c75488 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip_html.js
+++ b/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip_html.js
@@ -83,7 +83,8 @@
<div class$="container [[_getBackgroundClass(transparentBackground)]]">
<gr-account-link
account="[[account]]"
- show-attention="[[showAttention]]"
+ change="[[change]]"
+ highlight-attention="[[highlightAttention]]"
voteable-text="[[voteableText]]"
>
</gr-account-link>
diff --git a/polygerrit-ui/app/elements/shared/gr-account-entry/gr-account-entry_test.html b/polygerrit-ui/app/elements/shared/gr-account-entry/gr-account-entry_test.html
deleted file mode 100644
index 5899ad4..0000000
--- a/polygerrit-ui/app/elements/shared/gr-account-entry/gr-account-entry_test.html
+++ /dev/null
@@ -1,109 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-account-entry</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-account-entry></gr-account-entry>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-account-entry.js';
-suite('gr-account-entry tests', () => {
- let sandbox;
- let element;
-
- const suggestion1 = {
- email: 'email1@example.com',
- _account_id: 1,
- some_property: 'value',
- };
- const suggestion2 = {
- email: 'email2@example.com',
- _account_id: 2,
- };
- const suggestion3 = {
- email: 'email25@example.com',
- _account_id: 25,
- some_other_property: 'other value',
- };
-
- setup(done => {
- element = fixture('basic');
- sandbox = sinon.sandbox.create();
- return flush(done);
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- suite('stubbed values for querySuggestions', () => {
- setup(() => {
- element.querySuggestions = input => Promise.resolve([
- suggestion1,
- suggestion2,
- suggestion3,
- ]);
- });
- });
-
- test('account-text-changed fired when input text changed and allowAnyInput',
- () => {
- // Spy on query, as that is called when _updateSuggestions proceeds.
- const changeStub = sandbox.stub();
- element.allowAnyInput = true;
- element.querySuggestions = input => Promise.resolve([]);
- element.addEventListener('account-text-changed', changeStub);
- element.$.input.text = 'a';
- assert.isTrue(changeStub.calledOnce);
- element.$.input.text = 'ab';
- assert.isTrue(changeStub.calledTwice);
- });
-
- test('account-text-changed not fired when input text changed without ' +
- 'allowAnyInput', () => {
- // Spy on query, as that is called when _updateSuggestions proceeds.
- const changeStub = sandbox.stub();
- element.querySuggestions = input => Promise.resolve([]);
- element.addEventListener('account-text-changed', changeStub);
- element.$.input.text = 'a';
- assert.isFalse(changeStub.called);
- });
-
- test('setText', () => {
- // Spy on query, as that is called when _updateSuggestions proceeds.
- const suggestSpy = sandbox.spy(element.$.input, 'query');
- element.setText('test text');
- flushAsynchronousOperations();
-
- assert.equal(element.$.input.$.input.value, 'test text');
- assert.isFalse(suggestSpy.called);
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-account-entry/gr-account-entry_test.js b/polygerrit-ui/app/elements/shared/gr-account-entry/gr-account-entry_test.js
new file mode 100644
index 0000000..396145b
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-account-entry/gr-account-entry_test.js
@@ -0,0 +1,90 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-account-entry.js';
+
+const basicFixture = fixtureFromElement('gr-account-entry');
+
+suite('gr-account-entry tests', () => {
+ let element;
+
+ const suggestion1 = {
+ email: 'email1@example.com',
+ _account_id: 1,
+ some_property: 'value',
+ };
+ const suggestion2 = {
+ email: 'email2@example.com',
+ _account_id: 2,
+ };
+ const suggestion3 = {
+ email: 'email25@example.com',
+ _account_id: 25,
+ some_other_property: 'other value',
+ };
+
+ setup(done => {
+ element = basicFixture.instantiate();
+
+ return flush(done);
+ });
+
+ suite('stubbed values for querySuggestions', () => {
+ setup(() => {
+ element.querySuggestions = input => Promise.resolve([
+ suggestion1,
+ suggestion2,
+ suggestion3,
+ ]);
+ });
+ });
+
+ test('account-text-changed fired when input text changed and allowAnyInput',
+ () => {
+ // Spy on query, as that is called when _updateSuggestions proceeds.
+ const changeStub = sinon.stub();
+ element.allowAnyInput = true;
+ element.querySuggestions = input => Promise.resolve([]);
+ element.addEventListener('account-text-changed', changeStub);
+ element.$.input.text = 'a';
+ assert.isTrue(changeStub.calledOnce);
+ element.$.input.text = 'ab';
+ assert.isTrue(changeStub.calledTwice);
+ });
+
+ test('account-text-changed not fired when input text changed without ' +
+ 'allowAnyInput', () => {
+ // Spy on query, as that is called when _updateSuggestions proceeds.
+ const changeStub = sinon.stub();
+ element.querySuggestions = input => Promise.resolve([]);
+ element.addEventListener('account-text-changed', changeStub);
+ element.$.input.text = 'a';
+ assert.isFalse(changeStub.called);
+ });
+
+ test('setText', () => {
+ // Spy on query, as that is called when _updateSuggestions proceeds.
+ const suggestSpy = sinon.spy(element.$.input, 'query');
+ element.setText('test text');
+ flushAsynchronousOperations();
+
+ assert.equal(element.$.input.$.input.value, 'test text');
+ assert.isFalse(suggestSpy.called);
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.js b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.js
index 8c2b7da..f666148 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.js
+++ b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.js
@@ -44,8 +44,28 @@
* @type {{ name: string, status: string }}
*/
account: Object,
+ /**
+ * Optional ChangeInfo object, typically comes from the change page or
+ * from a row in a list of search results. This is needed for some change
+ * related features like adding the user as a reviewer.
+ */
+ change: Object,
voteableText: String,
- showAttention: {
+ /**
+ * Should attention set related features be shown in the component? Note
+ * that the information whether the user is in the attention set or not is
+ * part of the ChangeInfo object in the change property.
+ */
+ highlightAttention: {
+ type: Boolean,
+ value: false,
+ },
+ blurred: {
+ type: Boolean,
+ value: false,
+ reflectToAttribute: true,
+ },
+ hideHovercard: {
type: Boolean,
value: false,
},
@@ -57,7 +77,10 @@
type: Boolean,
value: false,
},
- _serverConfig: {
+ /**
+ * This is a ServerInfo response object.
+ */
+ _config: {
type: Object,
value: null,
},
@@ -67,8 +90,22 @@
/** @override */
ready() {
super.ready();
- this.$.restAPI.getConfig()
- .then(config => { this._serverConfig = config; });
+ this.$.restAPI.getConfig().then(config => { this._config = config; });
+ }
+
+ get isAttentionSetEnabled() {
+ return !!this._config && !!this._config.change
+ && !!this._config.change.enable_attention_set
+ && !!this.highlightAttention && !!this.change && !!this.account;
+ }
+
+ get hasAttention() {
+ if (!this.isAttentionSetEnabled || !this.change.attention_set) return false;
+ return this.change.attention_set.hasOwnProperty(this.account._account_id);
+ }
+
+ _computeShowAttentionIcon(config, highlightAttention, account, change) {
+ return this.isAttentionSetEnabled && this.hasAttention;
}
_computeName(account, config) {
diff --git a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_html.js b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_html.js
index ba2d9cb..9e7807a 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_html.js
+++ b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_html.js
@@ -49,7 +49,11 @@
@apply --gr-account-label-text-hover-style;
}
iron-icon.attention {
+ width: 14px;
+ height: 14px;
vertical-align: top;
+ position: relative;
+ top: 3px;
}
iron-icon.status {
width: 14px;
@@ -61,23 +65,26 @@
</style>
<div class="overlay"></div>
<span>
- <gr-hovercard-account
- attention="[[showAttention]]"
- account="[[account]]"
- voteable-text="[[voteableText]]"
+ <template is="dom-if" if="[[!hideHovercard]]">
+ <gr-hovercard-account
+ account="[[account]]"
+ change="[[change]]"
+ highlight-attention="[[highlightAttention]]"
+ voteable-text="[[voteableText]]"
+ >
+ </gr-hovercard-account>
+ </template>
+ <template
+ is="dom-if"
+ if="[[_computeShowAttentionIcon(_config, highlightAttention, account, change)]]"
>
- </gr-hovercard-account>
- <template is="dom-if" if="[[showAttention]]">
- <iron-icon class="attention" icon="gr-icons:attention"></iron-icon
- ><!--
- --></template
- ><!--
- --><template is="dom-if" if="[[!hideAvatar]]"
- ><!--
- --><gr-avatar account="[[account]]" image-size="32"></gr-avatar>
+ <iron-icon class="attention" icon="gr-icons:attention"></iron-icon>
+ </template>
+ <template is="dom-if" if="[[!hideAvatar]]">
+ <gr-avatar account="[[account]]" image-size="32"></gr-avatar>
</template>
<span class="text">
- <span class="name"> [[_computeName(account, _serverConfig)]]</span>
+ <span class="name">[[_computeName(account, _config)]]</span>
<template is="dom-if" if="[[!hideStatus]]">
<template is="dom-if" if="[[account.status]]">
<iron-icon class="status" icon="gr-icons:calendar"></iron-icon>
diff --git a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_test.html b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_test.html
deleted file mode 100644
index 4cc66c4..0000000
--- a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_test.html
+++ /dev/null
@@ -1,94 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-account-label</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-account-label></gr-account-label>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-account-label.js';
-suite('gr-account-label tests', () => {
- let element;
-
- setup(() => {
- stub('gr-rest-api-interface', {
- getConfig() { return Promise.resolve({}); },
- getLoggedIn() { return Promise.resolve(false); },
- });
- element = fixture('basic');
- element._config = {
- user: {
- anonymous_coward_name: 'Anonymous Coward',
- },
- };
- });
-
- test('null guard', () => {
- assert.doesNotThrow(() => {
- element.account = null;
- });
- });
-
- suite('_computeName', () => {
- test('not showing anonymous', () => {
- const account = {name: 'Wyatt'};
- assert.deepEqual(element._computeName(account, null), 'Wyatt');
- });
-
- test('showing anonymous but no config', () => {
- const account = {};
- assert.deepEqual(element._computeName(account, null),
- 'Anonymous');
- });
-
- test('test for Anonymous Coward user and replace with Anonymous', () => {
- const config = {
- user: {
- anonymous_coward_name: 'Anonymous Coward',
- },
- };
- const account = {};
- assert.deepEqual(element._computeName(account, config),
- 'Anonymous');
- });
-
- test('test for anonymous_coward_name', () => {
- const config = {
- user: {
- anonymous_coward_name: 'TestAnon',
- },
- };
- const account = {};
- assert.deepEqual(element._computeName(account, config),
- 'TestAnon');
- });
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_test.js b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_test.js
new file mode 100644
index 0000000..94274a7
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_test.js
@@ -0,0 +1,80 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-account-label.js';
+
+const basicFixture = fixtureFromElement('gr-account-label');
+
+suite('gr-account-label tests', () => {
+ let element;
+
+ setup(() => {
+ stub('gr-rest-api-interface', {
+ getConfig() { return Promise.resolve({}); },
+ getLoggedIn() { return Promise.resolve(false); },
+ });
+ element = basicFixture.instantiate();
+ element._config = {
+ user: {
+ anonymous_coward_name: 'Anonymous Coward',
+ },
+ };
+ });
+
+ test('null guard', () => {
+ assert.doesNotThrow(() => {
+ element.account = null;
+ });
+ });
+
+ suite('_computeName', () => {
+ test('not showing anonymous', () => {
+ const account = {name: 'Wyatt'};
+ assert.deepEqual(element._computeName(account, null), 'Wyatt');
+ });
+
+ test('showing anonymous but no config', () => {
+ const account = {};
+ assert.deepEqual(element._computeName(account, null),
+ 'Anonymous');
+ });
+
+ test('test for Anonymous Coward user and replace with Anonymous', () => {
+ const config = {
+ user: {
+ anonymous_coward_name: 'Anonymous Coward',
+ },
+ };
+ const account = {};
+ assert.deepEqual(element._computeName(account, config),
+ 'Anonymous');
+ });
+
+ test('test for anonymous_coward_name', () => {
+ const config = {
+ user: {
+ anonymous_coward_name: 'TestAnon',
+ },
+ };
+ const account = {};
+ assert.deepEqual(element._computeName(account, config),
+ 'TestAnon');
+ });
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link.js b/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link.js
index d7dd88d..3844bea 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link.js
+++ b/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link.js
@@ -41,7 +41,18 @@
return {
voteableText: String,
account: Object,
- showAttention: {
+ /**
+ * Optional ChangeInfo object, typically comes from the change page or
+ * from a row in a list of search results. This is needed for some change
+ * related features like adding the user as a reviewer.
+ */
+ change: Object,
+ /**
+ * Should attention set related features be shown in the component? Note
+ * that the information whether the user is in the attention set or not is
+ * part of the ChangeInfo object in the change property.
+ */
+ highlightAttention: {
type: Boolean,
value: false,
},
diff --git a/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link_html.js b/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link_html.js
index ce2dc9e..44afb84 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link_html.js
+++ b/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link_html.js
@@ -42,10 +42,11 @@
<span>
<a href$="[[_computeOwnerLink(account)]]">
<gr-account-label
- show-attention="[[showAttention]]"
+ account="[[account]]"
+ change="[[change]]"
+ highlight-attention="[[highlightAttention]]"
hide-avatar="[[hideAvatar]]"
hide-status="[[hideStatus]]"
- account="[[account]]"
voteable-text="[[voteableText]]"
>
</gr-account-label>
diff --git a/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link_test.html b/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link_test.html
deleted file mode 100644
index f3bff6e..0000000
--- a/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link_test.html
+++ /dev/null
@@ -1,81 +0,0 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2015 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-account-link</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-account-link></gr-account-link>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-account-link.js';
-import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
-
-suite('gr-account-link tests', () => {
- let element;
- let sandbox;
-
- setup(() => {
- stub('gr-rest-api-interface', {
- getConfig() { return Promise.resolve({}); },
- });
- element = fixture('basic');
- sandbox = sinon.sandbox.create();
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('computed fields', () => {
- const url = 'test/url';
- const urlStub = sandbox.stub(GerritNav, 'getUrlForOwner').returns(url);
- const account = {
- email: 'email',
- username: 'username',
- name: 'name',
- _account_id: '_account_id',
- };
- assert.isNotOk(element._computeOwnerLink());
- assert.equal(element._computeOwnerLink(account), url);
- assert.isTrue(urlStub.lastCall.calledWithExactly('email'));
-
- delete account.email;
- assert.equal(element._computeOwnerLink(account), url);
- assert.isTrue(urlStub.lastCall.calledWithExactly('username'));
-
- delete account.username;
- assert.equal(element._computeOwnerLink(account), url);
- assert.isTrue(urlStub.lastCall.calledWithExactly('name'));
-
- delete account.name;
- assert.equal(element._computeOwnerLink(account), url);
- assert.isTrue(urlStub.lastCall.calledWithExactly('_account_id'));
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link_test.js b/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link_test.js
new file mode 100644
index 0000000..554953e
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link_test.js
@@ -0,0 +1,60 @@
+/**
+ * @license
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import '../../../test/common-test-setup-karma.js';
+import './gr-account-link.js';
+import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
+
+const basicFixture = fixtureFromElement('gr-account-link');
+
+suite('gr-account-link tests', () => {
+ let element;
+
+ setup(() => {
+ stub('gr-rest-api-interface', {
+ getConfig() { return Promise.resolve({}); },
+ });
+ element = basicFixture.instantiate();
+ });
+
+ test('computed fields', () => {
+ const url = 'test/url';
+ const urlStub = sinon.stub(GerritNav, 'getUrlForOwner').returns(url);
+ const account = {
+ email: 'email',
+ username: 'username',
+ name: 'name',
+ _account_id: '_account_id',
+ };
+ assert.isNotOk(element._computeOwnerLink());
+ assert.equal(element._computeOwnerLink(account), url);
+ assert.isTrue(urlStub.lastCall.calledWithExactly('email'));
+
+ delete account.email;
+ assert.equal(element._computeOwnerLink(account), url);
+ assert.isTrue(urlStub.lastCall.calledWithExactly('username'));
+
+ delete account.username;
+ assert.equal(element._computeOwnerLink(account), url);
+ assert.isTrue(urlStub.lastCall.calledWithExactly('name'));
+
+ delete account.name;
+ assert.equal(element._computeOwnerLink(account), url);
+ assert.isTrue(urlStub.lastCall.calledWithExactly('_account_id'));
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list_test.html b/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list_test.js
similarity index 84%
rename from polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list_test.html
rename to polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list_test.js
index 41158a8..b26f468 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list_test.js
@@ -1,41 +1,26 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-account-list</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-account-list></gr-account-list>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-account-list.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+const basicFixture = fixtureFromElement('gr-account-list');
+
class MockSuggestionsProvider {
getSuggestions(input) {
return Promise.resolve([]);
@@ -64,7 +49,7 @@
let existingAccount1;
let existingAccount2;
- let sandbox;
+
let element;
let suggestionsProvider;
@@ -73,23 +58,18 @@
}
setup(() => {
- sandbox = sinon.sandbox.create();
existingAccount1 = makeAccount();
existingAccount2 = makeAccount();
stub('gr-rest-api-interface', {
getConfig() { return Promise.resolve({}); },
});
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.accounts = [existingAccount1, existingAccount2];
suggestionsProvider = new MockSuggestionsProvider();
element.suggestionsProvider = suggestionsProvider;
});
- teardown(() => {
- sandbox.restore();
- });
-
test('account entry only appears when editable', () => {
element.readonly = false;
assert.isFalse(element.$.entry.hasAttribute('hidden'));
@@ -99,7 +79,7 @@
test('addition and removal of account/group chips', () => {
flushAsynchronousOperations();
- sandbox.stub(element, '_computeRemovable').returns(true);
+ sinon.stub(element, '_computeRemovable').returns(true);
// Existing accounts are listed.
let chips = getChips();
assert.equal(chips.length, 2);
@@ -195,14 +175,15 @@
_account_id: 25,
},
];
- sandbox.stub(suggestionsProvider, 'getSuggestions')
+ sinon.stub(suggestionsProvider, 'getSuggestions')
.returns(Promise.resolve(originalSuggestions));
- sandbox.stub(suggestionsProvider, 'makeSuggestionItem', suggestion => {
- return {
- name: suggestion.email,
- value: suggestion._account_id,
- };
- });
+ sinon.stub(suggestionsProvider, 'makeSuggestionItem')
+ .callsFake( suggestion => {
+ return {
+ name: suggestion.email,
+ value: suggestion._account_id,
+ };
+ });
element._getSuggestions().then(suggestions => {
// Default is no filtering.
@@ -257,13 +238,13 @@
element.allowAnyInput = true;
flushAsynchronousOperations();
- const getTextStub = sandbox.stub(element.$.entry, 'getText');
+ const getTextStub = sinon.stub(element.$.entry, 'getText');
getTextStub.onFirstCall().returns('');
getTextStub.onSecondCall().returns('test');
getTextStub.onThirdCall().returns('test@test');
// When entry is empty, return true.
- const clearStub = sandbox.stub(element.$.entry, 'clear');
+ const clearStub = sinon.stub(element.$.entry, 'clear');
assert.isTrue(element.submitEntryText());
assert.isFalse(clearStub.called);
@@ -381,11 +362,12 @@
},
];
const getSuggestionsStub =
- sandbox.stub(suggestionsProvider, 'getSuggestions')
+ sinon.stub(suggestionsProvider, 'getSuggestions')
.returns(Promise.resolve(suggestions));
const makeSuggestionItemStub =
- sandbox.stub(suggestionsProvider, 'makeSuggestionItem', item => item);
+ sinon.stub(suggestionsProvider, 'makeSuggestionItem')
+ .callsFake( item => item);
const input = element.$.entry.$.input;
@@ -414,11 +396,12 @@
},
];
const getSuggestionsStub =
- sandbox.stub(suggestionsProvider, 'getSuggestions')
+ sinon.stub(suggestionsProvider, 'getSuggestions')
.returns(Promise.resolve(suggestions));
const makeSuggestionItemStub =
- sandbox.stub(suggestionsProvider, 'makeSuggestionItem', item => item);
+ sinon.stub(suggestionsProvider, 'makeSuggestionItem')
+ .callsFake( item => item);
const input = element.$.entry.$.input;
@@ -437,7 +420,7 @@
test('skip suggestion on empty', done => {
element.skipSuggestOnEmpty = true;
const getSuggestionsStub =
- sandbox.stub(suggestionsProvider, 'getSuggestions')
+ sinon.stub(suggestionsProvider, 'getSuggestions')
.returns(Promise.resolve([]));
const input = element.$.entry.$.input;
@@ -465,7 +448,7 @@
});
test('toasts on invalid email', () => {
- const toastHandler = sandbox.stub();
+ const toastHandler = sinon.stub();
element.addEventListener('show-alert', toastHandler);
element._handleAdd({detail: {value: 'test'}});
assert.isTrue(toastHandler.called);
@@ -488,8 +471,8 @@
suite('keyboard interactions', () => {
test('backspace at text input start removes last account', done => {
const input = element.$.entry.$.input;
- sandbox.stub(input, '_updateSuggestions');
- sandbox.stub(element, '_computeRemovable').returns(true);
+ sinon.stub(input, '_updateSuggestions');
+ sinon.stub(element, '_computeRemovable').returns(true);
flush(() => {
// Next line is a workaround for Firefox not moving cursor
// on input field update
@@ -519,10 +502,10 @@
MockInteractions.focus(input.$.input);
flushAsynchronousOperations();
const chips = element.accountChips;
- const chipsOneSpy = sandbox.spy(chips[1], 'focus');
+ const chipsOneSpy = sinon.spy(chips[1], 'focus');
MockInteractions.pressAndReleaseKeyOn(input.$.input, 37); // Left
assert.isTrue(chipsOneSpy.called);
- const chipsZeroSpy = sandbox.spy(chips[0], 'focus');
+ const chipsZeroSpy = sinon.spy(chips[0], 'focus');
MockInteractions.pressAndReleaseKeyOn(chips[1], 37); // Left
assert.isTrue(chipsZeroSpy.called);
MockInteractions.pressAndReleaseKeyOn(chips[0], 37); // Left
@@ -536,8 +519,8 @@
test('delete', done => {
element.accounts = [makeAccount(), makeAccount()];
flush(() => {
- const focusSpy = sandbox.spy(element.accountChips[1], 'focus');
- const removeSpy = sandbox.spy(element, 'removeAccount');
+ const focusSpy = sinon.spy(element.accountChips[1], 'focus');
+ const removeSpy = sinon.spy(element, 'removeAccount');
MockInteractions.pressAndReleaseKeyOn(
element.accountChips[0], 8); // Backspace
assert.isTrue(focusSpy.called);
@@ -551,4 +534,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-alert/gr-alert_test.html b/polygerrit-ui/app/elements/shared/gr-alert/gr-alert_test.html
deleted file mode 100644
index 557ec28..0000000
--- a/polygerrit-ui/app/elements/shared/gr-alert/gr-alert_test.html
+++ /dev/null
@@ -1,59 +0,0 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2015 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-alert</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-alert.js';
-suite('gr-alert tests', () => {
- let element;
-
- setup(() => {
- element = document.createElement('gr-alert');
- });
-
- teardown(() => {
- if (element.parentNode) {
- element.parentNode.removeChild(element);
- }
- });
-
- test('show/hide', () => {
- assert.isNull(element.parentNode);
- element.show();
- assert.equal(element.parentNode, document.body);
- element.updateStyles({'--gr-alert-transition-duration': '0ms'});
- element.hide();
- assert.isNull(element.parentNode);
- });
-
- test('action event', done => {
- element.show();
- element._actionCallback = done;
- MockInteractions.tap(element.shadowRoot
- .querySelector('.action'));
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-alert/gr-alert_test.js b/polygerrit-ui/app/elements/shared/gr-alert/gr-alert_test.js
new file mode 100644
index 0000000..8105584
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-alert/gr-alert_test.js
@@ -0,0 +1,49 @@
+/**
+ * @license
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import '../../../test/common-test-setup-karma.js';
+import './gr-alert.js';
+suite('gr-alert tests', () => {
+ let element;
+
+ setup(() => {
+ element = document.createElement('gr-alert');
+ });
+
+ teardown(() => {
+ if (element.parentNode) {
+ element.parentNode.removeChild(element);
+ }
+ });
+
+ test('show/hide', () => {
+ assert.isNull(element.parentNode);
+ element.show();
+ assert.equal(element.parentNode, document.body);
+ element.updateStyles({'--gr-alert-transition-duration': '0ms'});
+ element.hide();
+ assert.isNull(element.parentNode);
+ });
+
+ test('action event', done => {
+ element.show();
+ element._actionCallback = done;
+ MockInteractions.tap(element.shadowRoot
+ .querySelector('.action'));
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown_test.html b/polygerrit-ui/app/elements/shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown_test.js
similarity index 63%
rename from polygerrit-ui/app/elements/shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown_test.html
rename to polygerrit-ui/app/elements/shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown_test.js
index d836155..f76d070 100644
--- a/polygerrit-ui/app/elements/shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown_test.js
@@ -1,46 +1,30 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-autocomplete-dropdown</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-autocomplete-dropdown></gr-autocomplete-dropdown>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-autocomplete-dropdown.js';
+
+const basicFixture = fixtureFromElement('gr-autocomplete-dropdown');
+
suite('gr-autocomplete-dropdown', () => {
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.open();
element.suggestions = [
{dataValue: 'test value 1', name: 'test name 1', text: 1, label: 'hi'},
@@ -49,7 +33,6 @@
});
teardown(() => {
- sandbox.restore();
if (element.isOpen) element.close();
});
@@ -60,7 +43,7 @@
});
test('escape key', done => {
- const closeSpy = sandbox.spy(element, 'close');
+ const closeSpy = sinon.spy(element, 'close');
MockInteractions.pressAndReleaseKeyOn(element, 27);
flushAsynchronousOperations();
assert.isTrue(closeSpy.called);
@@ -68,8 +51,8 @@
});
test('tab key', () => {
- const handleTabSpy = sandbox.spy(element, '_handleTab');
- const itemSelectedStub = sandbox.stub();
+ const handleTabSpy = sinon.spy(element, '_handleTab');
+ const itemSelectedStub = sinon.stub();
element.addEventListener('item-selected', itemSelectedStub);
MockInteractions.pressAndReleaseKeyOn(element, 9);
assert.isTrue(handleTabSpy.called);
@@ -82,8 +65,8 @@
});
test('enter key', () => {
- const handleEnterSpy = sandbox.spy(element, '_handleEnter');
- const itemSelectedStub = sandbox.stub();
+ const handleEnterSpy = sinon.spy(element, '_handleEnter');
+ const itemSelectedStub = sinon.stub();
element.addEventListener('item-selected', itemSelectedStub);
MockInteractions.pressAndReleaseKeyOn(element, 13);
assert.isTrue(handleEnterSpy.called);
@@ -96,7 +79,7 @@
test('down key', () => {
element.isHidden = true;
- const nextSpy = sandbox.spy(element.$.cursor, 'next');
+ const nextSpy = sinon.spy(element.$.cursor, 'next');
MockInteractions.pressAndReleaseKeyOn(element, 40);
assert.isFalse(nextSpy.called);
assert.equal(element.$.cursor.index, 0);
@@ -108,7 +91,7 @@
test('up key', () => {
element.isHidden = true;
- const prevSpy = sandbox.spy(element.$.cursor, 'previous');
+ const prevSpy = sinon.spy(element.$.cursor, 'previous');
MockInteractions.pressAndReleaseKeyOn(element, 38);
assert.isFalse(prevSpy.called);
assert.equal(element.$.cursor.index, 0);
@@ -121,7 +104,7 @@
});
test('tapping selects item', () => {
- const itemSelectedStub = sandbox.stub();
+ const itemSelectedStub = sinon.stub();
element.addEventListener('item-selected', itemSelectedStub);
MockInteractions.tap(element.$.suggestions.querySelectorAll('li')[1]);
@@ -133,7 +116,7 @@
});
test('tapping child still selects item', () => {
- const itemSelectedStub = sandbox.stub();
+ const itemSelectedStub = sinon.stub();
element.addEventListener('item-selected', itemSelectedStub);
MockInteractions.tap(element.$.suggestions.querySelectorAll('li')[0]
@@ -146,9 +129,9 @@
});
test('updated suggestions resets cursor stops', () => {
- const resetStopsSpy = sandbox.spy(element, '_resetCursorStops');
+ const resetStopsSpy = sinon.spy(element, '_resetCursorStops');
element.suggestions = [];
assert.isTrue(resetStopsSpy.called);
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.js b/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.js
index 4cf56a7..554559a 100644
--- a/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.js
+++ b/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.js
@@ -281,7 +281,7 @@
_updateSuggestions(text, threshold, noDebounce) {
// Polymer 2: check for undefined
- if ([text, threshold, noDebounce].some(arg => arg === undefined)) {
+ if ([text, threshold, noDebounce].includes(undefined)) {
return;
}
diff --git a/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete_test.js b/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete_test.js
index eb05b90..e9753c9 100644
--- a/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete_test.js
+++ b/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete_test.js
@@ -25,7 +25,7 @@
suite('gr-autocomplete tests', () => {
let element;
- let sandbox;
+
const focusOnInput = element => {
MockInteractions.pressAndReleaseKeyOn(element.$.input, 13, null,
'enter');
@@ -33,16 +33,11 @@
setup(() => {
element = basicFixture.instantiate();
- sandbox = sinon.sandbox.create();
- });
-
- teardown(() => {
- sandbox.restore();
});
test('renders', () => {
let promise;
- const queryStub = sandbox.spy(input => promise = Promise.resolve([
+ const queryStub = sinon.spy(input => promise = Promise.resolve([
{name: input + ' 0', value: 0},
{name: input + ' 1', value: 1},
{name: input + ' 2', value: 2},
@@ -76,7 +71,7 @@
test('selectAll', done => {
flush(() => {
const nativeInput = element._nativeInput;
- const selectionStub = sandbox.stub(nativeInput, 'setSelectionRange');
+ const selectionStub = sinon.stub(nativeInput, 'setSelectionRange');
element.selectAll();
assert.isFalse(selectionStub.called);
@@ -90,7 +85,7 @@
test('esc key behavior', done => {
let promise;
- const queryStub = sandbox.spy(() => promise = Promise.resolve([
+ const queryStub = sinon.spy(() => promise = Promise.resolve([
{name: 'blah', value: 123},
]));
element.query = queryStub;
@@ -103,7 +98,7 @@
promise.then(() => {
assert.isFalse(element.$.suggestions.isHidden);
- const cancelHandler = sandbox.spy();
+ const cancelHandler = sinon.spy();
element.addEventListener('cancel', cancelHandler);
MockInteractions.pressAndReleaseKeyOn(element.$.input, 27, null, 'esc');
@@ -119,7 +114,7 @@
test('emits commit and handles cursor movement', done => {
let promise;
- const queryStub = sandbox.spy(input => promise = Promise.resolve([
+ const queryStub = sinon.spy(input => promise = Promise.resolve([
{name: input + ' 0', value: 0},
{name: input + ' 1', value: 1},
{name: input + ' 2', value: 2},
@@ -136,7 +131,7 @@
promise.then(() => {
assert.isFalse(element.$.suggestions.isHidden);
- const commitHandler = sandbox.spy();
+ const commitHandler = sinon.spy();
element.addEventListener('commit', commitHandler);
assert.equal(element.$.suggestions.$.cursor.index, 0);
@@ -169,7 +164,7 @@
test('clear-on-commit behavior (off)', done => {
let promise;
- const queryStub = sandbox.spy(() => {
+ const queryStub = sinon.spy(() => {
promise = Promise.resolve([{name: 'suggestion', value: 0}]);
return promise;
});
@@ -178,7 +173,7 @@
element.text = 'blah';
promise.then(() => {
- const commitHandler = sandbox.spy();
+ const commitHandler = sinon.spy();
element.addEventListener('commit', commitHandler);
MockInteractions.pressAndReleaseKeyOn(element.$.input, 13, null,
@@ -192,7 +187,7 @@
test('clear-on-commit behavior (on)', done => {
let promise;
- const queryStub = sandbox.spy(() => {
+ const queryStub = sinon.spy(() => {
promise = Promise.resolve([{name: 'suggestion', value: 0}]);
return promise;
});
@@ -202,7 +197,7 @@
element.clearOnCommit = true;
promise.then(() => {
- const commitHandler = sandbox.spy();
+ const commitHandler = sinon.spy();
element.addEventListener('commit', commitHandler);
MockInteractions.pressAndReleaseKeyOn(element.$.input, 13, null,
@@ -215,7 +210,7 @@
});
test('threshold guards the query', () => {
- const queryStub = sandbox.spy(() => Promise.resolve([]));
+ const queryStub = sinon.spy(() => Promise.resolve([]));
element.query = queryStub;
element.threshold = 2;
focusOnInput(element);
@@ -226,9 +221,9 @@
});
test('noDebounce=false debounces the query', () => {
- const queryStub = sandbox.spy(() => Promise.resolve([]));
+ const queryStub = sinon.spy(() => Promise.resolve([]));
let callback;
- const debounceStub = sandbox.stub(element, 'debounce',
+ const debounceStub = sinon.stub(element, 'debounce').callsFake(
(name, cb) => { callback = cb; });
element.query = queryStub;
element.noDebounce = false;
@@ -255,7 +250,7 @@
test('when focused', done => {
let promise;
- const queryStub = sandbox.stub()
+ const queryStub = sinon.stub()
.returns(promise = Promise.resolve([
{name: 'suggestion', value: 0},
]));
@@ -274,7 +269,7 @@
test('when not focused', done => {
let promise;
- const queryStub = sandbox.stub()
+ const queryStub = sinon.stub()
.returns(promise = Promise.resolve([
{name: 'suggestion', value: 0},
]));
@@ -291,7 +286,7 @@
test('suggestions should not carry over', done => {
let promise;
- const queryStub = sandbox.stub()
+ const queryStub = sinon.stub()
.returns(promise = Promise.resolve([
{name: 'suggestion', value: 0},
]));
@@ -309,7 +304,7 @@
test('multi completes only the last part of the query', done => {
let promise;
- const queryStub = sandbox.stub()
+ const queryStub = sinon.stub()
.returns(promise = Promise.resolve([
{name: 'suggestion', value: 0},
]));
@@ -319,7 +314,7 @@
element.multi = true;
promise.then(() => {
- const commitHandler = sandbox.spy();
+ const commitHandler = sinon.spy();
element.addEventListener('commit', commitHandler);
MockInteractions.pressAndReleaseKeyOn(element.$.input, 13, null,
@@ -334,9 +329,9 @@
test('tabComplete flag functions', () => {
// commitHandler checks for the commit event, whereas commitSpy checks for
// the _commit function of the element.
- const commitHandler = sandbox.spy();
+ const commitHandler = sinon.spy();
element.addEventListener('commit', commitHandler);
- const commitSpy = sandbox.spy(element, '_commit');
+ const commitSpy = sinon.spy(element, '_commit');
element._focused = true;
element._suggestions = ['tunnel snakes rule!'];
@@ -385,8 +380,8 @@
});
test('_focused flag shows/hides the suggestions', () => {
- const openStub = sandbox.stub(element.$.suggestions, 'open');
- const closedStub = sandbox.stub(element.$.suggestions, 'close');
+ const openStub = sinon.stub(element.$.suggestions, 'open');
+ const closedStub = sinon.stub(element.$.suggestions, 'close');
element._suggestions = ['hello', 'its me'];
assert.isFalse(openStub.called);
assert.isTrue(closedStub.calledOnce);
@@ -399,7 +394,7 @@
test('_handleInputCommit with autocomplete hidden does nothing without' +
'without allowNonSuggestedValues', () => {
- const commitStub = sandbox.stub(element, '_commit');
+ const commitStub = sinon.stub(element, '_commit');
element.$.suggestions.isHidden = true;
element._handleInputCommit();
assert.isFalse(commitStub.called);
@@ -407,7 +402,7 @@
test('_handleInputCommit with autocomplete hidden with' +
'allowNonSuggestedValues', () => {
- const commitStub = sandbox.stub(element, '_commit');
+ const commitStub = sinon.stub(element, '_commit');
element.allowNonSuggestedValues = true;
element.$.suggestions.isHidden = true;
element._handleInputCommit();
@@ -415,7 +410,7 @@
});
test('_handleInputCommit with autocomplete open calls commit', () => {
- const commitStub = sandbox.stub(element, '_commit');
+ const commitStub = sinon.stub(element, '_commit');
element.$.suggestions.isHidden = false;
element._handleInputCommit();
assert.isTrue(commitStub.calledOnce);
@@ -423,7 +418,7 @@
test('_handleInputCommit with autocomplete open calls commit' +
'with allowNonSuggestedValues', () => {
- const commitStub = sandbox.stub(element, '_commit');
+ const commitStub = sinon.stub(element, '_commit');
element.allowNonSuggestedValues = true;
element.$.suggestions.isHidden = false;
element._handleInputCommit();
@@ -432,7 +427,7 @@
test('issue 8655', () => {
function makeSuggestion(s) { return {name: s, text: s, value: s}; }
- const keydownSpy = sandbox.spy(element, '_handleKeydown');
+ const keydownSpy = sinon.spy(element, '_handleKeydown');
element.setText('file:');
element._suggestions =
[makeSuggestion('file:'), makeSuggestion('-file:')];
@@ -455,12 +450,12 @@
let focusSpy;
setup(() => {
- commitSpy = sandbox.spy(element, '_commit');
+ commitSpy = sinon.spy(element, '_commit');
});
test('enter does not call focus', () => {
element._suggestions = ['sugar bombs'];
- focusSpy = sandbox.spy(element, 'focus');
+ focusSpy = sinon.spy(element, 'focus');
MockInteractions.pressAndReleaseKeyOn(element.$.input, 13, null,
'enter');
flushAsynchronousOperations();
@@ -471,8 +466,8 @@
});
test('tab in input, tabComplete = true', () => {
- focusSpy = sandbox.spy(element, 'focus');
- const commitHandler = sandbox.stub();
+ focusSpy = sinon.spy(element, 'focus');
+ const commitHandler = sinon.stub();
element.addEventListener('commit', commitHandler);
element.tabComplete = true;
element._suggestions = ['tunnel snakes drool'];
@@ -487,7 +482,7 @@
test('tab in input, tabComplete = false', () => {
element._suggestions = ['sugar bombs'];
- focusSpy = sandbox.spy(element, 'focus');
+ focusSpy = sinon.spy(element, 'focus');
MockInteractions.pressAndReleaseKeyOn(element.$.input, 9, null, 'tab');
flushAsynchronousOperations();
@@ -501,7 +496,7 @@
element._focused = true;
// When tabComplete is false, do not focus.
element.tabComplete = false;
- focusSpy = sandbox.spy(element, 'focus');
+ focusSpy = sinon.spy(element, 'focus');
flush$0();
assert.isFalse(element.$.suggestions.isHidden);
@@ -518,7 +513,7 @@
element._focused = true;
// When tabComplete is true, focus.
element.tabComplete = true;
- focusSpy = sandbox.spy(element, 'focus');
+ focusSpy = sinon.spy(element, 'focus');
flush$0();
assert.isFalse(element.$.suggestions.isHidden);
@@ -532,7 +527,7 @@
});
test('tap on suggestion commits, does not call focus', () => {
- focusSpy = sandbox.spy(element, 'focus');
+ focusSpy = sinon.spy(element, 'focus');
element._focused = true;
element._suggestions = [{name: 'first suggestion'}];
flush$0();
@@ -548,7 +543,7 @@
});
test('input-keydown event fired', () => {
- const listener = sandbox.spy();
+ const listener = sinon.spy();
element.addEventListener('input-keydown', listener);
MockInteractions.pressAndReleaseKeyOn(element.$.input, 9, null, 'tab');
flushAsynchronousOperations();
@@ -556,8 +551,8 @@
});
test('enter with modifier does not complete', () => {
- const handleSpy = sandbox.spy(element, '_handleKeydown');
- const commitStub = sandbox.stub(element, '_handleInputCommit');
+ const handleSpy = sinon.spy(element, '_handleKeydown');
+ const commitStub = sinon.stub(element, '_handleInputCommit');
MockInteractions.pressAndReleaseKeyOn(
element.$.input, 13, 'ctrl', 'enter');
assert.isTrue(handleSpy.called);
diff --git a/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar_test.html b/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar_test.html
deleted file mode 100644
index dddc3d8..0000000
--- a/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar_test.html
+++ /dev/null
@@ -1,209 +0,0 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2015 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-avatar</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-avatar></gr-avatar>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-avatar.js';
-import {pluginLoader} from '../gr-js-api-interface/gr-plugin-loader.js';
-
-suite('gr-avatar tests', () => {
- let element;
- let sandbox;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('methods', () => {
- assert.equal(
- element._buildAvatarURL({
- _account_id: 123,
- }),
- '/accounts/123/avatar?s=16');
- assert.equal(
- element._buildAvatarURL({
- email: 'test@example.com',
- }),
- '/accounts/test%40example.com/avatar?s=16');
- assert.equal(
- element._buildAvatarURL({
- name: 'John Doe',
- }),
- '/accounts/John%20Doe/avatar?s=16');
- assert.equal(
- element._buildAvatarURL({
- username: 'John_Doe',
- }),
- '/accounts/John_Doe/avatar?s=16');
- assert.equal(
- element._buildAvatarURL({
- _account_id: 123,
- avatars: [
- {
- url: 'https://cdn.example.com/s12-p/photo.jpg',
- height: 12,
- },
- {
- url: 'https://cdn.example.com/s16-p/photo.jpg',
- height: 16,
- },
- {
- url: 'https://cdn.example.com/s100-p/photo.jpg',
- height: 100,
- },
- ],
- }),
- 'https://cdn.example.com/s16-p/photo.jpg');
- assert.equal(
- element._buildAvatarURL({
- _account_id: 123,
- avatars: [
- {
- url: 'https://cdn.example.com/s95-p/photo.jpg',
- height: 95,
- },
- ],
- }),
- '/accounts/123/avatar?s=16');
- assert.equal(element._buildAvatarURL(undefined), '');
- });
-
- test('dom for existing account', () => {
- assert.isFalse(element.hasAttribute('hidden'));
-
- sandbox.stub(
- element,
- '_getConfig',
- () => Promise.resolve({plugin: {has_avatars: true}}));
-
- element.imageSize = 64;
- element.account = {
- _account_id: 123,
- };
-
- assert.strictEqual(element.style.backgroundImage, '');
-
- // Emulate plugins loaded.
- pluginLoader.loadPlugins([]);
-
- Promise.all([
- element.$.restAPI.getConfig(),
- pluginLoader.awaitPluginsLoaded(),
- ]).then(() => {
- assert.isFalse(element.hasAttribute('hidden'));
-
- assert.isTrue(
- element.style.backgroundImage.includes('/accounts/123/avatar?s=64'));
- });
- });
-
- suite('plugin has avatars', () => {
- let element;
- let sandbox;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
-
- stub('gr-avatar', {
- _getConfig: () => Promise.resolve({plugin: {has_avatars: true}}),
- });
-
- element = fixture('basic');
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('dom for non available account', () => {
- assert.isFalse(element.hasAttribute('hidden'));
-
- // Emulate plugins loaded.
- pluginLoader.loadPlugins([]);
-
- return Promise.all([
- element.$.restAPI.getConfig(),
- pluginLoader.awaitPluginsLoaded(),
- ]).then(() => {
- assert.isTrue(element.hasAttribute('hidden'));
-
- assert.strictEqual(element.style.backgroundImage, '');
- });
- });
- });
-
- suite('config not set', () => {
- let element;
- let sandbox;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
-
- stub('gr-avatar', {
- _getConfig: () => Promise.resolve({}),
- });
-
- element = fixture('basic');
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('avatar hidden when account set', () => {
- flush(() => {
- assert.isFalse(element.hasAttribute('hidden'));
-
- element.imageSize = 64;
- element.account = {
- _account_id: 123,
- };
- // Emulate plugins loaded.
- pluginLoader.loadPlugins([]);
-
- return Promise.all([
- element.$.restAPI.getConfig(),
- pluginLoader.awaitPluginsLoaded(),
- ]).then(() => {
- assert.isTrue(element.hasAttribute('hidden'));
- });
- });
- });
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar_test.js b/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar_test.js
new file mode 100644
index 0000000..5e43f90
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar_test.js
@@ -0,0 +1,178 @@
+/**
+ * @license
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import '../../../test/common-test-setup-karma.js';
+import './gr-avatar.js';
+import {pluginLoader} from '../gr-js-api-interface/gr-plugin-loader.js';
+
+const basicFixture = fixtureFromElement('gr-avatar');
+
+suite('gr-avatar tests', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ test('methods', () => {
+ assert.equal(
+ element._buildAvatarURL({
+ _account_id: 123,
+ }),
+ '/accounts/123/avatar?s=16');
+ assert.equal(
+ element._buildAvatarURL({
+ email: 'test@example.com',
+ }),
+ '/accounts/test%40example.com/avatar?s=16');
+ assert.equal(
+ element._buildAvatarURL({
+ name: 'John Doe',
+ }),
+ '/accounts/John%20Doe/avatar?s=16');
+ assert.equal(
+ element._buildAvatarURL({
+ username: 'John_Doe',
+ }),
+ '/accounts/John_Doe/avatar?s=16');
+ assert.equal(
+ element._buildAvatarURL({
+ _account_id: 123,
+ avatars: [
+ {
+ url: 'https://cdn.example.com/s12-p/photo.jpg',
+ height: 12,
+ },
+ {
+ url: 'https://cdn.example.com/s16-p/photo.jpg',
+ height: 16,
+ },
+ {
+ url: 'https://cdn.example.com/s100-p/photo.jpg',
+ height: 100,
+ },
+ ],
+ }),
+ 'https://cdn.example.com/s16-p/photo.jpg');
+ assert.equal(
+ element._buildAvatarURL({
+ _account_id: 123,
+ avatars: [
+ {
+ url: 'https://cdn.example.com/s95-p/photo.jpg',
+ height: 95,
+ },
+ ],
+ }),
+ '/accounts/123/avatar?s=16');
+ assert.equal(element._buildAvatarURL(undefined), '');
+ });
+
+ suite('config set', () => {
+ setup(() => {
+ stub('gr-avatar', {
+ _getConfig: () => Promise.resolve({plugin: {has_avatars: true}}),
+ });
+ element = basicFixture.instantiate();
+ });
+
+ test('dom for existing account', () => {
+ assert.isFalse(element.hasAttribute('hidden'));
+
+ element.imageSize = 64;
+ element.account = {
+ _account_id: 123,
+ };
+
+ assert.strictEqual(element.style.backgroundImage, '');
+
+ // Emulate plugins loaded.
+ pluginLoader.loadPlugins([]);
+
+ return Promise.all([
+ element.$.restAPI.getConfig(),
+ pluginLoader.awaitPluginsLoaded(),
+ ]).then(() => {
+ assert.isFalse(element.hasAttribute('hidden'));
+
+ assert.isTrue(
+ element.style.backgroundImage.includes(
+ '/accounts/123/avatar?s=64'));
+ });
+ });
+ });
+
+ suite('plugin has avatars', () => {
+ let element;
+
+ setup(() => {
+ stub('gr-avatar', {
+ _getConfig: () => Promise.resolve({plugin: {has_avatars: true}}),
+ });
+
+ element = basicFixture.instantiate();
+ });
+
+ test('dom for non available account', () => {
+ assert.isFalse(element.hasAttribute('hidden'));
+
+ // Emulate plugins loaded.
+ pluginLoader.loadPlugins([]);
+
+ return Promise.all([
+ element.$.restAPI.getConfig(),
+ pluginLoader.awaitPluginsLoaded(),
+ ]).then(() => {
+ assert.isTrue(element.hasAttribute('hidden'));
+
+ assert.strictEqual(element.style.backgroundImage, '');
+ });
+ });
+ });
+
+ suite('config not set', () => {
+ let element;
+
+ setup(() => {
+ stub('gr-avatar', {
+ _getConfig: () => Promise.resolve({}),
+ });
+
+ element = basicFixture.instantiate();
+ });
+
+ test('avatar hidden when account set', async () => {
+ await flush();
+ assert.isTrue(element.hasAttribute('hidden'));
+
+ element.imageSize = 64;
+ element.account = {
+ _account_id: 123,
+ };
+ // Emulate plugins loaded.
+ pluginLoader.loadPlugins([]);
+
+ return Promise.all([
+ element.$.restAPI.getConfig(),
+ pluginLoader.awaitPluginsLoaded(),
+ ]).then(() => {
+ assert.isTrue(element.hasAttribute('hidden'));
+ });
+ });
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/shared/gr-button/gr-button_test.html b/polygerrit-ui/app/elements/shared/gr-button/gr-button_test.js
similarity index 70%
rename from polygerrit-ui/app/elements/shared/gr-button/gr-button_test.html
rename to polygerrit-ui/app/elements/shared/gr-button/gr-button_test.js
index dfc3d75..4bc3bea 100644
--- a/polygerrit-ui/app/elements/shared/gr-button/gr-button_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-button/gr-button_test.js
@@ -1,62 +1,43 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-button</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-button></gr-button>
- </template>
-</test-fixture>
-
-<test-fixture id="nested">
- <template>
- <div id="test">
- <gr-button class="testBtn"></gr-button>
- </div>
- </template>
-</test-fixture>
-
-<test-fixture id="tabindex">
- <template>
- <gr-button tabindex="3"></gr-button>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-button.js';
import {addListener} from '@polymer/polymer/lib/utils/gestures.js';
import {appContext} from '../../../services/app-context.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const basicFixture = fixtureFromElement('gr-button');
+
+const nestedFixture = fixtureFromTemplate(html`
+<div id="test">
+ <gr-button class="testBtn"></gr-button>
+</div>
+`);
+
+const tabindexFixture = fixtureFromTemplate(html`
+ <gr-button tabindex="3"></gr-button>
+`);
suite('gr-button tests', () => {
let element;
- let sandbox;
const addSpyOn = function(eventName) {
- const spy = sandbox.spy();
+ const spy = sinon.spy();
if (eventName == 'tap') {
addListener(element, eventName, spy);
} else {
@@ -66,12 +47,7 @@
};
setup(() => {
- element = fixture('basic');
- sandbox = sinon.sandbox.create();
- });
-
- teardown(() => {
- sandbox.restore();
+ element = basicFixture.instantiate();
});
test('disabled is set by disabled', () => {
@@ -118,7 +94,7 @@
});
test('tabindex should be preserved', () => {
- element = fixture('tabindex');
+ element = tabindexFixture.instantiate();
element.disabled = false;
assert.equal(element.getAttribute('tabindex'), '3');
element.disabled = true;
@@ -150,14 +126,14 @@
// Keycodes: 32 for Space, 13 for Enter.
for (const key of [32, 13]) {
test('dispatches click event on keycode ' + key, () => {
- const tapSpy = sandbox.spy();
+ const tapSpy = sinon.spy();
element.addEventListener('click', tapSpy);
MockInteractions.pressAndReleaseKeyOn(element, key);
assert.isTrue(tapSpy.calledOnce);
});
test('dispatches no click event with modifier on keycode ' + key, () => {
- const tapSpy = sandbox.spy();
+ const tapSpy = sinon.spy();
element.addEventListener('click', tapSpy);
MockInteractions.pressAndReleaseKeyOn(element, key, 'shift');
MockInteractions.pressAndReleaseKeyOn(element, key, 'ctrl');
@@ -183,7 +159,7 @@
// Keycodes: 32 for Space, 13 for Enter.
for (const key of [32, 13]) {
test('stops click event on keycode ' + key, () => {
- const tapSpy = sandbox.spy();
+ const tapSpy = sinon.spy();
element.addEventListener('click', tapSpy);
MockInteractions.pressAndReleaseKeyOn(element, key);
assert.isFalse(tapSpy.called);
@@ -194,7 +170,7 @@
suite('reporting', () => {
let reportStub;
setup(() => {
- reportStub = sandbox.stub(appContext.reportingService,
+ reportStub = sinon.stub(appContext.reportingService,
'reportInteraction');
reportStub.reset();
});
@@ -204,19 +180,20 @@
assert.isTrue(reportStub.calledOnce);
assert.equal(reportStub.lastCall.args[0], 'button-click');
assert.deepEqual(reportStub.lastCall.args[1], {
- path: 'html>body>test-fixture#basic>gr-button',
+ path: `html>body>test-fixture#${basicFixture.fixtureId}>gr-button`,
});
});
test('report event after click on nested', () => {
- element = fixture('nested');
+ element = nestedFixture.instantiate();
MockInteractions.click(element.querySelector('gr-button'));
assert.isTrue(reportStub.calledOnce);
assert.equal(reportStub.lastCall.args[0], 'button-click');
assert.deepEqual(reportStub.lastCall.args[1], {
- path: 'html>body>test-fixture#nested>div#test>gr-button.testBtn',
+ path: `html>body>test-fixture#${nestedFixture.fixtureId}` +
+ `>div#test>gr-button.testBtn`,
});
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star_test.html b/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star_test.html
deleted file mode 100644
index 1ea9071..0000000
--- a/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star_test.html
+++ /dev/null
@@ -1,82 +0,0 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2015 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-change-star</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-change-star></gr-change-star>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-change-star.js';
-suite('gr-change-star tests', () => {
- let element;
-
- setup(() => {
- element = fixture('basic');
- element.change = {
- _number: 2,
- starred: true,
- };
- });
-
- test('star visibility states', () => {
- element.set('change.starred', true);
- let icon = element.shadowRoot
- .querySelector('iron-icon');
- assert.isTrue(icon.classList.contains('active'));
- assert.equal(icon.icon, 'gr-icons:star');
-
- element.set('change.starred', false);
- icon = element.shadowRoot
- .querySelector('iron-icon');
- assert.isFalse(icon.classList.contains('active'));
- assert.equal(icon.icon, 'gr-icons:star-border');
- });
-
- test('starring', done => {
- element.addEventListener('toggle-star', () => {
- assert.equal(element.change.starred, true);
- done();
- });
- element.set('change.starred', false);
- MockInteractions.tap(element.shadowRoot
- .querySelector('button'));
- });
-
- test('unstarring', done => {
- element.addEventListener('toggle-star', () => {
- assert.equal(element.change.starred, false);
- done();
- });
- element.set('change.starred', true);
- MockInteractions.tap(element.shadowRoot
- .querySelector('button'));
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star_test.js b/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star_test.js
new file mode 100644
index 0000000..d479ece
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star_test.js
@@ -0,0 +1,68 @@
+/**
+ * @license
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import '../../../test/common-test-setup-karma.js';
+import './gr-change-star.js';
+
+const basicFixture = fixtureFromElement('gr-change-star');
+
+suite('gr-change-star tests', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ element.change = {
+ _number: 2,
+ starred: true,
+ };
+ });
+
+ test('star visibility states', () => {
+ element.set('change.starred', true);
+ let icon = element.shadowRoot
+ .querySelector('iron-icon');
+ assert.isTrue(icon.classList.contains('active'));
+ assert.equal(icon.icon, 'gr-icons:star');
+
+ element.set('change.starred', false);
+ icon = element.shadowRoot
+ .querySelector('iron-icon');
+ assert.isFalse(icon.classList.contains('active'));
+ assert.equal(icon.icon, 'gr-icons:star-border');
+ });
+
+ test('starring', done => {
+ element.addEventListener('toggle-star', () => {
+ assert.equal(element.change.starred, true);
+ done();
+ });
+ element.set('change.starred', false);
+ MockInteractions.tap(element.shadowRoot
+ .querySelector('button'));
+ });
+
+ test('unstarring', done => {
+ element.addEventListener('toggle-star', () => {
+ assert.equal(element.change.starred, false);
+ done();
+ });
+ element.set('change.starred', true);
+ MockInteractions.tap(element.shadowRoot
+ .querySelector('button'));
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status_test.html b/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status_test.js
similarity index 70%
rename from polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status_test.html
rename to polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status_test.js
index 806203b..770a21c 100644
--- a/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status_test.js
@@ -1,39 +1,25 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-change-status</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-change-status></gr-change-status>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-change-status.js';
+
+const basicFixture = fixtureFromElement('gr-change-status');
+
const WIP_TOOLTIP = 'This change isn\'t ready to be reviewed or submitted. ' +
'It will not appear on dashboards unless you are CC\'ed or assigned, ' +
'and email notifications will be silenced until the review is started.';
@@ -47,15 +33,9 @@
suite('gr-change-status tests', () => {
let element;
- let sandbox;
setup(() => {
- element = fixture('basic');
- sandbox = sinon.sandbox.create();
- });
-
- teardown(() => {
- sandbox.restore();
+ element = basicFixture.instantiate();
});
test('WIP', () => {
@@ -134,4 +114,4 @@
assert.isTrue(element.classList.contains('wip'));
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread_test.html b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread_test.js
similarity index 90%
rename from polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread_test.html
rename to polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread_test.js
index e219b22..3837514 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread_test.js
@@ -1,65 +1,40 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2015 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-comment-thread</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-comment-thread></gr-comment-thread>
- </template>
-</test-fixture>
-
-<test-fixture id="withComment">
- <template>
- <gr-comment-thread></gr-comment-thread>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-comment-thread.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
import {SpecialFilePath} from '../../../constants/constants.js';
+const basicFixture = fixtureFromElement('gr-comment-thread');
+
+const withCommentFixture = fixtureFromElement('gr-comment-thread');
+
suite('gr-comment-thread tests', () => {
suite('basic test', () => {
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
stub('gr-rest-api-interface', {
getLoggedIn() { return Promise.resolve(false); },
});
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- });
- teardown(() => {
- sandbox.restore();
+ element = basicFixture.instantiate();
});
test('comments are sorted correctly', () => {
@@ -132,9 +107,9 @@
updated: '2015-12-25 15:00:20.396000000',
__draft: true,
}];
- const commentElStub = sandbox.stub(element, '_commentElWithDraftID',
- () => { return {}; });
- const addDraftStub = sandbox.stub(element, 'addDraft');
+ const commentElStub = sinon.stub(element, '_commentElWithDraftID')
+ .callsFake(() => { return {}; });
+ const addDraftStub = sinon.stub(element, 'addDraft');
element.addOrEditDraft(123);
@@ -144,9 +119,9 @@
test('addOrEditDraft w/o edit draft', () => {
element.comments = [];
- const commentElStub = sandbox.stub(element, '_commentElWithDraftID',
- () => { return {}; });
- const addDraftStub = sandbox.stub(element, 'addDraft');
+ const commentElStub = sinon.stub(element, '_commentElWithDraftID')
+ .callsFake(() => { return {}; });
+ const addDraftStub = sinon.stub(element, 'addDraft');
element.addOrEditDraft(123);
@@ -188,7 +163,7 @@
test('setting project name loads the project config', done => {
const projectName = 'foo/bar/baz';
- const getProjectStub = sandbox.stub(element.$.restAPI, 'getProjectConfig')
+ const getProjectStub = sinon.stub(element.$.restAPI, 'getProjectConfig')
.returns(Promise.resolve({}));
element.projectName = projectName;
flush(() => {
@@ -203,7 +178,7 @@
assert.isNotOk(element.shadowRoot
.querySelector('.pathInfo'));
- sandbox.stub(GerritNav, 'getUrlForDiffById');
+ sinon.stub(GerritNav, 'getUrlForDiffById');
element.changeNum = 123;
element.projectName = 'test project';
element.path = 'path/to/file';
@@ -253,10 +228,8 @@
suite('comment action tests with unresolved thread', () => {
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
stub('gr-rest-api-interface', {
getLoggedIn() { return Promise.resolve(false); },
saveDiffDraft() {
@@ -277,7 +250,7 @@
},
deleteDiffDraft() { return Promise.resolve({ok: true}); },
});
- element = fixture('withComment');
+ element = withCommentFixture.instantiate();
element.comments = [{
author: {
name: 'Mr. Peanutbutter',
@@ -295,14 +268,10 @@
flushAsynchronousOperations();
});
- teardown(() => {
- sandbox.restore();
- });
-
test('reply', () => {
const commentEl = element.shadowRoot
.querySelector('gr-comment');
- const reportStub = sandbox.stub(element.reporting,
+ const reportStub = sinon.stub(element.reporting,
'recordDraftInteraction');
assert.ok(commentEl);
@@ -320,7 +289,7 @@
test('quote reply', () => {
const commentEl = element.shadowRoot
.querySelector('gr-comment');
- const reportStub = sandbox.stub(element.reporting,
+ const reportStub = sinon.stub(element.reporting,
'recordDraftInteraction');
assert.ok(commentEl);
@@ -336,7 +305,7 @@
});
test('quote reply multiline', () => {
- const reportStub = sandbox.stub(element.reporting,
+ const reportStub = sinon.stub(element.reporting,
'recordDraftInteraction');
element.comments = [{
author: {
@@ -367,7 +336,7 @@
});
test('ack', done => {
- const reportStub = sandbox.stub(element.reporting,
+ const reportStub = sinon.stub(element.reporting,
'recordDraftInteraction');
element.changeNum = '42';
element.patchNum = '1';
@@ -390,7 +359,7 @@
});
test('done', done => {
- const reportStub = sandbox.stub(element.reporting,
+ const reportStub = sinon.stub(element.reporting,
'recordDraftInteraction');
element.changeNum = '42';
element.patchNum = '1';
@@ -419,7 +388,7 @@
.querySelector('gr-comment');
assert.ok(commentEl);
- const saveOrDiscardStub = sandbox.stub();
+ const saveOrDiscardStub = sinon.stub();
element.addEventListener('thread-changed', saveOrDiscardStub);
element.shadowRoot
.querySelector('gr-comment')._fireSave();
@@ -467,7 +436,7 @@
'it’s pronouced jiff, not giff'));
flushAsynchronousOperations();
- const saveOrDiscardStub = sandbox.stub();
+ const saveOrDiscardStub = sinon.stub();
element.addEventListener('thread-changed', saveOrDiscardStub);
const draftEl =
dom(element.root).querySelectorAll('gr-comment')[1];
@@ -500,7 +469,7 @@
const rootId = element.rootId;
assert.isOk(rootId);
- const saveOrDiscardStub = sandbox.stub();
+ const saveOrDiscardStub = sinon.stub();
element.addEventListener('thread-changed', saveOrDiscardStub);
const draftEl =
dom(element.root).querySelectorAll('gr-comment')[0];
@@ -834,10 +803,8 @@
suite('comment action tests on resolved comments', () => {
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
stub('gr-rest-api-interface', {
getLoggedIn() { return Promise.resolve(false); },
saveDiffDraft() {
@@ -858,7 +825,7 @@
},
deleteDiffDraft() { return Promise.resolve({ok: true}); },
});
- element = fixture('withComment');
+ element = withCommentFixture.instantiate();
element.comments = [{
author: {
name: 'Mr. Peanutbutter',
@@ -874,10 +841,6 @@
flushAsynchronousOperations();
});
- teardown(() => {
- sandbox.restore();
- });
-
test('ack and done should be hidden', () => {
element.changeNum = '42';
element.patchNum = '1';
@@ -903,4 +866,4 @@
assert.ok(quoteBtn);
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.js b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.js
index 02fec5a..e27940e 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.js
+++ b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.js
@@ -357,7 +357,7 @@
_calculateActionstoShow(showActions, isRobotComment) {
// Polymer 2: check for undefined
- if ([showActions, isRobotComment].some(arg => arg === undefined)) {
+ if ([showActions, isRobotComment].includes(undefined)) {
return;
}
@@ -786,7 +786,7 @@
_loadLocalDraft(changeNum, patchNum, comment) {
// Polymer 2: check for undefined
- if ([changeNum, patchNum, comment].some(arg => arg === undefined)) {
+ if ([changeNum, patchNum, comment].includes(undefined)) {
return;
}
diff --git a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment_test.html b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment_test.js
similarity index 90%
rename from polygerrit-ui/app/elements/shared/gr-comment/gr-comment_test.html
rename to polygerrit-ui/app/elements/shared/gr-comment/gr-comment_test.js
index 17c01e9..b227383 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment_test.js
@@ -1,46 +1,30 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2015 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-comment</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<script src="/node_modules/page/page.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-comment></gr-comment>
- </template>
-</test-fixture>
-
-<test-fixture id="draft">
- <template>
- <gr-comment draft="true"></gr-comment>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-comment.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const basicFixture = fixtureFromElement('gr-comment');
+
+const draftFixture = fixtureFromTemplate(html`
+<gr-comment draft="true"></gr-comment>
+`);
+
function isVisible(el) {
assert.ok(el);
return getComputedStyle(el).getPropertyValue('display') !== 'none';
@@ -49,12 +33,14 @@
suite('gr-comment tests', () => {
suite('basic tests', () => {
let element;
- let sandbox;
+
+ let openOverlaySpy;
+
setup(() => {
stub('gr-rest-api-interface', {
getAccount() { return Promise.resolve(null); },
});
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.comment = {
author: {
name: 'Mr. Peanutbutter',
@@ -65,11 +51,14 @@
message: 'is this a crossover episode!?',
updated: '2015-12-08 19:48:33.843000000',
};
- sandbox = sinon.sandbox.create();
+
+ openOverlaySpy = sinon.spy(element, '_openOverlay');
});
teardown(() => {
- sandbox.restore();
+ openOverlaySpy.getCalls().forEach(call => {
+ call.args[0].remove();
+ });
});
test('collapsible comments', () => {
@@ -119,8 +108,8 @@
});
test('message is not retrieved from storage when other edits', done => {
- const storageStub = sandbox.stub(element.$.storage, 'getDraftComment');
- const loadSpy = sandbox.spy(element, '_loadLocalDraft');
+ const storageStub = sinon.stub(element.$.storage, 'getDraftComment');
+ const loadSpy = sinon.spy(element, '_loadLocalDraft');
element.changeNum = 1;
element.patchNum = 1;
@@ -140,8 +129,8 @@
});
test('message is retrieved from storage when no other edits', done => {
- const storageStub = sandbox.stub(element.$.storage, 'getDraftComment');
- const loadSpy = sandbox.spy(element, '_loadLocalDraft');
+ const storageStub = sinon.stub(element.$.storage, 'getDraftComment');
+ const loadSpy = sinon.spy(element, '_loadLocalDraft');
element.changeNum = 1;
element.patchNum = 1;
@@ -198,8 +187,8 @@
setup(() => {
element.editing = true;
element._messageText = 'test';
- sandbox.stub(element, '_handleCancel');
- sandbox.stub(element, '_handleSave');
+ sinon.stub(element, '_handleCancel');
+ sinon.stub(element, '_handleSave');
flushAsynchronousOperations();
});
@@ -275,9 +264,9 @@
});
test('delete comment', done => {
- sandbox.stub(
+ sinon.stub(
element.$.restAPI, 'deleteComment').returns(Promise.resolve({}));
- sandbox.spy(element.confirmDeleteOverlay, 'open');
+ sinon.spy(element.confirmDeleteOverlay, 'open');
element.changeNum = 42;
element.patchNum = 0xDEADBEEF;
element._isAdmin = true;
@@ -307,12 +296,12 @@
setup(() => {
mockEvent = {preventDefault() {}};
- sandbox.stub(element, 'save')
+ sinon.stub(element, 'save')
.returns(Promise.resolve({}));
- sandbox.stub(element, '_discardDraft')
+ sinon.stub(element, '_discardDraft')
.returns(Promise.resolve({}));
endStub = sinon.stub();
- getTimerStub = sandbox.stub(element.reporting, 'getTimer')
+ getTimerStub = sinon.stub(element.reporting, 'getTimer')
.returns({end: endStub});
});
@@ -336,7 +325,7 @@
test('discard', () => {
element.comment = {id: 'abc_123'};
- sandbox.stub(element, '_closeConfirmDiscardOverlay');
+ sinon.stub(element, '_closeConfirmDiscardOverlay');
return element._handleConfirmDiscard(mockEvent).then(() => {
assert.isTrue(endStub.calledOnce);
assert.isTrue(getTimerStub.calledOnce);
@@ -346,7 +335,7 @@
});
test('edit reports interaction', () => {
- const reportStub = sandbox.stub(element.reporting,
+ const reportStub = sinon.stub(element.reporting,
'recordDraftInteraction');
element.draft = true;
flushAsynchronousOperations();
@@ -356,7 +345,7 @@
});
test('discard reports interaction', () => {
- const reportStub = sandbox.stub(element.reporting,
+ const reportStub = sinon.stub(element.reporting,
'recordDraftInteraction');
element.draft = true;
flushAsynchronousOperations();
@@ -368,7 +357,6 @@
suite('gr-comment draft tests', () => {
let element;
- let sandbox;
setup(() => {
stub('gr-rest-api-interface', {
@@ -397,7 +385,7 @@
stub('gr-storage', {
getDraftComment() { return null; },
});
- element = fixture('draft');
+ element = draftFixture.instantiate();
element.changeNum = 42;
element.patchNum = 1;
element.editing = false;
@@ -409,11 +397,6 @@
line: 5,
};
element.commentSide = 'right';
- sandbox = sinon.sandbox.create();
- });
-
- teardown(() => {
- sandbox.restore();
});
test('button visibility states', () => {
@@ -668,7 +651,7 @@
assert.isTrue(element.editing);
element._messageText = '';
- const eraseMessageDraftSpy = sandbox.spy(element, '_eraseDraftComment');
+ const eraseMessageDraftSpy = sinon.spy(element, '_eraseDraftComment');
// Save should be disabled on an empty message.
let disabled = element.shadowRoot
@@ -701,8 +684,8 @@
test('draft discard removes message from storage', done => {
element._messageText = '';
- const eraseMessageDraftSpy = sandbox.spy(element, '_eraseDraftComment');
- sandbox.stub(element, '_closeConfirmDiscardOverlay');
+ const eraseMessageDraftSpy = sinon.spy(element, '_eraseDraftComment');
+ sinon.stub(element, '_closeConfirmDiscardOverlay');
element.addEventListener('comment-discard', e => {
assert.isTrue(eraseMessageDraftSpy.called);
@@ -713,11 +696,11 @@
test('storage is cleared only after save success', () => {
element._messageText = 'test';
- const eraseStub = sandbox.stub(element, '_eraseDraftComment');
- sandbox.stub(element.$.restAPI, 'getResponseObject')
+ const eraseStub = sinon.stub(element, '_eraseDraftComment');
+ sinon.stub(element.$.restAPI, 'getResponseObject')
.returns(Promise.resolve({}));
- sandbox.stub(element, '_saveDraft').returns(Promise.resolve({ok: false}));
+ sinon.stub(element, '_saveDraft').returns(Promise.resolve({ok: false}));
const savePromise = element.save();
assert.isFalse(eraseStub.called);
@@ -725,7 +708,7 @@
assert.isFalse(eraseStub.called);
element._saveDraft.restore();
- sandbox.stub(element, '_saveDraft')
+ sinon.stub(element, '_saveDraft')
.returns(Promise.resolve({ok: true}));
return element.save().then(() => {
assert.isTrue(eraseStub.called);
@@ -754,8 +737,8 @@
let mockEvent;
setup(() => {
- discardStub = sandbox.stub(element, '_discardDraft');
- overlayStub = sandbox.stub(element, '_openOverlay')
+ discardStub = sinon.stub(element, '_discardDraft');
+ overlayStub = sinon.stub(element, '_openOverlay')
.returns(Promise.resolve());
mockEvent = {preventDefault: sinon.stub()};
});
@@ -776,7 +759,7 @@
});
test('ctrl+s saves comment', done => {
- const stub = sinon.stub(element, 'save', () => {
+ const stub = sinon.stub(element, 'save').callsFake(() => {
assert.isTrue(stub.called);
stub.restore();
done();
@@ -792,7 +775,7 @@
test('draft saving/editing', done => {
const dispatchEventStub = sinon.stub(element, 'dispatchEvent');
- const cancelDebounce = sandbox.stub(element, 'cancelDebouncer');
+ const cancelDebounce = sinon.stub(element, 'cancelDebouncer');
element.draft = true;
flushAsynchronousOperations();
@@ -858,7 +841,7 @@
});
test('draft prevent save when disabled', () => {
- const saveStub = sandbox.stub(element, 'save').returns(Promise.resolve());
+ const saveStub = sinon.stub(element, 'save').returns(Promise.resolve());
element.showActions = true;
element.draft = true;
flushAsynchronousOperations();
@@ -881,7 +864,7 @@
});
test('proper event fires on resolve, comment is not saved', done => {
- const save = sandbox.stub(element, 'save');
+ const save = sinon.stub(element, 'save');
element.addEventListener('comment-update', e => {
assert.isTrue(e.detail.comment.unresolved);
assert.isFalse(save.called);
@@ -892,7 +875,7 @@
});
test('resolved comment state indicated by checkbox', () => {
- sandbox.stub(element, 'save');
+ sinon.stub(element, 'save');
element.comment = {unresolved: false};
assert.isTrue(element.shadowRoot
.querySelector('.resolve input').checked);
@@ -903,7 +886,7 @@
test('resolved checkbox saves with tap when !editing', () => {
element.editing = false;
- const save = sandbox.stub(element, 'save');
+ const save = sinon.stub(element, 'save');
element.comment = {unresolved: false};
assert.isTrue(element.shadowRoot
@@ -927,7 +910,7 @@
});
test('_show{Start,End}Request', () => {
- const updateStub = sandbox.stub(element, '_updateRequestToast');
+ const updateStub = sinon.stub(element, '_updateRequestToast');
element._numPendingDraftRequests.number = 1;
element._showStartRequest();
@@ -948,9 +931,9 @@
});
test('cancelling an unsaved draft discards, persists in storage', () => {
- const discardSpy = sandbox.spy(element, '_fireDiscard');
- const storeStub = sandbox.stub(element.$.storage, 'setDraftComment');
- const eraseStub = sandbox.stub(element.$.storage, 'eraseDraftComment');
+ const discardSpy = sinon.spy(element, '_fireDiscard');
+ const storeStub = sinon.stub(element.$.storage, 'setDraftComment');
+ const eraseStub = sinon.stub(element.$.storage, 'eraseDraftComment');
element._messageText = 'test text';
flushAsynchronousOperations();
element.flushDebouncer('store');
@@ -964,8 +947,8 @@
test('cancelling edit on a saved draft does not store', () => {
element.comment.id = 'foo';
- const discardSpy = sandbox.spy(element, '_fireDiscard');
- const storeStub = sandbox.stub(element.$.storage, 'setDraftComment');
+ const discardSpy = sinon.spy(element, '_fireDiscard');
+ const storeStub = sinon.stub(element.$.storage, 'setDraftComment');
element._messageText = 'test text';
flushAsynchronousOperations();
element.flushDebouncer('store');
@@ -978,7 +961,7 @@
test('deleting text from saved draft and saving deletes the draft', () => {
element.comment = {id: 'foo', message: 'test'};
element._messageText = '';
- const discardStub = sandbox.stub(element, '_discardDraft');
+ const discardStub = sinon.stub(element, '_discardDraft');
element.save();
assert.isTrue(discardStub.called);
@@ -1150,19 +1133,18 @@
suite('respectful tips', () => {
let element;
- let sandbox;
+
let clock;
setup(() => {
stub('gr-rest-api-interface', {
getAccount() { return Promise.resolve(null); },
});
clock = sinon.useFakeTimers();
- sandbox = sinon.sandbox.create();
});
teardown(() => {
clock.restore();
- sandbox.restore();
+ sinon.restore();
});
test('show tip when no cached record', done => {
@@ -1174,7 +1156,7 @@
setRespectfulTipVisibility() { return respectfulSetStub(); },
});
respectfulGetStub.returns(null);
- element = fixture('draft');
+ element = draftFixture.instantiate();
// fake random
element.getRandomNum = () => 0;
element.comment = {__editing: true};
@@ -1197,7 +1179,7 @@
setRespectfulTipVisibility(days) { return respectfulSetStub(days); },
});
respectfulGetStub.returns(null);
- element = fixture('draft');
+ element = draftFixture.instantiate();
// fake random
element.getRandomNum = () => 0;
element.comment = {__editing: true};
@@ -1226,7 +1208,7 @@
setRespectfulTipVisibility() { return respectfulSetStub(); },
});
respectfulGetStub.returns(null);
- element = fixture('draft');
+ element = draftFixture.instantiate();
// fake random
element.getRandomNum = () => 3;
element.comment = {__editing: true};
@@ -1249,7 +1231,7 @@
setRespectfulTipVisibility() { return respectfulSetStub(); },
});
respectfulGetStub.returns(null);
- element = fixture('draft');
+ element = draftFixture.instantiate();
// fake random
element.getRandomNum = () => 0;
element.comment = {__editing: false};
@@ -1281,7 +1263,7 @@
setRespectfulTipVisibility() { return respectfulSetStub(); },
});
respectfulGetStub.returns({});
- element = fixture('draft');
+ element = draftFixture.instantiate();
// fake random
element.getRandomNum = () => 0;
element.comment = {__editing: true};
@@ -1296,4 +1278,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard_test.html b/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard_test.js
similarity index 60%
rename from polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard_test.html
rename to polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard_test.js
index 398f7f0..58c00da 100644
--- a/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard_test.js
@@ -1,59 +1,39 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-copy-clipboard</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-copy-clipboard></gr-copy-clipboard>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-copy-clipboard.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+
+const basicFixture = fixtureFromElement('gr-copy-clipboard');
+
suite('gr-copy-clipboard tests', () => {
let element;
- let sandbox;
setup(done => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.text = `git fetch http://gerrit@localhost:8080/a/test-project
refs/changes/05/5/1 && git checkout FETCH_HEAD`;
flushAsynchronousOperations();
flush(done);
});
- teardown(() => {
- sandbox.restore();
- });
-
test('copy to clipboard', () => {
- const clipboardSpy = sandbox.spy(element, '_copyToClipboard');
+ const clipboardSpy = sinon.spy(element, '_copyToClipboard');
const copyBtn = element.shadowRoot
.querySelector('.copyToClipboard');
MockInteractions.tap(copyBtn);
@@ -102,4 +82,4 @@
assert.isFalse(clickStub.called);
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-count-string-formatter/gr-count-string-formatter_test.html b/polygerrit-ui/app/elements/shared/gr-count-string-formatter/gr-count-string-formatter_test.html
deleted file mode 100644
index 63435d2..0000000
--- a/polygerrit-ui/app/elements/shared/gr-count-string-formatter/gr-count-string-formatter_test.html
+++ /dev/null
@@ -1,58 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-count-string-formatter</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<script type="module">
-import '../../../test/common-test-setup.js';
-import {GrCountStringFormatter} from './gr-count-string-formatter.js';
-
-suite('gr-count-string-formatter tests', () => {
- test('computeString', () => {
- const noun = 'unresolved';
- assert.equal(GrCountStringFormatter.computeString(0, noun), '');
- assert.equal(GrCountStringFormatter.computeString(1, noun),
- '1 unresolved');
- assert.equal(GrCountStringFormatter.computeString(2, noun),
- '2 unresolved');
- });
-
- test('computeShortString', () => {
- const noun = 'c';
- assert.equal(GrCountStringFormatter.computeShortString(0, noun), '');
- assert.equal(GrCountStringFormatter.computeShortString(1, noun), '1c');
- assert.equal(GrCountStringFormatter.computeShortString(2, noun), '2c');
- });
-
- test('computePluralString', () => {
- const noun = 'comment';
- assert.equal(GrCountStringFormatter.computePluralString(0, noun), '');
- assert.equal(GrCountStringFormatter.computePluralString(1, noun),
- '1 comment');
- assert.equal(GrCountStringFormatter.computePluralString(2, noun),
- '2 comments');
- });
-});
-</script>
-
diff --git a/polygerrit-ui/app/elements/shared/gr-count-string-formatter/gr-count-string-formatter_test.js b/polygerrit-ui/app/elements/shared/gr-count-string-formatter/gr-count-string-formatter_test.js
new file mode 100644
index 0000000..36637ec
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-count-string-formatter/gr-count-string-formatter_test.js
@@ -0,0 +1,47 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import {GrCountStringFormatter} from './gr-count-string-formatter.js';
+
+suite('gr-count-string-formatter tests', () => {
+ test('computeString', () => {
+ const noun = 'unresolved';
+ assert.equal(GrCountStringFormatter.computeString(0, noun), '');
+ assert.equal(GrCountStringFormatter.computeString(1, noun),
+ '1 unresolved');
+ assert.equal(GrCountStringFormatter.computeString(2, noun),
+ '2 unresolved');
+ });
+
+ test('computeShortString', () => {
+ const noun = 'c';
+ assert.equal(GrCountStringFormatter.computeShortString(0, noun), '');
+ assert.equal(GrCountStringFormatter.computeShortString(1, noun), '1c');
+ assert.equal(GrCountStringFormatter.computeShortString(2, noun), '2c');
+ });
+
+ test('computePluralString', () => {
+ const noun = 'comment';
+ assert.equal(GrCountStringFormatter.computePluralString(0, noun), '');
+ assert.equal(GrCountStringFormatter.computePluralString(1, noun),
+ '1 comment');
+ assert.equal(GrCountStringFormatter.computePluralString(2, noun),
+ '2 comments');
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/shared/gr-cursor-manager/gr-cursor-manager.js b/polygerrit-ui/app/elements/shared/gr-cursor-manager/gr-cursor-manager.js
index 647f41b..de9dcc2 100644
--- a/polygerrit-ui/app/elements/shared/gr-cursor-manager/gr-cursor-manager.js
+++ b/polygerrit-ui/app/elements/shared/gr-cursor-manager/gr-cursor-manager.js
@@ -20,6 +20,9 @@
import {htmlTemplate} from './gr-cursor-manager_html.js';
import {ScrollMode} from '../../../constants/constants.js';
+// Time in which pressing n key again after the toast navigates to next file
+const NAVIGATE_TO_NEXT_FILE_TIMEOUT_MS = 5000;
+
/** @extends PolymerElement */
class GrCursorManager extends GestureEventListeners(
LegacyElementMixin(
@@ -119,11 +122,15 @@
* sometimes different, used by the diff cursor.
* @param {boolean=} opt_clipToTop When none of the next indices match, move
* back to first instead of to last.
+ * @param {boolean=} opt_navigateToNextFile Navigate to next unreviewed file
+ * if user presses next on the last diff chunk
* @private
*/
- next(opt_condition, opt_getTargetHeight, opt_clipToTop) {
- this._moveCursor(1, opt_condition, opt_getTargetHeight, opt_clipToTop);
+ next(opt_condition, opt_getTargetHeight, opt_clipToTop,
+ opt_navigateToNextFile) {
+ this._moveCursor(1, opt_condition, opt_getTargetHeight, opt_clipToTop,
+ opt_navigateToNextFile);
}
previous(opt_condition) {
@@ -265,9 +272,12 @@
* sometimes different, used by the diff cursor.
* @param {boolean=} opt_clipToTop When none of the next indices match, move
* back to first instead of to last.
+ * @param {boolean=} opt_navigateToNextFile Navigate to next unreviewed file
+ * if user presses next on the last diff chunk
* @private
*/
- _moveCursor(delta, opt_condition, opt_getTargetHeight, opt_clipToTop) {
+ _moveCursor(delta, opt_condition, opt_getTargetHeight, opt_clipToTop,
+ opt_navigateToNextFile) {
if (!this.stops.length) {
this.unsetCursor();
return;
@@ -282,6 +292,35 @@
newTarget = this.stops[newIndex];
}
+ /*
+ * If user presses n on the last diff chunk, show a toast informing user
+ * that pressing n again will navigate them to next unreviewed file.
+ * If click happens within the time limit, then navigate to next file
+ */
+ if (opt_navigateToNextFile && this.index === newIndex) {
+ if (newIndex === this.stops.length - 1) {
+ if (this._lastDisplayedNavigateToNextFileToast && (Date.now() -
+ this._lastDisplayedNavigateToNextFileToast <=
+ NAVIGATE_TO_NEXT_FILE_TIMEOUT_MS)) {
+ // reset for next file
+ this._lastDisplayedNavigateToNextFileToast = null;
+ this.dispatchEvent(new CustomEvent(
+ 'navigate-to-next-unreviewed-file', {
+ composed: true, bubbles: true,
+ }));
+ return;
+ }
+ this._lastDisplayedNavigateToNextFileToast = Date.now();
+ this.dispatchEvent(new CustomEvent('show-alert', {
+ detail: {
+ message: 'Press n again to navigate to next unreviewed file',
+ },
+ composed: true, bubbles: true,
+ }));
+ return;
+ }
+ }
+
this.index = newIndex;
this.target = newTarget;
diff --git a/polygerrit-ui/app/elements/shared/gr-cursor-manager/gr-cursor-manager_test.js b/polygerrit-ui/app/elements/shared/gr-cursor-manager/gr-cursor-manager_test.js
index 561746a..bc07d84 100644
--- a/polygerrit-ui/app/elements/shared/gr-cursor-manager/gr-cursor-manager_test.js
+++ b/polygerrit-ui/app/elements/shared/gr-cursor-manager/gr-cursor-manager_test.js
@@ -30,21 +30,15 @@
`);
suite('gr-cursor-manager tests', () => {
- let sandbox;
let element;
let list;
setup(() => {
- sandbox = sinon.sandbox.create();
const fixtureElements = basicTestFixutre.instantiate();
element = fixtureElements[0];
list = fixtureElements[1];
});
- teardown(() => {
- sandbox.restore();
- });
-
test('core cursor functionality', () => {
// The element is initialized into the proper state.
assert.isArray(element.stops);
@@ -164,8 +158,8 @@
});
test('opt_noScroll', () => {
- sandbox.stub(element, '_targetIsVisible', () => false);
- const scrollStub = sandbox.stub(window, 'scrollTo');
+ sinon.stub(element, '_targetIsVisible').callsFake(() => false);
+ const scrollStub = sinon.stub(window, 'scrollTo');
element.stops = list.querySelectorAll('li');
element.scrollMode = 'keep-visible';
@@ -207,7 +201,7 @@
test('focusOnMove prop', () => {
const listEls = list.querySelectorAll('li');
for (let i = 0; i < listEls.length; i++) {
- sandbox.spy(listEls[i], 'focus');
+ sinon.spy(listEls[i], 'focus');
}
element.stops = listEls;
element.setCursor(list.children[0]);
@@ -230,32 +224,32 @@
// There is a target which has a targetNext
element.setCursor(list.children[0]);
element._moveCursor(1);
- scrollStub = sandbox.stub(window, 'scrollTo');
+ scrollStub = sinon.stub(window, 'scrollTo');
window.innerHeight = 60;
});
test('Called when top and bottom not visible', () => {
- sandbox.stub(element, '_targetIsVisible').returns(false);
+ sinon.stub(element, '_targetIsVisible').returns(false);
element._scrollToTarget();
assert.isTrue(scrollStub.called);
});
test('Not called when top and bottom visible', () => {
- sandbox.stub(element, '_targetIsVisible').returns(true);
+ sinon.stub(element, '_targetIsVisible').returns(true);
element._scrollToTarget();
assert.isFalse(scrollStub.called);
});
test('Called when top is visible, bottom is not, scroll is lower', () => {
- const visibleStub = sandbox.stub(element, '_targetIsVisible',
+ const visibleStub = sinon.stub(element, '_targetIsVisible').callsFake(
() => visibleStub.callCount === 2);
- sandbox.stub(element, '_getWindowDims').returns({
+ sinon.stub(element, '_getWindowDims').returns({
scrollX: 123,
scrollY: 15,
innerHeight: 1000,
pageYOffset: 0,
});
- sandbox.stub(element, '_calculateScrollToValue').returns(20);
+ sinon.stub(element, '_calculateScrollToValue').returns(20);
element._scrollToTarget();
assert.isTrue(scrollStub.called);
assert.isTrue(scrollStub.calledWithExactly(123, 20));
@@ -263,22 +257,22 @@
});
test('Called when top is visible, bottom not, scroll is higher', () => {
- const visibleStub = sandbox.stub(element, '_targetIsVisible',
+ const visibleStub = sinon.stub(element, '_targetIsVisible').callsFake(
() => visibleStub.callCount === 2);
- sandbox.stub(element, '_getWindowDims').returns({
+ sinon.stub(element, '_getWindowDims').returns({
scrollX: 123,
scrollY: 25,
innerHeight: 1000,
pageYOffset: 0,
});
- sandbox.stub(element, '_calculateScrollToValue').returns(20);
+ sinon.stub(element, '_calculateScrollToValue').returns(20);
element._scrollToTarget();
assert.isFalse(scrollStub.called);
assert.equal(visibleStub.callCount, 2);
});
test('_calculateScrollToValue', () => {
- sandbox.stub(element, '_getWindowDims').returns({
+ sinon.stub(element, '_getWindowDims').returns({
scrollX: 123,
scrollY: 25,
innerHeight: 300,
diff --git a/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter.js b/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter.js
index 5335ede..40aa808 100644
--- a/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter.js
+++ b/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter.js
@@ -224,7 +224,7 @@
dateStr,
timeFormat,
dateFormat,
- ].some(arg => arg === undefined)) {
+ ].includes(undefined)) {
return undefined;
}
diff --git a/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter_test.html b/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter_test.js
similarity index 80%
rename from polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter_test.html
rename to polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter_test.js
index 589a157..804c3b7 100644
--- a/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter_test.js
@@ -1,50 +1,34 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2015 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-date-formatter</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-date-formatter date-str="2015-09-24 23:30:17.033000000"></gr-date-formatter>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-date-formatter.js';
import {parseDate} from '../../../utils/date-util.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const basicFixture = fixtureFromTemplate(html`
+<gr-date-formatter date-str="2015-09-24 23:30:17.033000000"></gr-date-formatter>
+`);
+
suite('gr-date-formatter tests', () => {
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
- });
- teardown(() => {
- sandbox.restore();
});
/**
@@ -63,7 +47,7 @@
.toJSON()
.replace('T', ' ')
.slice(0, -1);
- sandbox.useFakeTimers(normalizedDate(nowStr).getTime());
+ sinon.useFakeTimers(normalizedDate(nowStr).getTime());
element.dateStr = dateStr;
flush(() => {
const span = element.shadowRoot
@@ -93,8 +77,8 @@
date_format: 'STD',
relative_date_in_change_table: false,
}).then(() => {
- element = fixture('basic');
- sandbox.stub(element, '_getUtcOffsetString').returns('');
+ element = basicFixture.instantiate();
+ sinon.stub(element, '_getUtcOffsetString').returns('');
return element._loadPreferences();
}));
@@ -142,8 +126,8 @@
date_format: 'US',
relative_date_in_change_table: false,
}).then(() => {
- element = fixture('basic');
- sandbox.stub(element, '_getUtcOffsetString').returns('');
+ element = basicFixture.instantiate();
+ sinon.stub(element, '_getUtcOffsetString').returns('');
return element._loadPreferences();
}));
@@ -178,8 +162,8 @@
date_format: 'ISO',
relative_date_in_change_table: false,
}).then(() => {
- element = fixture('basic');
- sandbox.stub(element, '_getUtcOffsetString').returns('');
+ element = basicFixture.instantiate();
+ sinon.stub(element, '_getUtcOffsetString').returns('');
return element._loadPreferences();
}));
@@ -214,8 +198,8 @@
date_format: 'EURO',
relative_date_in_change_table: false,
}).then(() => {
- element = fixture('basic');
- sandbox.stub(element, '_getUtcOffsetString').returns('');
+ element = basicFixture.instantiate();
+ sinon.stub(element, '_getUtcOffsetString').returns('');
return element._loadPreferences();
}));
@@ -250,8 +234,8 @@
date_format: 'UK',
relative_date_in_change_table: false,
}).then(() => {
- element = fixture('basic');
- sandbox.stub(element, '_getUtcOffsetString').returns('');
+ element = basicFixture.instantiate();
+ sinon.stub(element, '_getUtcOffsetString').returns('');
return element._loadPreferences();
}));
@@ -286,8 +270,8 @@
stubRestAPI(
{time_format: 'HHMM_12', date_format: 'STD'}
).then(() => {
- element = fixture('basic');
- sandbox.stub(element, '_getUtcOffsetString').returns('');
+ element = basicFixture.instantiate();
+ sinon.stub(element, '_getUtcOffsetString').returns('');
return element._loadPreferences();
})
);
@@ -307,8 +291,8 @@
stubRestAPI(
{time_format: 'HHMM_12', date_format: 'US'}
).then(() => {
- element = fixture('basic');
- sandbox.stub(element, '_getUtcOffsetString').returns('');
+ element = basicFixture.instantiate();
+ sinon.stub(element, '_getUtcOffsetString').returns('');
return element._loadPreferences();
})
);
@@ -328,8 +312,8 @@
stubRestAPI(
{time_format: 'HHMM_12', date_format: 'ISO'}
).then(() => {
- element = fixture('basic');
- sandbox.stub(element, '_getUtcOffsetString').returns('');
+ element = basicFixture.instantiate();
+ sinon.stub(element, '_getUtcOffsetString').returns('');
return element._loadPreferences();
})
);
@@ -349,8 +333,8 @@
stubRestAPI(
{time_format: 'HHMM_12', date_format: 'EURO'}
).then(() => {
- element = fixture('basic');
- sandbox.stub(element, '_getUtcOffsetString').returns('');
+ element = basicFixture.instantiate();
+ sinon.stub(element, '_getUtcOffsetString').returns('');
return element._loadPreferences();
})
);
@@ -370,8 +354,8 @@
stubRestAPI(
{time_format: 'HHMM_12', date_format: 'UK'}
).then(() => {
- element = fixture('basic');
- sandbox.stub(element, '_getUtcOffsetString').returns('');
+ element = basicFixture.instantiate();
+ sinon.stub(element, '_getUtcOffsetString').returns('');
return element._loadPreferences();
})
);
@@ -391,8 +375,8 @@
date_format: 'STD',
relative_date_in_change_table: true,
}).then(() => {
- element = fixture('basic');
- sandbox.stub(element, '_getUtcOffsetString').returns('');
+ element = basicFixture.instantiate();
+ sinon.stub(element, '_getUtcOffsetString').returns('');
return element._loadPreferences();
}));
@@ -419,7 +403,7 @@
date_format: 'US',
relative_date_in_change_table: true,
}).then(() => {
- element = fixture('basic');
+ element = basicFixture.instantiate();
return element._loadPreferences();
}));
@@ -433,7 +417,7 @@
suite('logged out', () => {
setup(() => stubRestAPI(null).then(() => {
- element = fixture('basic');
+ element = basicFixture.instantiate();
return element._loadPreferences();
}));
@@ -445,4 +429,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-dialog/gr-dialog_test.html b/polygerrit-ui/app/elements/shared/gr-dialog/gr-dialog_test.html
deleted file mode 100644
index 1060e82..0000000
--- a/polygerrit-ui/app/elements/shared/gr-dialog/gr-dialog_test.html
+++ /dev/null
@@ -1,111 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-dialog</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-dialog></gr-dialog>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-dialog.js';
-import {isHidden} from '../../../test/test-utils.js';
-suite('gr-dialog tests', () => {
- let element;
- let sandbox;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- });
-
- teardown(() => { sandbox.restore(); });
-
- test('events', done => {
- let numEvents = 0;
- function handler() { if (++numEvents == 2) { done(); } }
-
- element.addEventListener('confirm', handler);
- element.addEventListener('cancel', handler);
-
- MockInteractions.tap(element.shadowRoot
- .querySelector('gr-button[primary]'));
- MockInteractions.tap(element.shadowRoot
- .querySelector('gr-button:not([primary])'));
- });
-
- test('confirmOnEnter', () => {
- element.confirmOnEnter = false;
- const handleConfirmStub = sandbox.stub(element, '_handleConfirm');
- const handleKeydownSpy = sandbox.spy(element, '_handleKeydown');
- MockInteractions.pressAndReleaseKeyOn(element.shadowRoot
- .querySelector('main'),
- 13, null, 'enter');
- flushAsynchronousOperations();
-
- assert.isTrue(handleKeydownSpy.called);
- assert.isFalse(handleConfirmStub.called);
-
- element.confirmOnEnter = true;
- MockInteractions.pressAndReleaseKeyOn(element.shadowRoot
- .querySelector('main'),
- 13, null, 'enter');
- flushAsynchronousOperations();
-
- assert.isTrue(handleConfirmStub.called);
- });
-
- test('resetFocus', () => {
- const focusStub = sandbox.stub(element.$.confirm, 'focus');
- element.resetFocus();
- assert.isTrue(focusStub.calledOnce);
- });
-
- suite('tooltip', () => {
- test('tooltip not added by default', () => {
- assert.isNull(element.$.confirm.getAttribute('has-tooltip'));
- });
-
- test('tooltip added if confirm tooltip is passed', done => {
- element.confirmTooltip = 'confirm tooltip';
- flush(() => {
- assert(element.$.confirm.getAttribute('has-tooltip'));
- done();
- });
- });
- });
-
- test('empty cancel label hides cancel btn', () => {
- assert.isFalse(isHidden(element.$.cancel));
- element.cancelLabel = '';
- flushAsynchronousOperations();
-
- assert.isTrue(isHidden(element.$.cancel));
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-dialog/gr-dialog_test.js b/polygerrit-ui/app/elements/shared/gr-dialog/gr-dialog_test.js
new file mode 100644
index 0000000..ce36d7b
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-dialog/gr-dialog_test.js
@@ -0,0 +1,93 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-dialog.js';
+import {isHidden} from '../../../test/test-utils.js';
+
+const basicFixture = fixtureFromElement('gr-dialog');
+
+suite('gr-dialog tests', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ test('events', done => {
+ let numEvents = 0;
+ function handler() { if (++numEvents == 2) { done(); } }
+
+ element.addEventListener('confirm', handler);
+ element.addEventListener('cancel', handler);
+
+ MockInteractions.tap(element.shadowRoot
+ .querySelector('gr-button[primary]'));
+ MockInteractions.tap(element.shadowRoot
+ .querySelector('gr-button:not([primary])'));
+ });
+
+ test('confirmOnEnter', () => {
+ element.confirmOnEnter = false;
+ const handleConfirmStub = sinon.stub(element, '_handleConfirm');
+ const handleKeydownSpy = sinon.spy(element, '_handleKeydown');
+ MockInteractions.pressAndReleaseKeyOn(element.shadowRoot
+ .querySelector('main'),
+ 13, null, 'enter');
+ flushAsynchronousOperations();
+
+ assert.isTrue(handleKeydownSpy.called);
+ assert.isFalse(handleConfirmStub.called);
+
+ element.confirmOnEnter = true;
+ MockInteractions.pressAndReleaseKeyOn(element.shadowRoot
+ .querySelector('main'),
+ 13, null, 'enter');
+ flushAsynchronousOperations();
+
+ assert.isTrue(handleConfirmStub.called);
+ });
+
+ test('resetFocus', () => {
+ const focusStub = sinon.stub(element.$.confirm, 'focus');
+ element.resetFocus();
+ assert.isTrue(focusStub.calledOnce);
+ });
+
+ suite('tooltip', () => {
+ test('tooltip not added by default', () => {
+ assert.isNull(element.$.confirm.getAttribute('has-tooltip'));
+ });
+
+ test('tooltip added if confirm tooltip is passed', done => {
+ element.confirmTooltip = 'confirm tooltip';
+ flush(() => {
+ assert(element.$.confirm.getAttribute('has-tooltip'));
+ done();
+ });
+ });
+ });
+
+ test('empty cancel label hides cancel btn', () => {
+ assert.isFalse(isHidden(element.$.cancel));
+ element.cancelLabel = '';
+ flushAsynchronousOperations();
+
+ assert.isTrue(isHidden(element.$.cancel));
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/shared/gr-diff-preferences/gr-diff-preferences_test.html b/polygerrit-ui/app/elements/shared/gr-diff-preferences/gr-diff-preferences_test.js
similarity index 67%
rename from polygerrit-ui/app/elements/shared/gr-diff-preferences/gr-diff-preferences_test.html
rename to polygerrit-ui/app/elements/shared/gr-diff-preferences/gr-diff-preferences_test.js
index 2750d67..ced8c6c 100644
--- a/polygerrit-ui/app/elements/shared/gr-diff-preferences/gr-diff-preferences_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-diff-preferences/gr-diff-preferences_test.js
@@ -1,42 +1,28 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-diff-preferences</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-diff-preferences></gr-diff-preferences>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-diff-preferences.js';
+
+const basicFixture = fixtureFromElement('gr-diff-preferences');
+
suite('gr-diff-preferences tests', () => {
let element;
- let sandbox;
+
let diffPreferences;
function valueOf(title, fieldsetid) {
@@ -70,13 +56,11 @@
},
});
- element = fixture('basic');
- sandbox = sinon.sandbox.create();
+ element = basicFixture.instantiate();
+
return element.loadData();
});
- teardown(() => { sandbox.restore(); });
-
test('renders', () => {
// Rendered with the expected preferences selected.
assert.equal(valueOf('Context', 'diffPreferences')
@@ -105,7 +89,7 @@
});
test('save changes', () => {
- sandbox.stub(element.$.restAPI, 'saveDiffPreferences')
+ sinon.stub(element.$.restAPI, 'saveDiffPreferences')
.returns(Promise.resolve());
const showTrailingWhitespaceCheckbox =
valueOf('Show trailing whitespace', 'diffPreferences')
@@ -121,4 +105,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-download-commands/gr-download-commands_test.html b/polygerrit-ui/app/elements/shared/gr-download-commands/gr-download-commands_test.js
similarity index 68%
rename from polygerrit-ui/app/elements/shared/gr-download-commands/gr-download-commands_test.html
rename to polygerrit-ui/app/elements/shared/gr-download-commands/gr-download-commands_test.js
index 237fbe0..0f8b97d 100644
--- a/polygerrit-ui/app/elements/shared/gr-download-commands/gr-download-commands_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-download-commands/gr-download-commands_test.js
@@ -1,43 +1,29 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-download-commands</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-download-commands></gr-download-commands>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-download-commands.js';
import {isHidden} from '../../../test/test-utils.js';
+
+const basicFixture = fixtureFromElement('gr-download-commands');
+
suite('gr-download-commands', () => {
let element;
- let sandbox;
+
const SCHEMES = ['http', 'repo', 'ssh'];
const COMMANDS = [{
title: 'Checkout',
@@ -59,16 +45,12 @@
const SELECTED_SCHEME = 'http';
setup(() => {
- sandbox = sinon.sandbox.create();
- });
- teardown(() => {
- sandbox.restore();
});
suite('unauthenticated', () => {
setup(done => {
- element = fixture('basic');
+ element = basicFixture.instantiate();
element.schemes = SCHEMES;
element.commands = COMMANDS;
element.selectedScheme = SELECTED_SCHEME;
@@ -77,7 +59,7 @@
});
test('focusOnCopy', () => {
- const focusStub = sandbox.stub(element.shadowRoot
+ const focusStub = sinon.stub(element.shadowRoot
.querySelector('gr-shell-command'),
'focusOnCopy');
element.focusOnCopy();
@@ -136,8 +118,8 @@
test('saves scheme to preferences', () => {
element._loggedIn = true;
- const savePrefsStub = sandbox.stub(element.$.restAPI, 'savePreferences',
- () => Promise.resolve());
+ const savePrefsStub = sinon.stub(element.$.restAPI, 'savePreferences')
+ .callsFake(() => Promise.resolve());
flushAsynchronousOperations();
@@ -152,4 +134,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_test.html b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_test.js
similarity index 76%
rename from polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_test.html
rename to polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_test.js
index b64d5f7..8d7de0e 100644
--- a/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_test.js
@@ -1,58 +1,39 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-dropdown-list</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-dropdown-list></gr-dropdown-list>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-dropdown-list.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+
+const basicFixture = fixtureFromElement('gr-dropdown-list');
+
suite('gr-dropdown-list tests', () => {
let element;
- let sandbox;
setup(() => {
stub('gr-rest-api-interface', {
getConfig() { return Promise.resolve({}); },
});
- element = fixture('basic');
- sandbox = sinon.sandbox.create();
- });
-
- teardown(() => {
- sandbox.restore();
+ element = basicFixture.instantiate();
});
test('tap on trigger opens menu', () => {
- sandbox.stub(element, '_open', () => { element.$.dropdown.open(); });
+ sinon.stub(element, '_open')
+ .callsFake(() => { element.$.dropdown.open(); });
assert.isFalse(element.$.dropdown.opened);
MockInteractions.tap(element.$.trigger);
assert.isTrue(element.$.dropdown.opened);
@@ -169,4 +150,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown_test.html b/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown_test.js
similarity index 74%
rename from polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown_test.html
rename to polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown_test.js
index d17cc1a..d1d9164 100644
--- a/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown_test.js
@@ -1,54 +1,34 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-dropdown</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-dropdown></gr-dropdown>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-dropdown.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+
+const basicFixture = fixtureFromElement('gr-dropdown');
+
suite('gr-dropdown tests', () => {
let element;
- let sandbox;
setup(() => {
stub('gr-rest-api-interface', {
getConfig() { return Promise.resolve({}); },
});
- element = fixture('basic');
- sandbox = sinon.sandbox.create();
- });
-
- teardown(() => {
- sandbox.restore();
+ element = basicFixture.instantiate();
});
test('_computeIsDownload', () => {
@@ -57,8 +37,10 @@
});
test('tap on trigger opens menu, then closes', () => {
- sandbox.stub(element, '_open', () => { element.$.dropdown.open(); });
- sandbox.stub(element, '_close', () => { element.$.dropdown.close(); });
+ sinon.stub(element, '_open')
+ .callsFake(() => { element.$.dropdown.open(); });
+ sinon.stub(element, '_close')
+ .callsFake(() => { element.$.dropdown.close(); });
assert.isFalse(element.$.dropdown.opened);
MockInteractions.tap(element.$.trigger);
assert.isTrue(element.$.dropdown.opened);
@@ -122,8 +104,8 @@
test('non link items', () => {
const item0 = {name: 'item one', id: 'foo'};
element.items = [item0, {name: 'item two', id: 'bar'}];
- const fooTapped = sandbox.stub();
- const tapped = sandbox.stub();
+ const fooTapped = sinon.stub();
+ const tapped = sinon.stub();
element.addEventListener('tap-item-foo', fooTapped);
element.addEventListener('tap-item', tapped);
flushAsynchronousOperations();
@@ -138,8 +120,8 @@
element.items = [{name: 'item one', id: 'foo'}];
element.disabledIds = ['foo'];
- const stub = sandbox.stub();
- const tapped = sandbox.stub();
+ const stub = sinon.stub();
+ const tapped = sinon.stub();
element.addEventListener('tap-item-foo', stub);
element.addEventListener('tap-item', tapped);
flushAsynchronousOperations();
@@ -174,7 +156,7 @@
});
test('down', () => {
- const stub = sandbox.stub(element.$.cursor, 'next');
+ const stub = sinon.stub(element.$.cursor, 'next');
assert.isFalse(element.$.dropdown.opened);
MockInteractions.pressAndReleaseKeyOn(element, 40);
assert.isTrue(element.$.dropdown.opened);
@@ -183,7 +165,7 @@
});
test('up', () => {
- const stub = sandbox.stub(element.$.cursor, 'previous');
+ const stub = sinon.stub(element.$.cursor, 'previous');
assert.isFalse(element.$.dropdown.opened);
MockInteractions.pressAndReleaseKeyOn(element, 38);
assert.isTrue(element.$.dropdown.opened);
@@ -199,10 +181,10 @@
assert.isTrue(element.$.dropdown.opened);
const el = element.$.cursor.target.querySelector(':not([hidden]) a');
- const stub = sandbox.stub(el, 'click');
+ const stub = sinon.stub(el, 'click');
MockInteractions.pressAndReleaseKeyOn(element, 32); // Space
assert.isTrue(stub.called);
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content_test.html b/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content_test.html
deleted file mode 100644
index c50920e..0000000
--- a/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content_test.html
+++ /dev/null
@@ -1,166 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-editable-content</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<!-- Can't use absolute path below for mock-interaction.js.
-Web component tester(wct) has a built-in http server and it serves "/components" directory (which is
-actually /node_modules directory). Also, wct patches some files to load modules from /components.
-With the absolute path, browser tries to load dom-module from 2 different places (/component/... and
-/node_modules/...) though this is actually the same file. This leads to a run-time error.
--->
-<script src="../../../node_modules/iron-test-helpers/mock-interactions.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-editable-content></gr-editable-content>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-editable-content.js';
-suite('gr-editable-content tests', () => {
- let element;
- let sandbox;
-
- setup(() => {
- element = fixture('basic');
- sandbox = sinon.sandbox.create();
- });
-
- teardown(() => { sandbox.restore(); });
-
- test('save event', done => {
- element.content = '';
- element._newContent = 'foo';
- element.addEventListener('editable-content-save', e => {
- assert.equal(e.detail.content, 'foo');
- done();
- });
- MockInteractions.tap(element.shadowRoot
- .querySelector('gr-button[primary]'));
- });
-
- test('cancel event', done => {
- element.addEventListener('editable-content-cancel', () => {
- done();
- });
- MockInteractions.tap(element.shadowRoot
- .querySelector('gr-button:not([primary])'));
- });
-
- test('enabling editing keeps old content', () => {
- element.content = 'current content';
- element._newContent = 'old content';
- element.editing = true;
- assert.equal(element._newContent, 'old content');
- });
-
- test('disabling editing does not update edit field contents', () => {
- element.content = 'current content';
- element.editing = true;
- element._newContent = 'stale content';
- element.editing = false;
- assert.equal(element._newContent, 'stale content');
- });
-
- test('zero width spaces are removed properly', () => {
- element.removeZeroWidthSpace = true;
- element.content = 'R=\u200Btest@google.com';
- element.editing = true;
- assert.equal(element._newContent, 'R=test@google.com');
- });
-
- suite('editing', () => {
- setup(() => {
- element.content = 'current content';
- element.editing = true;
- });
-
- test('save button is disabled initially', () => {
- assert.isTrue(element.shadowRoot
- .querySelector('gr-button[primary]').disabled);
- });
-
- test('save button is enabled when content changes', () => {
- element._newContent = 'new content';
- assert.isFalse(element.shadowRoot
- .querySelector('gr-button[primary]').disabled);
- });
- });
-
- suite('storageKey and related behavior', () => {
- let dispatchSpy;
- setup(() => {
- element.content = 'current content';
- element.storageKey = 'test';
- dispatchSpy = sandbox.spy(element, 'dispatchEvent');
- });
-
- test('editing toggled to true, has stored data', () => {
- sandbox.stub(element.$.storage, 'getEditableContentItem')
- .returns({message: 'stored content'});
- element.editing = true;
-
- assert.equal(element._newContent, 'stored content');
- assert.isTrue(dispatchSpy.called);
- assert.equal(dispatchSpy.lastCall.args[0].type, 'show-alert');
- });
-
- test('editing toggled to true, has no stored data', () => {
- sandbox.stub(element.$.storage, 'getEditableContentItem')
- .returns({});
- element.editing = true;
-
- assert.equal(element._newContent, 'current content');
- assert.isFalse(dispatchSpy.called);
- });
-
- test('edits are cached', () => {
- const storeStub =
- sandbox.stub(element.$.storage, 'setEditableContentItem');
- const eraseStub =
- sandbox.stub(element.$.storage, 'eraseEditableContentItem');
- element.editing = true;
-
- element._newContent = 'new content';
- flushAsynchronousOperations();
- element.flushDebouncer('store');
-
- assert.isTrue(storeStub.called);
- assert.deepEqual(
- [element.storageKey, element._newContent],
- storeStub.lastCall.args);
-
- element._newContent = '';
- flushAsynchronousOperations();
- element.flushDebouncer('store');
-
- assert.isTrue(eraseStub.called);
- assert.deepEqual([element.storageKey], eraseStub.lastCall.args);
- });
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content_test.js b/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content_test.js
new file mode 100644
index 0000000..0a9dd79
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content_test.js
@@ -0,0 +1,141 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-editable-content.js';
+
+const basicFixture = fixtureFromElement('gr-editable-content');
+
+suite('gr-editable-content tests', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ test('save event', done => {
+ element.content = '';
+ element._newContent = 'foo';
+ element.addEventListener('editable-content-save', e => {
+ assert.equal(e.detail.content, 'foo');
+ done();
+ });
+ MockInteractions.tap(element.shadowRoot
+ .querySelector('gr-button[primary]'));
+ });
+
+ test('cancel event', done => {
+ element.addEventListener('editable-content-cancel', () => {
+ done();
+ });
+ MockInteractions.tap(element.shadowRoot
+ .querySelector('gr-button:not([primary])'));
+ });
+
+ test('enabling editing keeps old content', () => {
+ element.content = 'current content';
+ element._newContent = 'old content';
+ element.editing = true;
+ assert.equal(element._newContent, 'old content');
+ });
+
+ test('disabling editing does not update edit field contents', () => {
+ element.content = 'current content';
+ element.editing = true;
+ element._newContent = 'stale content';
+ element.editing = false;
+ assert.equal(element._newContent, 'stale content');
+ });
+
+ test('zero width spaces are removed properly', () => {
+ element.removeZeroWidthSpace = true;
+ element.content = 'R=\u200Btest@google.com';
+ element.editing = true;
+ assert.equal(element._newContent, 'R=test@google.com');
+ });
+
+ suite('editing', () => {
+ setup(() => {
+ element.content = 'current content';
+ element.editing = true;
+ });
+
+ test('save button is disabled initially', () => {
+ assert.isTrue(element.shadowRoot
+ .querySelector('gr-button[primary]').disabled);
+ });
+
+ test('save button is enabled when content changes', () => {
+ element._newContent = 'new content';
+ assert.isFalse(element.shadowRoot
+ .querySelector('gr-button[primary]').disabled);
+ });
+ });
+
+ suite('storageKey and related behavior', () => {
+ let dispatchSpy;
+ setup(() => {
+ element.content = 'current content';
+ element.storageKey = 'test';
+ dispatchSpy = sinon.spy(element, 'dispatchEvent');
+ });
+
+ test('editing toggled to true, has stored data', () => {
+ sinon.stub(element.$.storage, 'getEditableContentItem')
+ .returns({message: 'stored content'});
+ element.editing = true;
+
+ assert.equal(element._newContent, 'stored content');
+ assert.isTrue(dispatchSpy.called);
+ assert.equal(dispatchSpy.lastCall.args[0].type, 'show-alert');
+ });
+
+ test('editing toggled to true, has no stored data', () => {
+ sinon.stub(element.$.storage, 'getEditableContentItem')
+ .returns({});
+ element.editing = true;
+
+ assert.equal(element._newContent, 'current content');
+ assert.isFalse(dispatchSpy.called);
+ });
+
+ test('edits are cached', () => {
+ const storeStub =
+ sinon.stub(element.$.storage, 'setEditableContentItem');
+ const eraseStub =
+ sinon.stub(element.$.storage, 'eraseEditableContentItem');
+ element.editing = true;
+
+ element._newContent = 'new content';
+ flushAsynchronousOperations();
+ element.flushDebouncer('store');
+
+ assert.isTrue(storeStub.called);
+ assert.deepEqual(
+ [element.storageKey, element._newContent],
+ storeStub.lastCall.args);
+
+ element._newContent = '';
+ flushAsynchronousOperations();
+ element.flushDebouncer('store');
+
+ assert.isTrue(eraseStub.called);
+ assert.deepEqual([element.storageKey], eraseStub.lastCall.args);
+ });
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label_test.html b/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label_test.js
similarity index 64%
rename from polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label_test.html
rename to polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label_test.js
index 1d1bce8..8c04aed 100644
--- a/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label_test.js
@@ -1,78 +1,55 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
+import '../../../test/common-test-setup-karma.js';
+import './gr-editable-label.js';
+import {flush as flush$0} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-editable-label</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<!-- Can't use absolute path below for mock-interaction.js.
-Web component tester(wct) has a built-in http server and it serves "/components" directory (which is
-actually /node_modules directory). Also, wct patches some files to load modules from /components.
-With the absolute path, browser tries to load dom-module from 2 different places (/component/... and
-/node_modules/...) though this is actually the same file. This leads to a run-time error.
--->
-<script src="../../../node_modules/iron-test-helpers/mock-interactions.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-editable-label
+const basicFixture = fixtureFromTemplate(html`
+<gr-editable-label
value="value text"
placeholder="label text"></gr-editable-label>
- </template>
-</test-fixture>
+`);
-<test-fixture id="no-placeholder">
- <template>
- <gr-editable-label value=""></gr-editable-label>
- </template>
-</test-fixture>
+const noPlaceholderFixture = fixtureFromTemplate(html`
+<gr-editable-label value=""></gr-editable-label>
+`);
-<test-fixture id="read-only">
- <template>
- <gr-editable-label
+const readOnlyFixture = fixtureFromTemplate(html`
+<gr-editable-label
read-only
value="value text"
placeholder="label text"></gr-editable-label>
- </template>
-</test-fixture>
+`);
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-editable-label.js';
-import {flush as flush$0} from '@polymer/polymer/lib/legacy/polymer.dom.js';
suite('gr-editable-label tests', () => {
let element;
let elementNoPlaceholder;
let input;
let label;
- let sandbox;
setup(done => {
- element = fixture('basic');
- elementNoPlaceholder = fixture('no-placeholder');
+ element = basicFixture.instantiate();
+ elementNoPlaceholder = noPlaceholderFixture.instantiate();
label = element.shadowRoot
.querySelector('label');
- sandbox = sinon.sandbox.create();
+
flush(() => {
// In Polymer 2 inputElement isn't nativeInput anymore
input = element.$.input.$.nativeInput || element.$.input.inputElement;
@@ -80,17 +57,13 @@
});
});
- teardown(() => {
- sandbox.restore();
- });
-
test('element render', () => {
// The dropdown is closed and the label is visible:
assert.isFalse(element.$.dropdown.opened);
assert.isTrue(label.classList.contains('editable'));
assert.equal(label.textContent, 'value text');
- const focusSpy = sandbox.spy(input, 'focus');
- const showSpy = sandbox.spy(element, '_showDropdown');
+ const focusSpy = sinon.spy(input, 'focus');
+ const showSpy = sinon.spy(element, '_showDropdown');
MockInteractions.tap(label);
@@ -123,7 +96,7 @@
});
test('edit value', done => {
- const editedStub = sandbox.stub();
+ const editedStub = sinon.stub();
element.addEventListener('changed', editedStub);
assert.isFalse(element.editing);
@@ -148,7 +121,7 @@
});
test('save button', done => {
- const editedStub = sandbox.stub();
+ const editedStub = sinon.stub();
element.addEventListener('changed', editedStub);
assert.isFalse(element.editing);
@@ -173,7 +146,7 @@
});
test('edit and then escape key', done => {
- const editedStub = sandbox.stub();
+ const editedStub = sinon.stub();
element.addEventListener('changed', editedStub);
assert.isFalse(element.editing);
@@ -199,7 +172,7 @@
});
test('cancel button', done => {
- const editedStub = sandbox.stub();
+ const editedStub = sinon.stub();
element.addEventListener('changed', editedStub);
assert.isFalse(element.editing);
@@ -229,7 +202,7 @@
let label;
setup(() => {
- element = fixture('read-only');
+ element = readOnlyFixture.instantiate();
label = element.shadowRoot
.querySelector('label');
});
@@ -250,4 +223,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-fixed-panel/gr-fixed-panel_test.html b/polygerrit-ui/app/elements/shared/gr-fixed-panel/gr-fixed-panel_test.html
deleted file mode 100644
index ef31382..0000000
--- a/polygerrit-ui/app/elements/shared/gr-fixed-panel/gr-fixed-panel_test.html
+++ /dev/null
@@ -1,124 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-fixed-panel</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<style>
- /* Prevent horizontal scrolling on page.
- New version of web-component-tester creates body with margins */
- body {
- margin: 0px;
- padding: 0px;
- }
-</style>
-
-<test-fixture id="basic">
- <template>
- <gr-fixed-panel>
- <div style="height: 100px"></div>
- </gr-fixed-panel>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-fixed-panel.js';
-suite('gr-fixed-panel', () => {
- let element;
- let sandbox;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- element.readyForMeasure = true;
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('can be disabled with floatingDisabled', () => {
- element.floatingDisabled = true;
- sandbox.stub(element, '_reposition');
- window.dispatchEvent(new CustomEvent('resize'));
- element.flushDebouncer('update');
- assert.isFalse(element._reposition.called);
- });
-
- test('header is the height of the content', () => {
- assert.equal(element.getBoundingClientRect().height, 100);
- });
-
- test('scroll triggers _reposition', () => {
- sandbox.stub(element, '_reposition');
- window.dispatchEvent(new CustomEvent('scroll'));
- element.flushDebouncer('update');
- assert.isTrue(element._reposition.called);
- });
-
- suite('_reposition', () => {
- const getHeaderTop = function() {
- return element.$.header.style.top;
- };
-
- const emulateScrollY = function(distance) {
- element._getElementTop.returns(element._headerTopInitial - distance);
- element._updateDebounced();
- element.flushDebouncer('scroll');
- };
-
- setup(() => {
- element._headerTopInitial = 10;
- sandbox.stub(element, '_getElementTop')
- .returns(element._headerTopInitial);
- });
-
- test('scrolls header along with document', () => {
- emulateScrollY(20);
- // No top property is set when !_headerFloating.
- assert.equal(getHeaderTop(), '');
- });
-
- test('does not stick to the top by default', () => {
- emulateScrollY(150);
- // No top property is set when !_headerFloating.
- assert.equal(getHeaderTop(), '');
- });
-
- test('sticks to the top if enabled', () => {
- element.keepOnScroll = true;
- emulateScrollY(120);
- assert.equal(getHeaderTop(), '0px');
- });
-
- test('drops a shadow when fixed to the top', () => {
- element.keepOnScroll = true;
- emulateScrollY(5);
- assert.isFalse(element.$.header.classList.contains('fixedAtTop'));
- emulateScrollY(120);
- assert.isTrue(element.$.header.classList.contains('fixedAtTop'));
- });
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-fixed-panel/gr-fixed-panel_test.js b/polygerrit-ui/app/elements/shared/gr-fixed-panel/gr-fixed-panel_test.js
new file mode 100644
index 0000000..b9378ba
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-fixed-panel/gr-fixed-panel_test.js
@@ -0,0 +1,99 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-fixed-panel.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const basicFixture = fixtureFromTemplate(html`
+<gr-fixed-panel>
+ <div style="height: 100px"></div>
+ </gr-fixed-panel>
+`);
+
+suite('gr-fixed-panel', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ element.readyForMeasure = true;
+ });
+
+ test('can be disabled with floatingDisabled', () => {
+ element.floatingDisabled = true;
+ sinon.stub(element, '_reposition');
+ window.dispatchEvent(new CustomEvent('resize'));
+ element.flushDebouncer('update');
+ assert.isFalse(element._reposition.called);
+ });
+
+ test('header is the height of the content', () => {
+ assert.equal(element.getBoundingClientRect().height, 100);
+ });
+
+ test('scroll triggers _reposition', () => {
+ sinon.stub(element, '_reposition');
+ window.dispatchEvent(new CustomEvent('scroll'));
+ element.flushDebouncer('update');
+ assert.isTrue(element._reposition.called);
+ });
+
+ suite('_reposition', () => {
+ const getHeaderTop = function() {
+ return element.$.header.style.top;
+ };
+
+ const emulateScrollY = function(distance) {
+ element._getElementTop.returns(element._headerTopInitial - distance);
+ element._updateDebounced();
+ element.flushDebouncer('scroll');
+ };
+
+ setup(() => {
+ element._headerTopInitial = 10;
+ sinon.stub(element, '_getElementTop')
+ .returns(element._headerTopInitial);
+ });
+
+ test('scrolls header along with document', () => {
+ emulateScrollY(20);
+ // No top property is set when !_headerFloating.
+ assert.equal(getHeaderTop(), '');
+ });
+
+ test('does not stick to the top by default', () => {
+ emulateScrollY(150);
+ // No top property is set when !_headerFloating.
+ assert.equal(getHeaderTop(), '');
+ });
+
+ test('sticks to the top if enabled', () => {
+ element.keepOnScroll = true;
+ emulateScrollY(120);
+ assert.equal(getHeaderTop(), '0px');
+ });
+
+ test('drops a shadow when fixed to the top', () => {
+ element.keepOnScroll = true;
+ emulateScrollY(5);
+ assert.isFalse(element.$.header.classList.contains('fixedAtTop'));
+ emulateScrollY(120);
+ assert.isTrue(element.$.header.classList.contains('fixedAtTop'));
+ });
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text_test.html b/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text_test.js
similarity index 89%
rename from polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text_test.html
rename to polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text_test.js
index 083eac4..fd5a9ba 100644
--- a/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text_test.js
@@ -1,42 +1,27 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-editable-label</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-formatted-text></gr-formatted-text>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-formatted-text.js';
+
+const basicFixture = fixtureFromElement('gr-formatted-text');
+
suite('gr-formatted-text tests', () => {
let element;
- let sandbox;
function assertBlock(result, index, type, text) {
assert.equal(result[index].type, type);
@@ -49,12 +34,7 @@
}
setup(() => {
- element = fixture('basic');
- sandbox = sinon.sandbox.create();
- });
-
- teardown(() => {
- sandbox.restore();
+ element = basicFixture.instantiate();
});
test('parse null undefined and empty', () => {
@@ -409,18 +389,18 @@
});
test('_computeNodes called without config', () => {
- const computeNodesSpy = sandbox.spy(element, '_computeNodes');
+ const computeNodesSpy = sinon.spy(element, '_computeNodes');
element.content = 'some text';
assert.isTrue(computeNodesSpy.called);
});
test('_contentOrConfigChanged called with config', () => {
- const contentStub = sandbox.stub(element, '_contentChanged');
- const contentConfigStub = sandbox.stub(element, '_contentOrConfigChanged');
+ const contentStub = sinon.stub(element, '_contentChanged');
+ const contentConfigStub = sinon.stub(element, '_contentOrConfigChanged');
element.content = 'some text';
element.config = {};
assert.isTrue(contentStub.called);
assert.isTrue(contentConfigStub.called);
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account.js b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account.js
index 49aff7e..ac9bd62 100644
--- a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account.js
+++ b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account.js
@@ -19,7 +19,9 @@
import '../../../styles/shared-styles.js';
import '../gr-avatar/gr-avatar.js';
import '../gr-button/gr-button.js';
+import '../gr-rest-api-interface/gr-rest-api-interface.js';
import {hovercardBehaviorMixin} from '../gr-hovercard/gr-hovercard-behavior.js';
+import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
@@ -35,15 +37,111 @@
static get properties() {
return {
+ /**
+ * This is an AccountInfo response object.
+ */
account: Object,
+ _selfAccount: Object,
+ /**
+ * Optional ChangeInfo object, typically comes from the change page or
+ * from a row in a list of search results. This is needed for some change
+ * related features like adding the user as a reviewer.
+ */
+ change: Object,
+ /**
+ * Explains which labels the user can vote on and which score they can
+ * give.
+ */
voteableText: String,
- attention: {
+ /**
+ * Should attention set related features be shown in the component? Note
+ * that the information whether the user is in the attention set or not is
+ * part of the ChangeInfo object in the change property.
+ */
+ highlightAttention: {
type: Boolean,
value: false,
- reflectToAttribute: true,
+ },
+ /**
+ * This is a ServerInfo response object.
+ */
+ _config: {
+ type: Object,
+ value: null,
},
};
}
+
+ attached() {
+ super.attached();
+ this.$.restAPI.getConfig().then(config => {
+ this._config = config;
+ });
+ this.$.restAPI.getAccount().then(account => {
+ this._selfAccount = account;
+ });
+ }
+
+ _computeText(account, selfAccount) {
+ if (!account || !selfAccount) return '';
+ return account._account_id === selfAccount._account_id ? 'Your' : 'Their';
+ }
+
+ get isAttentionSetEnabled() {
+ return !!this._config && !!this._config.change
+ && !!this._config.change.enable_attention_set
+ && !!this.highlightAttention && !!this.change && !!this.account;
+ }
+
+ get hasAttention() {
+ if (!this.isAttentionSetEnabled || !this.change.attention_set) return false;
+ return this.change.attention_set.hasOwnProperty(this.account._account_id);
+ }
+
+ _computeShowLabelNeedsAttention(config, highlightAttention, account, change) {
+ return this.isAttentionSetEnabled && this.hasAttention;
+ }
+
+ _computeShowActionAddToAttentionSet(config, highlightAttn, account, change) {
+ return this.isAttentionSetEnabled && !this.hasAttention;
+ }
+
+ _computeShowActionRemoveFromAttentionSet(config, highlightAttention, account,
+ change) {
+ return this.isAttentionSetEnabled && this.hasAttention;
+ }
+
+ _handleClickAddToAttentionSet(e) {
+ this.dispatchEvent(new CustomEvent('show-alert', {
+ detail: {
+ message: 'Adding user to attention set. Will be reloading ...',
+ dismissOnNavigation: true,
+ },
+ composed: true,
+ bubbles: true,
+ }));
+ this.$.restAPI.addToAttentionSet(this.change._number,
+ this.account._account_id, 'manually added').then(obj => {
+ GerritNav.navigateToChange(this.change);
+ });
+ this.hide();
+ }
+
+ _handleClickRemoveFromAttentionSet(e) {
+ this.dispatchEvent(new CustomEvent('show-alert', {
+ detail: {
+ message: 'Removing user from attention set. Will be reloading ...',
+ dismissOnNavigation: true,
+ },
+ composed: true,
+ bubbles: true,
+ }));
+ this.$.restAPI.removeFromAttentionSet(this.change._number,
+ this.account._account_id, 'manually removed').then(obj => {
+ GerritNav.navigateToChange(this.change);
+ });
+ this.hide();
+ }
}
customElements.define(GrHovercardAccount.is, GrHovercardAccount);
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_html.js b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_html.js
index bbf6a96..262b089 100644
--- a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_html.js
+++ b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_html.js
@@ -50,17 +50,18 @@
border-top: 1px solid var(--border-color);
padding: var(--spacing-s) var(--spacing-l);
--gr-button: {
- padding: var(--spacing-s) 0;
+ padding: var(--spacing-s) var(--spacing-m);
}
}
- :host(:not([attention])) .attention {
- display: none;
- }
.attention {
background-color: var(--emphasis-color);
}
.attention iron-icon {
+ width: 14px;
+ height: 14px;
vertical-align: top;
+ position: relative;
+ top: 3px;
}
</style>
<div id="container" role="tooltip" tabindex="-1">
@@ -89,10 +90,46 @@
<span class="value">[[voteableText]]</span>
</div>
</template>
- <div class="attention">
- <iron-icon icon="gr-icons:attention"></iron-icon>
- <span>It is this user's turn to take action.</span>
- </div>
+ <template
+ is="dom-if"
+ if="[[_computeShowLabelNeedsAttention(_config, highlightAttention, account, change)]]"
+ >
+ <div class="attention">
+ <iron-icon icon="gr-icons:attention"></iron-icon>
+ <span>
+ [[_computeText(account, _selfAccount)]] turn to take action.
+ </span>
+ </div>
+ </template>
+ <template
+ is="dom-if"
+ if="[[_computeShowActionAddToAttentionSet(_config, highlightAttention, account, change)]]"
+ >
+ <div class="action">
+ <gr-button
+ link=""
+ no-uppercase=""
+ on-click="_handleClickAddToAttentionSet"
+ >
+ Add to attention set
+ </gr-button>
+ </div>
+ </template>
+ <template
+ is="dom-if"
+ if="[[_computeShowActionRemoveFromAttentionSet(_config, highlightAttention, account, change)]]"
+ >
+ <div class="action">
+ <gr-button
+ link=""
+ no-uppercase=""
+ on-click="_handleClickRemoveFromAttentionSet"
+ >
+ Remove from attention set
+ </gr-button>
+ </div>
+ </template>
</template>
</div>
+ <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
`;
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_test.html b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_test.html
deleted file mode 100644
index 884e1b6..0000000
--- a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_test.html
+++ /dev/null
@@ -1,83 +0,0 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2020 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport"
- content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<title>gr-hovercard-account</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<script src="../../../node_modules/iron-test-helpers/mock-interactions.js" type="module"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-hovercard-account class="hovered"></gr-hovercard-account>
- </template>
-</test-fixture>
-
-
-<script type="module">
- import '../../../test/common-test-setup.js';
- import './gr-hovercard-account.js';
-
- suite('gr-hovercard-account tests', () => {
- let element;
- const ACCOUNT = {
- email: 'kermit@gmail.com',
- username: 'kermit',
- name: 'Kermit The Frog',
- _account_id: '31415926535',
- };
-
- setup(() => {
- element = fixture('basic');
- element.account = Object.assign({}, ACCOUNT);
- element.show({});
- flushAsynchronousOperations();
- });
-
- test('account name is shown', () => {
- assert.equal(element.shadowRoot.querySelector('.name').innerText,
- 'Kermit The Frog');
- });
-
- test('account status is not shown if the property is not set', () => {
- assert.isNull(element.shadowRoot.querySelector('.status'));
- });
-
- test('account status is displayed', () => {
- element.account = Object.assign({status: 'OOO'}, ACCOUNT);
- flushAsynchronousOperations();
- assert.equal(element.shadowRoot.querySelector('.status .value').innerText,
- 'OOO');
- });
-
- test('voteable div is not shown if the property is not set', () => {
- assert.isNull(element.shadowRoot.querySelector('.voteable'));
- });
-
- test('voteable div is displayed', () => {
- element.voteableText = 'CodeReview: +2';
- flushAsynchronousOperations();
- assert.equal(element.shadowRoot.querySelector('.voteable .value').innerText,
- element.voteableText);
- });
- });
-</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_test.js b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_test.js
new file mode 100644
index 0000000..ea7eb87
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_test.js
@@ -0,0 +1,86 @@
+/**
+ * @license
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import '../../../test/common-test-setup-karma.js';
+import './gr-hovercard-account.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const basicFixture = fixtureFromTemplate(html`
+<gr-hovercard-account class="hovered"></gr-hovercard-account>
+`);
+
+suite('gr-hovercard-account tests', () => {
+ let element;
+
+ const ACCOUNT = {
+ email: 'kermit@gmail.com',
+ username: 'kermit',
+ name: 'Kermit The Frog',
+ _account_id: '31415926535',
+ };
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ sinon.stub(element.$.restAPI, 'getAccount').returns(
+ new Promise(resolve => { '2'; })
+ );
+
+ element.account = Object.assign({}, ACCOUNT);
+ element.show({});
+ flushAsynchronousOperations();
+ });
+
+ teardown(() => {
+ element.hide({});
+ });
+
+ test('account name is shown', () => {
+ assert.equal(element.shadowRoot.querySelector('.name').innerText,
+ 'Kermit The Frog');
+ });
+
+ test('_computeText', () => {
+ let account = {_account_id: '1'};
+ const selfAccount = {_account_id: '1'};
+ assert.equal(element._computeText(account, selfAccount), 'Your');
+ account = {_account_id: '2'};
+ assert.equal(element._computeText(account, selfAccount), 'Their');
+ });
+
+ test('account status is not shown if the property is not set', () => {
+ assert.isNull(element.shadowRoot.querySelector('.status'));
+ });
+
+ test('account status is displayed', () => {
+ element.account = Object.assign({status: 'OOO'}, ACCOUNT);
+ flushAsynchronousOperations();
+ assert.equal(element.shadowRoot.querySelector('.status .value').innerText,
+ 'OOO');
+ });
+
+ test('voteable div is not shown if the property is not set', () => {
+ assert.isNull(element.shadowRoot.querySelector('.voteable'));
+ });
+
+ test('voteable div is displayed', () => {
+ element.voteableText = 'CodeReview: +2';
+ flushAsynchronousOperations();
+ assert.equal(element.shadowRoot.querySelector('.voteable .value').innerText,
+ element.voteableText);
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard-behavior.js b/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard-behavior.js
index 1190908..571e49a 100644
--- a/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard-behavior.js
+++ b/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard-behavior.js
@@ -186,9 +186,9 @@
* `mouseleave` event on the hovercard's `target` element (as long as the
* user is not hovering over the hovercard).
*
- * @param {Event} e DOM Event (e.g. `mouseleave` event)
+ * @param {Event} opt_e DOM Event (e.g. `mouseleave` event)
*/
- hide(e) {
+ hide(opt_e) {
this._isScheduledToShow = false;
if (!this._isShowing) {
return;
@@ -197,9 +197,11 @@
// If the user is now hovering over the hovercard or the user is returning
// from the hovercard but now hovering over the target (to stop an annoying
// flicker effect), just return.
- if (e.toElement === this ||
- (e.fromElement === this && e.toElement === this._target)) {
- return;
+ if (opt_e) {
+ if (opt_e.toElement === this ||
+ (opt_e.fromElement === this && opt_e.toElement === this._target)) {
+ return;
+ }
}
// Mark that the hovercard is not visible and do not allow focusing
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard_test.html b/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard_test.js
similarity index 66%
rename from polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard_test.html
rename to polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard_test.js
index 21f692d..a7a2c0e 100644
--- a/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard_test.js
@@ -1,58 +1,49 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2018 The Android Open Source Project
+/**
+ * @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.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-hovercard</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<!-- Can't use absolute path below for mock-interaction.js.
-Web component tester(wct) has a built-in http server and it serves "/components" directory (which is
-actually /node_modules directory). Also, wct patches some files to load modules from /components.
-With the absolute path, browser tries to load dom-module from 2 different places (/component/... and
-/node_modules/...) though this is actually the same file. This leads to a run-time error.
--->
-<script src="../../../node_modules/iron-test-helpers/mock-interactions.js"></script>
-
-<button id="foo">Hello</button>
-<test-fixture id="basic">
- <template>
- <gr-hovercard for="foo" id="bar"></gr-hovercard>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-hovercard.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+//
+
+const basicFixture = fixtureFromTemplate(html`
+<gr-hovercard for="foo" id="bar"></gr-hovercard>
+`);
+
suite('gr-hovercard tests', () => {
let element;
- let sandbox;
+
+ let button;
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
+ button = document.createElement('button');
+ button.innerHTML = 'Hello';
+ button.setAttribute('id', 'foo');
+ document.body.appendChild(button);
+
+ element = basicFixture.instantiate();
});
- teardown(() => { sandbox.restore(); });
+ teardown(() => {
+ element.hide({});
+ button.remove();
+ });
test('updatePosition', () => {
// Test that the correct style properties have at least been set.
@@ -156,4 +147,4 @@
button.dispatchEvent(new CustomEvent('mouseenter'));
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-icons/gr-icons.js b/polygerrit-ui/app/elements/shared/gr-icons/gr-icons.js
index 070ac02..5ffe028 100644
--- a/polygerrit-ui/app/elements/shared/gr-icons/gr-icons.js
+++ b/polygerrit-ui/app/elements/shared/gr-icons/gr-icons.js
@@ -55,6 +55,8 @@
<g id="help"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 17h-2v-2h2v2zm2.07-7.75l-.9.92C13.45 12.9 13 13.5 13 15h-2v-.5c0-1.1.45-2.1 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41 0-1.1-.9-2-2-2s-2 .9-2 2H8c0-2.21 1.79-4 4-4s4 1.79 4 4c0 .88-.36 1.68-.93 2.25z"></path></g>
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.js -->
<g id="info"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"></path></g>
+ <!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.js -->
+ <g id="info-outline"><path d="M11 17h2v-6h-2v6zm1-15C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zM11 9h2V7h-2v2z"></path></g>
<!-- This SVG is a copy from material.io https://material.io/icons/#ic_hourglass_full-->
<g id="hourglass"><path d="M6 2v6h.01L6 8.01 10 12l-4 4 .01.01H6V22h12v-5.99h-.01L18 16l-4-4 4-3.99-.01-.01H18V2H6z"></path><path d="M0 0h24v24H0V0z" fill="none"></path></g>
<!-- This SVG is a copy from material.io https://material.io/icons/#mode_comment-->
@@ -97,7 +99,7 @@
<!-- This is a custom PolyGerrit SVG -->
<g id="zeroState"><path d="M22 9V7h-2V5c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2v-2h2v-2h-2v-2h2v-2h-2V9h2zm-4 10H4V5h14v14zM6 13h5v4H6zm6-6h4v3h-4zM6 7h5v5H6zm6 4h4v6h-4z"></path></g>
<!-- This SVG is an adaptation of material.io https://material.io/icons/#label_important-->
- <g id="attention"><path d="M5.5 19 l9 0 c.67 0 1.27 -.33 1.63 -.84 L20.5 12 l-4.37 -6.16 c-.36 -.51 -.96 -.84 -1.63 -.84 l-9 0 L9 12 z"></path></g>
+ <g id="attention"><path d="M1 23 l13 0 c.67 0 1.27 -.33 1.63 -.84 l7.37 -10.16 l-7.37 -10.16 c-.36 -.51 -.96 -.84 -1.63 -.84 L1 1 L7 12 z"></path></g>
<!-- This SVG is a copy from material.io https://material.io/icons/#pets-->
<g id="pets"><circle cx="4.5" cy="9.5" r="2.5"/><circle cx="9" cy="5.5" r="2.5"/><circle cx="15" cy="5.5" r="2.5"/><circle cx="19.5" cy="9.5" r="2.5"/><path d="M17.34 14.86c-.87-1.02-1.6-1.89-2.48-2.91-.46-.54-1.05-1.08-1.75-1.32-.11-.04-.22-.07-.33-.09-.25-.04-.52-.04-.78-.04s-.53 0-.79.05c-.11.02-.22.05-.33.09-.7.24-1.28.78-1.75 1.32-.87 1.02-1.6 1.89-2.48 2.91-1.31 1.31-2.92 2.76-2.62 4.79.29 1.02 1.02 2.03 2.33 2.32.73.15 3.06-.44 5.54-.44h.18c2.48 0 4.81.58 5.54.44 1.31-.29 2.04-1.31 2.33-2.32.31-2.04-1.3-3.49-2.61-4.8z"/><path d="M0 0h24v24H0z" fill="none"/></g>
<!-- This SVG is a copy from material.io https://material.io/icons/#visibility-->
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-context_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-context_test.js
similarity index 62%
rename from polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-context_test.html
rename to polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-context_test.js
index a14612b..b46a3b0 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-context_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-context_test.js
@@ -1,53 +1,36 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-annotation-actions-context</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <div></div>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-js-api-interface.js';
import {GrAnnotation} from '../../diff/gr-diff-highlight/gr-annotation.js';
import {GrAnnotationActionsContext} from './gr-annotation-actions-context.js';
import {_testOnly_initGerritPluginApi} from './gr-gerrit.js';
+
const pluginApi = _testOnly_initGerritPluginApi();
suite('gr-annotation-actions-context tests', () => {
let instance;
- let sandbox;
+
let el;
let lineNumberEl;
let plugin;
setup(() => {
- sandbox = sinon.sandbox.create();
pluginApi.install(p => { plugin = p; }, '0.1',
'http://test.com/plugins/testplugin/static/test.js');
@@ -64,11 +47,11 @@
});
teardown(() => {
- sandbox.restore();
+ el.remove();
});
test('test annotateRange', () => {
- const annotateElementSpy = sandbox.spy(GrAnnotation, 'annotateElement');
+ const annotateElementSpy = sinon.spy(GrAnnotation, 'annotateElement');
const start = 0;
const end = 100;
const cssStyleObject = plugin.styles().css('background-color: #000000');
@@ -101,4 +84,4 @@
assert.isTrue(lineNumberEl.classList.contains(className));
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api.js
index 3b24404..6f73c36 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api.js
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api.js
@@ -144,7 +144,6 @@
// path.
if (annotationLayer._path === path) {
annotationLayer.notifyListeners(startRange, endRange, side);
- break;
}
}
};
@@ -153,6 +152,8 @@
* Should be called to register annotation layers by the framework. Not
* intended to be called by plugins.
*
+ * Don't forget to dispose layer.
+ *
* @param {string} path The file path (eg: /COMMIT_MSG').
* @param {string} changeNum The Gerrit change number.
* @param {string} patchNum The Gerrit patch number.
@@ -165,6 +166,11 @@
return annotationLayer;
};
+GrAnnotationActionsInterface.prototype.disposeLayer = function(path) {
+ this._annotationLayers = this._annotationLayers
+ .filter(annotationLayer => annotationLayer._path !== path);
+};
+
/**
* Used to create an instance of the Annotation Layer interface.
*
@@ -186,6 +192,7 @@
/**
* Register a listener for layer updates.
+ * Don't forget to removeListener when you stop using layer.
*
* @param {Function} fn The update handler function.
* Should accept as arguments the line numbers for the start and end of
@@ -195,6 +202,10 @@
this._listeners.push(fn);
};
+AnnotationLayer.prototype.removeListener = function(fn) {
+ this._listeners = this._listeners.filter(f => f != fn);
+};
+
/**
* Layer method to add annotations to a line.
*
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api_test.js
similarity index 69%
rename from polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api_test.html
rename to polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api_test.js
index e72fc63..e819529 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api_test.js
@@ -1,54 +1,42 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-annotation-actions-js-api-js-api</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<test-fixture id="basic">
- <template>
- <span hidden id="annotation-span">
- <label for="annotation-checkbox" id="annotation-label"></label>
- <iron-input type="checkbox" disabled>
- <input is="iron-input" type="checkbox" id="annotation-checkbox" disabled>
- </iron-input>
- </span>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import '../../change/gr-change-actions/gr-change-actions.js';
import {_testOnly_initGerritPluginApi} from './gr-gerrit.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const basicFixture = fixtureFromTemplate(html`
+ <span hidden id="annotation-span">
+ <label for="annotation-checkbox" id="annotation-label"></label>
+ <iron-input type="checkbox" disabled>
+ <input is="iron-input" type="checkbox" id="annotation-checkbox" disabled>
+ </iron-input>
+ </span>
+`);
const pluginApi = _testOnly_initGerritPluginApi();
suite('gr-annotation-actions-js-api tests', () => {
let annotationActions;
- let sandbox;
+
let plugin;
setup(() => {
- sandbox = sinon.sandbox.create();
pluginApi.install(p => { plugin = p; }, '0.1',
'http://test.com/plugins/testplugin/static/test.js');
annotationActions = plugin.annotationApi();
@@ -56,7 +44,6 @@
teardown(() => {
annotationActions = null;
- sandbox.restore();
});
test('add/get layer', () => {
@@ -89,8 +76,8 @@
const path2 = '/dummy/path2';
const annotationLayer1 = annotationActions.getLayer(path1, 1, 2);
const annotationLayer2 = annotationActions.getLayer(path2, 1, 2);
- const layer1Spy = sandbox.spy(annotationLayer1, 'notifyListeners');
- const layer2Spy = sandbox.spy(annotationLayer2, 'notifyListeners');
+ const layer1Spy = sinon.spy(annotationLayer1, 'notifyListeners');
+ const layer2Spy = sinon.spy(annotationLayer2, 'notifyListeners');
let notify;
let notifyFuncCalled;
@@ -112,8 +99,8 @@
assert.isFalse(layer2Spy.called);
// Reset spies.
- layer1Spy.reset();
- layer2Spy.reset();
+ layer1Spy.resetHistory();
+ layer2Spy.resetHistory();
// Assert that only the 2nd layer is invoked with path2.
notify(path2, 0, 20, 'left');
@@ -122,9 +109,9 @@
});
test('toggle checkbox', () => {
- const fakeEl = {content: fixture('basic')};
- const hookStub = {onAttached: sandbox.stub()};
- sandbox.stub(plugin, 'hook').returns(hookStub);
+ const fakeEl = {content: basicFixture.instantiate()};
+ const hookStub = {onAttached: sinon.stub()};
+ sinon.stub(plugin, 'hook').returns(hookStub);
let checkbox;
let onAttachedFuncCalled = false;
@@ -148,8 +135,8 @@
// Assert that error is shown if we try to enable checkbox again.
onAttachedFuncCalled = false;
annotationActions.enableToggleCheckbox('test label2', onAttachedFunc);
- const errorStub = sandbox.stub(
- console, 'error', (msg, err) => undefined);
+ const errorStub = sinon.stub(
+ console, 'error').callsFake((msg, err) => undefined);
emulateAttached();
assert.isTrue(
errorStub.calledWith(
@@ -189,4 +176,4 @@
assert.equal(listenerCalledTimes, 3);
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-api-utils.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-api-utils.js
index 5b58a5c..81ece81 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-api-utils.js
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-api-utils.js
@@ -56,7 +56,10 @@
pathname = url.href.replace(window.ASSETS_PATH, '');
}
// Site theme is server from predefined path.
- if (pathname === '/static/gerrit-theme.html') {
+ if ([
+ '/static/gerrit-theme.html',
+ '/static/gerrit-theme.js',
+ ].includes(pathname)) {
return 'gerrit-theme';
} else if (!pathname.startsWith('/plugins')) {
console.warn('Plugin not being loaded from /plugins base path:',
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-api-utils_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-api-utils_test.html
deleted file mode 100644
index d01566a..0000000
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-api-utils_test.html
+++ /dev/null
@@ -1,85 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-api-interface</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-js-api-interface.js';
-import {getPluginNameFromUrl} from './gr-api-utils.js';
-
-const PRELOADED_PROTOCOL = 'preloaded:';
-
-suite('gr-api-utils tests', () => {
- suite('test getPluginNameFromUrl', () => {
- test('with empty string', () => {
- assert.equal(getPluginNameFromUrl(''), null);
- });
-
- test('with invalid url', () => {
- assert.equal(getPluginNameFromUrl('test'), null);
- });
-
- test('with random invalid url', () => {
- assert.equal(getPluginNameFromUrl('http://example.com'), null);
- assert.equal(
- getPluginNameFromUrl('http://example.com/static/a.html'),
- null
- );
- });
-
- test('with valid urls', () => {
- assert.equal(
- getPluginNameFromUrl('http://example.com/plugins/a.html'),
- 'a'
- );
- assert.equal(
- getPluginNameFromUrl('http://example.com/plugins/a/static/t.html'),
- 'a'
- );
- });
-
- test('with preloaded urls', () => {
- assert.equal(getPluginNameFromUrl(`${PRELOADED_PROTOCOL}a`), 'a');
- });
-
- test('with gerrit-theme override', () => {
- assert.equal(
- getPluginNameFromUrl('http://example.com/static/gerrit-theme.html'),
- 'gerrit-theme'
- );
- });
-
- test('with ASSETS_PATH', () => {
- window.ASSETS_PATH = 'http://cdn.com/2';
- assert.equal(
- getPluginNameFromUrl(`${window.ASSETS_PATH}/plugins/a.html`),
- 'a'
- );
- window.ASSETS_PATH = undefined;
- });
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-api-utils_test.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-api-utils_test.js
new file mode 100644
index 0000000..85c62cb
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-api-utils_test.js
@@ -0,0 +1,74 @@
+/**
+ * @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.
+ */
+
+import '../../../test/common-test-setup-karma.js';
+import './gr-js-api-interface.js';
+import {getPluginNameFromUrl} from './gr-api-utils.js';
+
+const PRELOADED_PROTOCOL = 'preloaded:';
+
+suite('gr-api-utils tests', () => {
+ suite('test getPluginNameFromUrl', () => {
+ test('with empty string', () => {
+ assert.equal(getPluginNameFromUrl(''), null);
+ });
+
+ test('with invalid url', () => {
+ assert.equal(getPluginNameFromUrl('test'), null);
+ });
+
+ test('with random invalid url', () => {
+ assert.equal(getPluginNameFromUrl('http://example.com'), null);
+ assert.equal(
+ getPluginNameFromUrl('http://example.com/static/a.html'),
+ null
+ );
+ });
+
+ test('with valid urls', () => {
+ assert.equal(
+ getPluginNameFromUrl('http://example.com/plugins/a.html'),
+ 'a'
+ );
+ assert.equal(
+ getPluginNameFromUrl('http://example.com/plugins/a/static/t.html'),
+ 'a'
+ );
+ });
+
+ test('with preloaded urls', () => {
+ assert.equal(getPluginNameFromUrl(`${PRELOADED_PROTOCOL}a`), 'a');
+ });
+
+ test('with gerrit-theme override', () => {
+ assert.equal(
+ getPluginNameFromUrl('http://example.com/static/gerrit-theme.html'),
+ 'gerrit-theme'
+ );
+ });
+
+ test('with ASSETS_PATH', () => {
+ window.ASSETS_PATH = 'http://cdn.com/2';
+ assert.equal(
+ getPluginNameFromUrl(`${window.ASSETS_PATH}/plugins/a.html`),
+ 'a'
+ );
+ window.ASSETS_PATH = undefined;
+ });
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-actions-js-api_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-actions-js-api_test.js
similarity index 81%
rename from polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-actions-js-api_test.html
rename to polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-actions-js-api_test.js
index 1d5e423..231830bd 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-actions-js-api_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-actions-js-api_test.js
@@ -1,50 +1,32 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-change-actions-js-api</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<!--
-This must refer to the element this interface is wrapping around. Otherwise
-breaking changes to gr-change-actions won’t be noticed.
--->
-
-<test-fixture id="basic">
- <template>
- <gr-change-actions></gr-change-actions>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import '../../change/gr-change-actions/gr-change-actions.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {resetPlugins} from '../../../test/test-utils.js';
import {pluginLoader} from './gr-plugin-loader.js';
import {_testOnly_initGerritPluginApi} from './gr-gerrit.js';
+
+const basicFixture = fixtureFromElement('gr-change-actions');
+
const pluginApi = _testOnly_initGerritPluginApi();
-suite('gr-js-api-interface tests', () => {
+suite('gr-change-actions-js-api-interface tests', () => {
let element;
let changeActions;
let plugin;
@@ -65,7 +47,7 @@
// Mimic all plugins loaded.
pluginLoader.loadPlugins([]);
changeActions = plugin.changeActions();
- element = fixture('basic');
+ element = basicFixture.instantiate();
});
teardown(() => {
@@ -83,7 +65,7 @@
suite('normal init', () => {
setup(() => {
resetPlugins();
- element = fixture('basic');
+ element = basicFixture.instantiate();
sinon.stub(element, '_editStatusChanged');
element.change = {};
element._hasKnownChainState = false;
@@ -229,4 +211,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-reply-js-api_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-reply-js-api_test.html
deleted file mode 100644
index 0360f85..0000000
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-reply-js-api_test.html
+++ /dev/null
@@ -1,125 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-change-reply-js-api</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<!--
-This must refer to the element this interface is wrapping around. Otherwise
-breaking changes to gr-reply-dialog won’t be noticed.
--->
-
-<test-fixture id="basic">
- <template>
- <gr-reply-dialog></gr-reply-dialog>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import '../../change/gr-reply-dialog/gr-reply-dialog.js';
-import {_testOnly_initGerritPluginApi} from './gr-gerrit.js';
-
-const pluginApi = _testOnly_initGerritPluginApi();
-
-suite('gr-change-reply-js-api tests', () => {
- let element;
- let sandbox;
- let changeReply;
- let plugin;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- stub('gr-rest-api-interface', {
- getConfig() { return Promise.resolve({}); },
- getAccount() { return Promise.resolve(null); },
- });
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- suite('early init', () => {
- setup(() => {
- pluginApi.install(p => { plugin = p; }, '0.1',
- 'http://test.com/plugins/testplugin/static/test.js');
- changeReply = plugin.changeReply();
- element = fixture('basic');
- });
-
- teardown(() => {
- changeReply = null;
- });
-
- test('works', () => {
- sandbox.stub(element, 'getLabelValue').returns('+123');
- assert.equal(changeReply.getLabelValue('My-Label'), '+123');
-
- sandbox.stub(element, 'setLabelValue');
- changeReply.setLabelValue('My-Label', '+1337');
- assert.isTrue(
- element.setLabelValue.calledWithExactly('My-Label', '+1337'));
-
- sandbox.stub(element, 'send');
- changeReply.send(false);
- assert.isTrue(element.send.calledWithExactly(false));
-
- sandbox.stub(element, 'setPluginMessage');
- changeReply.showMessage('foobar');
- assert.isTrue(element.setPluginMessage.calledWithExactly('foobar'));
- });
- });
-
- suite('normal init', () => {
- setup(() => {
- element = fixture('basic');
- pluginApi.install(p => { plugin = p; }, '0.1',
- 'http://test.com/plugins/testplugin/static/test.js');
- changeReply = plugin.changeReply();
- });
-
- teardown(() => {
- changeReply = null;
- });
-
- test('works', () => {
- sandbox.stub(element, 'getLabelValue').returns('+123');
- assert.equal(changeReply.getLabelValue('My-Label'), '+123');
-
- sandbox.stub(element, 'setLabelValue');
- changeReply.setLabelValue('My-Label', '+1337');
- assert.isTrue(
- element.setLabelValue.calledWithExactly('My-Label', '+1337'));
-
- sandbox.stub(element, 'send');
- changeReply.send(false);
- assert.isTrue(element.send.calledWithExactly(false));
-
- sandbox.stub(element, 'setPluginMessage');
- changeReply.showMessage('foobar');
- assert.isTrue(element.setPluginMessage.calledWithExactly('foobar'));
- });
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-reply-js-api_test.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-reply-js-api_test.js
new file mode 100644
index 0000000..8f41b39
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-reply-js-api_test.js
@@ -0,0 +1,101 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import '../../change/gr-reply-dialog/gr-reply-dialog.js';
+import {_testOnly_initGerritPluginApi} from './gr-gerrit.js';
+
+const basicFixture = fixtureFromElement('gr-reply-dialog');
+
+const pluginApi = _testOnly_initGerritPluginApi();
+
+suite('gr-change-reply-js-api tests', () => {
+ let element;
+
+ let changeReply;
+ let plugin;
+
+ setup(() => {
+ stub('gr-rest-api-interface', {
+ getConfig() { return Promise.resolve({}); },
+ getAccount() { return Promise.resolve(null); },
+ });
+ });
+
+ suite('early init', () => {
+ setup(() => {
+ pluginApi.install(p => { plugin = p; }, '0.1',
+ 'http://test.com/plugins/testplugin/static/test.js');
+ changeReply = plugin.changeReply();
+ element = basicFixture.instantiate();
+ });
+
+ teardown(() => {
+ changeReply = null;
+ });
+
+ test('works', () => {
+ sinon.stub(element, 'getLabelValue').returns('+123');
+ assert.equal(changeReply.getLabelValue('My-Label'), '+123');
+
+ sinon.stub(element, 'setLabelValue');
+ changeReply.setLabelValue('My-Label', '+1337');
+ assert.isTrue(
+ element.setLabelValue.calledWithExactly('My-Label', '+1337'));
+
+ sinon.stub(element, 'send');
+ changeReply.send(false);
+ assert.isTrue(element.send.calledWithExactly(false));
+
+ sinon.stub(element, 'setPluginMessage');
+ changeReply.showMessage('foobar');
+ assert.isTrue(element.setPluginMessage.calledWithExactly('foobar'));
+ });
+ });
+
+ suite('normal init', () => {
+ setup(() => {
+ element = basicFixture.instantiate();
+ pluginApi.install(p => { plugin = p; }, '0.1',
+ 'http://test.com/plugins/testplugin/static/test.js');
+ changeReply = plugin.changeReply();
+ });
+
+ teardown(() => {
+ changeReply = null;
+ });
+
+ test('works', () => {
+ sinon.stub(element, 'getLabelValue').returns('+123');
+ assert.equal(changeReply.getLabelValue('My-Label'), '+123');
+
+ sinon.stub(element, 'setLabelValue');
+ changeReply.setLabelValue('My-Label', '+1337');
+ assert.isTrue(
+ element.setLabelValue.calledWithExactly('My-Label', '+1337'));
+
+ sinon.stub(element, 'send');
+ changeReply.send(false);
+ assert.isTrue(element.send.calledWithExactly(false));
+
+ sinon.stub(element, 'setPluginMessage');
+ changeReply.showMessage('foobar');
+ assert.isTrue(element.setPluginMessage.calledWithExactly('foobar'));
+ });
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-gerrit_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-gerrit_test.html
deleted file mode 100644
index 2d87497..0000000
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-gerrit_test.html
+++ /dev/null
@@ -1,105 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-api-interface</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-js-api-interface></gr-js-api-interface>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-js-api-interface.js';
-import {pluginLoader} from './gr-plugin-loader.js';
-import {resetPlugins} from '../../../test/test-utils.js';
-import {_testOnly_initGerritPluginApi} from './gr-gerrit.js';
-
-const pluginApi = _testOnly_initGerritPluginApi();
-
-suite('gr-gerrit tests', () => {
- let element;
- let sandbox;
- let sendStub;
-
- setup(() => {
- window.clock = sinon.useFakeTimers();
- sandbox = sinon.sandbox.create();
- sendStub = sandbox.stub().returns(Promise.resolve({status: 200}));
- stub('gr-rest-api-interface', {
- getAccount() {
- return Promise.resolve({name: 'Judy Hopps'});
- },
- send(...args) {
- return sendStub(...args);
- },
- });
- element = fixture('basic');
- });
-
- teardown(() => {
- window.clock.restore();
- sandbox.restore();
- element._removeEventCallbacks();
- resetPlugins();
- });
-
- suite('proxy methods', () => {
- test('Gerrit._isPluginEnabled proxy to pluginLoader', () => {
- const stubFn = sandbox.stub();
- sandbox.stub(
- pluginLoader,
- 'isPluginEnabled',
- (...args) => stubFn(...args)
- );
- pluginApi._isPluginEnabled('test_plugin');
- assert.isTrue(stubFn.calledWith('test_plugin'));
- });
-
- test('Gerrit._isPluginLoaded proxy to pluginLoader', () => {
- const stubFn = sandbox.stub();
- sandbox.stub(
- pluginLoader,
- 'isPluginLoaded',
- (...args) => stubFn(...args)
- );
- pluginApi._isPluginLoaded('test_plugin');
- assert.isTrue(stubFn.calledWith('test_plugin'));
- });
-
- test('Gerrit._isPluginPreloaded proxy to pluginLoader', () => {
- const stubFn = sandbox.stub();
- sandbox.stub(
- pluginLoader,
- 'isPluginPreloaded',
- (...args) => stubFn(...args)
- );
- pluginApi._isPluginPreloaded('test_plugin');
- assert.isTrue(stubFn.calledWith('test_plugin'));
- });
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-gerrit_test.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-gerrit_test.js
new file mode 100644
index 0000000..e5b32f7
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-gerrit_test.js
@@ -0,0 +1,87 @@
+/**
+ * @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.
+ */
+
+import '../../../test/common-test-setup-karma.js';
+import './gr-js-api-interface.js';
+import {pluginLoader} from './gr-plugin-loader.js';
+import {resetPlugins} from '../../../test/test-utils.js';
+import {_testOnly_initGerritPluginApi} from './gr-gerrit.js';
+
+const basicFixture = fixtureFromElement('gr-js-api-interface');
+
+const pluginApi = _testOnly_initGerritPluginApi();
+
+suite('gr-gerrit tests', () => {
+ let element;
+
+ let sendStub;
+
+ setup(() => {
+ window.clock = sinon.useFakeTimers();
+
+ sendStub = sinon.stub().returns(Promise.resolve({status: 200}));
+ stub('gr-rest-api-interface', {
+ getAccount() {
+ return Promise.resolve({name: 'Judy Hopps'});
+ },
+ send(...args) {
+ return sendStub(...args);
+ },
+ });
+ element = basicFixture.instantiate();
+ });
+
+ teardown(() => {
+ window.clock.restore();
+ element._removeEventCallbacks();
+ resetPlugins();
+ });
+
+ suite('proxy methods', () => {
+ test('Gerrit._isPluginEnabled proxy to pluginLoader', () => {
+ const stubFn = sinon.stub();
+ sinon.stub(
+ pluginLoader,
+ 'isPluginEnabled')
+ .callsFake((...args) => stubFn(...args)
+ );
+ pluginApi._isPluginEnabled('test_plugin');
+ assert.isTrue(stubFn.calledWith('test_plugin'));
+ });
+
+ test('Gerrit._isPluginLoaded proxy to pluginLoader', () => {
+ const stubFn = sinon.stub();
+ sinon.stub(
+ pluginLoader,
+ 'isPluginLoaded')
+ .callsFake((...args) => stubFn(...args));
+ pluginApi._isPluginLoaded('test_plugin');
+ assert.isTrue(stubFn.calledWith('test_plugin'));
+ });
+
+ test('Gerrit._isPluginPreloaded proxy to pluginLoader', () => {
+ const stubFn = sinon.stub();
+ sinon.stub(
+ pluginLoader,
+ 'isPluginPreloaded')
+ .callsFake((...args) => stubFn(...args));
+ pluginApi._isPluginPreloaded('test_plugin');
+ assert.isTrue(stubFn.calledWith('test_plugin'));
+ });
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface-element.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface-element.js
index a98936f..43d7378 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface-element.js
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface-element.js
@@ -277,6 +277,17 @@
return layers;
}
+ disposeDiffLayers(path) {
+ for (const annotationApi of
+ this._getEventCallbacks(EventType.ANNOTATE_DIFF)) {
+ try {
+ annotationApi.disposeLayer(path);
+ } catch (err) {
+ console.error(err);
+ }
+ }
+ }
+
/**
* Retrieves coverage data possibly provided by a plugin.
*
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.js
similarity index 84%
rename from polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.html
rename to polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.js
index ea1ac91..69d635b 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.js
@@ -1,38 +1,21 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-api-interface</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-js-api-interface></gr-js-api-interface>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-js-api-interface.js';
import {BaseUrlBehavior} from '../../../behaviors/base-url-behavior/base-url-behavior.js';
import {GrPopupInterface} from '../../plugins/gr-popup-interface/gr-popup-interface.js';
@@ -42,13 +25,15 @@
import {pluginLoader} from './gr-plugin-loader.js';
import {_testOnly_initGerritPluginApi} from './gr-gerrit.js';
+const basicFixture = fixtureFromElement('gr-js-api-interface');
+
const pluginApi = _testOnly_initGerritPluginApi();
suite('gr-js-api-interface tests', () => {
let element;
let plugin;
let errorStub;
- let sandbox;
+
let getResponseObjectStub;
let sendStub;
@@ -58,9 +43,9 @@
setup(() => {
window.clock = sinon.useFakeTimers();
- sandbox = sinon.sandbox.create();
- getResponseObjectStub = sandbox.stub().returns(Promise.resolve());
- sendStub = sandbox.stub().returns(Promise.resolve({status: 200}));
+
+ getResponseObjectStub = sinon.stub().returns(Promise.resolve());
+ sendStub = sinon.stub().returns(Promise.resolve({status: 200}));
stub('gr-rest-api-interface', {
getAccount() {
return Promise.resolve({name: 'Judy Hopps'});
@@ -70,8 +55,8 @@
return sendStub(...args);
},
});
- element = fixture('basic');
- errorStub = sandbox.stub(console, 'error');
+ element = basicFixture.instantiate();
+ errorStub = sinon.stub(console, 'error');
pluginApi.install(p => { plugin = p; }, '0.1',
'http://test.com/plugins/testplugin/static/test.js');
pluginLoader.loadPlugins([]);
@@ -79,7 +64,6 @@
teardown(() => {
window.clock.restore();
- sandbox.restore();
element._removeEventCallbacks();
plugin = null;
});
@@ -242,7 +226,7 @@
_number: 42,
revisions: {def: {_number: 2}, abc: {_number: 1}},
};
- const spy = sandbox.spy();
+ const spy = sinon.spy();
pluginLoader.loadPlugins(['plugins/test.html']);
plugin.on(element.EventType.SHOW_CHANGE, spy);
element.handleEvent(element.EventType.SHOW_CHANGE,
@@ -350,7 +334,7 @@
test('getLoggedIn', done => {
// fake fetch for authCheck
- sandbox.stub(window, 'fetch', () => Promise.resolve({status: 204}));
+ sinon.stub(window, 'fetch').callsFake(() => Promise.resolve({status: 204}));
plugin.restApi().getLoggedIn()
.then(loggedIn => {
assert.isTrue(loggedIn);
@@ -371,7 +355,7 @@
test('getAdminMenuLinks', () => {
const links = [{text: 'a', url: 'b'}, {text: 'c', url: 'd'}];
- const getCallbacksStub = sandbox.stub(element, '_getEventCallbacks')
+ const getCallbacksStub = sinon.stub(element, '_getEventCallbacks')
.returns([
{getMenuLinks: () => [links[0]]},
{getMenuLinks: () => [links[1]]},
@@ -387,7 +371,7 @@
let baseUrlPlugin;
setup(() => {
- sandbox.stub(BaseUrlBehavior, 'getBaseUrl').returns('/r');
+ sinon.stub(BaseUrlBehavior, 'getBaseUrl').returns('/r');
pluginApi.install(p => { baseUrlPlugin = p; }, '0.1',
'http://test.com/r/plugins/baseurlplugin/static/test.js');
@@ -410,7 +394,7 @@
});
test('popup(moduleName) creates popup with component', () => {
- const openStub = sandbox.stub(GrPopupInterface.prototype, 'open',
+ const openStub = sinon.stub(GrPopupInterface.prototype, 'open').callsFake(
function() {
// Arrow function can't be used here, because we want to
// get properties from the instance of GrPopupInterface
@@ -426,7 +410,7 @@
test('deprecated.popup(element) creates popup with element', () => {
const el = document.createElement('div');
el.textContent = 'some text here';
- const openStub = sandbox.stub(GrPopupInterface.prototype, 'open');
+ const openStub = sinon.stub(GrPopupInterface.prototype, 'open');
openStub.returns(Promise.resolve({
_getElement() {
return document.createElement('div');
@@ -445,15 +429,15 @@
change = {};
revision = {};
actionDetails = {__key: 'some'};
- sandbox.stub(plugin, 'on').callsArgWith(1, change, revision);
- sandbox.stub(plugin, 'changeActions').returns({
- addTapListener: sandbox.stub().callsArg(1),
+ sinon.stub(plugin, 'on').callsArgWith(1, change, revision);
+ sinon.stub(plugin, 'changeActions').returns({
+ addTapListener: sinon.stub().callsArg(1),
getActionDetails: () => actionDetails,
});
});
test('returns GrPluginActionContext', () => {
- const stub = sandbox.stub();
+ const stub = sinon.stub();
plugin.deprecated.onAction('change', 'foo', ctx => {
assert.isTrue(ctx instanceof GrPluginActionContext);
assert.strictEqual(ctx.change, change);
@@ -466,7 +450,7 @@
});
test('other actions', () => {
- const stub = sandbox.stub();
+ const stub = sinon.stub();
plugin.deprecated.onAction('project', 'foo', stub);
plugin.deprecated.onAction('edit', 'foo', stub);
plugin.deprecated.onAction('branch', 'foo', stub);
@@ -476,7 +460,7 @@
suite('screen', () => {
test('screenUrl()', () => {
- sandbox.stub(BaseUrlBehavior, 'getBaseUrl').returns('/base');
+ sinon.stub(BaseUrlBehavior, 'getBaseUrl').returns('/base');
assert.equal(
plugin.screenUrl(),
`${location.origin}/base/x/testplugin`
@@ -488,9 +472,9 @@
});
test('deprecated works', () => {
- const stub = sandbox.stub();
- const hookStub = {onAttached: sandbox.stub()};
- sandbox.stub(plugin, 'hook').returns(hookStub);
+ const stub = sinon.stub();
+ const hookStub = {onAttached: sinon.stub()};
+ sinon.stub(plugin, 'hook').returns(hookStub);
plugin.deprecated.screen('foo', stub);
assert.isTrue(plugin.hook.calledWith('testplugin-screen-foo'));
const fakeEl = {style: {display: ''}};
@@ -500,7 +484,7 @@
});
test('works', () => {
- sandbox.stub(plugin, 'registerCustomComponent');
+ sinon.stub(plugin, 'registerCustomComponent');
plugin.screen('foo', 'some-module');
assert.isTrue(plugin.registerCustomComponent.calledWith(
'testplugin-screen-foo', 'some-module'));
@@ -513,8 +497,8 @@
setup(()=> {
fakeEl = {change: {}, revision: {}};
- const hookStub = {onAttached: sandbox.stub()};
- sandbox.stub(plugin, 'hook').returns(hookStub);
+ const hookStub = {onAttached: sinon.stub()};
+ sinon.stub(plugin, 'hook').returns(hookStub);
emulateAttached = () => hookStub.onAttached.callArgWith(0, fakeEl);
});
@@ -528,7 +512,7 @@
['CHANGE_SCREEN_BELOW_CHANGE_INFO_BLOCK', 'change-metadata-item'],
].forEach(([panelName, endpointName]) => {
test(`deprecated.panel works for ${panelName}`, () => {
- const callback = sandbox.stub();
+ const callback = sinon.stub();
plugin.deprecated.panel(panelName, callback);
assert.isTrue(plugin.hook.calledWith(endpointName));
emulateAttached();
@@ -553,15 +537,15 @@
});
test('plugin.deprecated.settingsScreen() works', () => {
- const hookStub = {onAttached: sandbox.stub()};
- sandbox.stub(plugin, 'hook').returns(hookStub);
+ const hookStub = {onAttached: sinon.stub()};
+ sinon.stub(plugin, 'hook').returns(hookStub);
const fakeSettings = {};
- fakeSettings.title = sandbox.stub().returns(fakeSettings);
- fakeSettings.token = sandbox.stub().returns(fakeSettings);
- fakeSettings.module = sandbox.stub().returns(fakeSettings);
- fakeSettings.build = sandbox.stub().returns(hookStub);
- sandbox.stub(plugin, 'settings').returns(fakeSettings);
- const callback = sandbox.stub();
+ fakeSettings.title = sinon.stub().returns(fakeSettings);
+ fakeSettings.token = sinon.stub().returns(fakeSettings);
+ fakeSettings.module = sinon.stub().returns(fakeSettings);
+ fakeSettings.build = sinon.stub().returns(hookStub);
+ sinon.stub(plugin, 'settings').returns(fakeSettings);
+ const callback = sinon.stub();
plugin.deprecated.settingsScreen('path', 'menu', callback);
assert.isTrue(fakeSettings.title.calledWith('menu'));
@@ -574,7 +558,7 @@
style: {
display: '',
},
- querySelector: sandbox.stub().returns(fakeBody),
+ querySelector: sinon.stub().returns(fakeBody),
};
// Emulate settings screen attached
hookStub.onAttached.callArgWith(0, fakeEl);
@@ -585,4 +569,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-action-context_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-action-context_test.html
deleted file mode 100644
index 08c784ab..0000000
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-action-context_test.html
+++ /dev/null
@@ -1,163 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-plugin-action-context</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <div></div>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-js-api-interface.js';
-import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
-import {GrPluginActionContext} from './gr-plugin-action-context.js';
-import {_testOnly_initGerritPluginApi} from './gr-gerrit.js';
-
-const pluginApi = _testOnly_initGerritPluginApi();
-
-suite('gr-plugin-action-context tests', () => {
- let instance;
- let sandbox;
- let plugin;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- pluginApi.install(p => { plugin = p; }, '0.1',
- 'http://test.com/plugins/testplugin/static/test.js');
- instance = new GrPluginActionContext(plugin);
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('popup() and hide()', () => {
- const popupApiStub = {
- close: sandbox.stub(),
- };
- sandbox.stub(plugin.deprecated, 'popup').returns(popupApiStub);
- const el = {};
- instance.popup(el);
- assert.isTrue(instance.plugin.deprecated.popup.calledWith(el));
-
- instance.hide();
- assert.isTrue(popupApiStub.close.called);
- });
-
- test('textfield', () => {
- assert.equal(instance.textfield().tagName, 'PAPER-INPUT');
- });
-
- test('br', () => {
- assert.equal(instance.br().tagName, 'BR');
- });
-
- test('msg', () => {
- const el = instance.msg('foobar');
- assert.equal(el.tagName, 'GR-LABEL');
- assert.equal(el.textContent, 'foobar');
- });
-
- test('div', () => {
- const el1 = document.createElement('span');
- el1.textContent = 'foo';
- const el2 = document.createElement('div');
- el2.textContent = 'bar';
- const div = instance.div(el1, el2);
- assert.equal(div.tagName, 'DIV');
- assert.equal(div.textContent, 'foobar');
- });
-
- test('button', done => {
- const clickStub = sandbox.stub();
- const button = instance.button('foo', {onclick: clickStub});
- // If you don't attach a Polymer element to the DOM, then the ready()
- // callback will not be called and then e.g. this.$ is undefined.
- dom(document.body).appendChild(button);
- MockInteractions.tap(button);
- flush(() => {
- assert.isTrue(clickStub.called);
- assert.equal(button.textContent, 'foo');
- done();
- });
- });
-
- test('checkbox', () => {
- const el = instance.checkbox();
- assert.equal(el.tagName, 'INPUT');
- assert.equal(el.type, 'checkbox');
- });
-
- test('label', () => {
- const fakeMsg = {};
- const fakeCheckbox = {};
- sandbox.stub(instance, 'div');
- sandbox.stub(instance, 'msg').returns(fakeMsg);
- instance.label(fakeCheckbox, 'foo');
- assert.isTrue(instance.div.calledWithExactly(fakeCheckbox, fakeMsg));
- });
-
- test('call', () => {
- instance.action = {
- method: 'METHOD',
- __key: 'key',
- __url: '/changes/1/revisions/2/foo~bar',
- };
- const sendStub = sandbox.stub().returns(Promise.resolve());
- sandbox.stub(plugin, 'restApi').returns({
- send: sendStub,
- });
- const payload = {foo: 'foo'};
- const successStub = sandbox.stub();
- instance.call(payload, successStub);
- assert.isTrue(sendStub.calledWith(
- 'METHOD', '/changes/1/revisions/2/foo~bar', payload));
- });
-
- test('call error', done => {
- instance.action = {
- method: 'METHOD',
- __key: 'key',
- __url: '/changes/1/revisions/2/foo~bar',
- };
- const sendStub = sandbox.stub().returns(Promise.reject(new Error('boom')));
- sandbox.stub(plugin, 'restApi').returns({
- send: sendStub,
- });
- const errorStub = sandbox.stub();
- document.addEventListener('show-alert', errorStub);
- instance.call();
- flush(() => {
- assert.isTrue(errorStub.calledOnce);
- assert.equal(errorStub.args[0][0].detail.message,
- 'Plugin network error: Error: boom');
- done();
- });
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-action-context_test.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-action-context_test.js
new file mode 100644
index 0000000..dde3c04
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-action-context_test.js
@@ -0,0 +1,152 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-js-api-interface.js';
+import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+import {GrPluginActionContext} from './gr-plugin-action-context.js';
+import {_testOnly_initGerritPluginApi} from './gr-gerrit.js';
+
+const pluginApi = _testOnly_initGerritPluginApi();
+
+suite('gr-plugin-action-context tests', () => {
+ let instance;
+
+ let plugin;
+
+ setup(() => {
+ pluginApi.install(p => { plugin = p; }, '0.1',
+ 'http://test.com/plugins/testplugin/static/test.js');
+ instance = new GrPluginActionContext(plugin);
+ });
+
+ test('popup() and hide()', () => {
+ const popupApiStub = {
+ close: sinon.stub(),
+ };
+ sinon.stub(plugin.deprecated, 'popup').returns(popupApiStub);
+ const el = {};
+ instance.popup(el);
+ assert.isTrue(instance.plugin.deprecated.popup.calledWith(el));
+
+ instance.hide();
+ assert.isTrue(popupApiStub.close.called);
+ });
+
+ test('textfield', () => {
+ assert.equal(instance.textfield().tagName, 'PAPER-INPUT');
+ });
+
+ test('br', () => {
+ assert.equal(instance.br().tagName, 'BR');
+ });
+
+ test('msg', () => {
+ const el = instance.msg('foobar');
+ assert.equal(el.tagName, 'GR-LABEL');
+ assert.equal(el.textContent, 'foobar');
+ });
+
+ test('div', () => {
+ const el1 = document.createElement('span');
+ el1.textContent = 'foo';
+ const el2 = document.createElement('div');
+ el2.textContent = 'bar';
+ const div = instance.div(el1, el2);
+ assert.equal(div.tagName, 'DIV');
+ assert.equal(div.textContent, 'foobar');
+ });
+
+ suite('button', () => {
+ let clickStub;
+ let button;
+ setup(() => {
+ clickStub = sinon.stub();
+ button = instance.button('foo', {onclick: clickStub});
+ // If you don't attach a Polymer element to the DOM, then the ready()
+ // callback will not be called and then e.g. this.$ is undefined.
+ dom(document.body).appendChild(button);
+ });
+
+ test('click', done => {
+ MockInteractions.tap(button);
+ flush(() => {
+ assert.isTrue(clickStub.called);
+ assert.equal(button.textContent, 'foo');
+ done();
+ });
+ });
+
+ teardown(() => {
+ button.remove();
+ });
+ });
+
+ test('checkbox', () => {
+ const el = instance.checkbox();
+ assert.equal(el.tagName, 'INPUT');
+ assert.equal(el.type, 'checkbox');
+ });
+
+ test('label', () => {
+ const fakeMsg = {};
+ const fakeCheckbox = {};
+ sinon.stub(instance, 'div');
+ sinon.stub(instance, 'msg').returns(fakeMsg);
+ instance.label(fakeCheckbox, 'foo');
+ assert.isTrue(instance.div.calledWithExactly(fakeCheckbox, fakeMsg));
+ });
+
+ test('call', () => {
+ instance.action = {
+ method: 'METHOD',
+ __key: 'key',
+ __url: '/changes/1/revisions/2/foo~bar',
+ };
+ const sendStub = sinon.stub().returns(Promise.resolve());
+ sinon.stub(plugin, 'restApi').returns({
+ send: sendStub,
+ });
+ const payload = {foo: 'foo'};
+ const successStub = sinon.stub();
+ instance.call(payload, successStub);
+ assert.isTrue(sendStub.calledWith(
+ 'METHOD', '/changes/1/revisions/2/foo~bar', payload));
+ });
+
+ test('call error', done => {
+ instance.action = {
+ method: 'METHOD',
+ __key: 'key',
+ __url: '/changes/1/revisions/2/foo~bar',
+ };
+ const sendStub = sinon.stub().returns(Promise.reject(new Error('boom')));
+ sinon.stub(plugin, 'restApi').returns({
+ send: sendStub,
+ });
+ const errorStub = sinon.stub();
+ document.addEventListener('show-alert', errorStub);
+ instance.call();
+ flush(() => {
+ assert.isTrue(errorStub.calledOnce);
+ assert.equal(errorStub.args[0][0].detail.message,
+ 'Plugin network error: Error: boom');
+ done();
+ });
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints.js
index 0727397..2c97df0 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints.js
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints.js
@@ -16,151 +16,201 @@
*/
import {pluginLoader} from './gr-plugin-loader.js';
+import {importHref} from '../../../scripts/import-href.js';
/** @constructor */
-export function GrPluginEndpoints() {
- this._endpoints = {};
- this._callbacks = {};
- this._dynamicPlugins = {};
-}
-
-GrPluginEndpoints.prototype.onNewEndpoint = function(endpoint, callback) {
- if (!this._callbacks[endpoint]) {
- this._callbacks[endpoint] = [];
+export class GrPluginEndpoints {
+ constructor() {
+ this._endpoints = {};
+ this._callbacks = {};
+ this._dynamicPlugins = {};
+ this._importedUrls = new Set();
}
- this._callbacks[endpoint].push(callback);
-};
-GrPluginEndpoints.prototype.onDetachedEndpoint = function(endpoint,
- callback) {
- if (this._callbacks[endpoint]) {
- this._callbacks[endpoint] = this._callbacks[endpoint]
- .filter(cb => cb !== callback);
- }
-};
-
-GrPluginEndpoints.prototype._getOrCreateModuleInfo = function(plugin, opts) {
- const {endpoint, slot, type, moduleName, domHook} = opts;
- const existingModule = this._endpoints[endpoint].find(info =>
- info.plugin === plugin &&
- info.moduleName === moduleName &&
- info.domHook === domHook &&
- info.slot === slot
- );
- if (existingModule) {
- return existingModule;
- } else {
- const newModule = {
- moduleName,
- plugin,
- pluginUrl: plugin._url,
- type,
- domHook,
- slot,
- };
- this._endpoints[endpoint].push(newModule);
- return newModule;
- }
-};
-
-/**
- * Register a plugin to an endpoint.
- *
- * Dynamic plugins are registered to a specific prefix, such as
- * 'change-list-header'. These plugins are then fetched by prefix to determine
- * which endpoints to dynamically add to the page.
- *
- * @param {Object} plugin
- * @param {Object} opts
- */
-GrPluginEndpoints.prototype.registerModule = function(plugin, opts) {
- const {endpoint, dynamicEndpoint} = opts;
- if (dynamicEndpoint) {
- if (!this._dynamicPlugins[dynamicEndpoint]) {
- this._dynamicPlugins[dynamicEndpoint] = new Set();
+ onNewEndpoint(endpoint, callback) {
+ if (!this._callbacks[endpoint]) {
+ this._callbacks[endpoint] = [];
}
- this._dynamicPlugins[dynamicEndpoint].add(endpoint);
+ this._callbacks[endpoint].push(callback);
}
- if (!this._endpoints[endpoint]) {
- this._endpoints[endpoint] = [];
- }
- const moduleInfo = this._getOrCreateModuleInfo(plugin, opts);
- if (pluginLoader.arePluginsLoaded() && this._callbacks[endpoint]) {
- this._callbacks[endpoint].forEach(callback => callback(moduleInfo));
- }
-};
-GrPluginEndpoints.prototype.getDynamicEndpoints = function(dynamicEndpoint) {
- const plugins = this._dynamicPlugins[dynamicEndpoint];
- if (!plugins) return [];
- return Array.from(plugins);
-};
-
-/**
- * Get detailed information about modules registered with an extension
- * endpoint.
- *
- * @param {string} name Endpoint name.
- * @param {?{
- * type: (string|undefined),
- * moduleName: (string|undefined)
- * }} opt_options
- * @return {!Array<{
- * moduleName: string,
- * plugin: Plugin,
- * pluginUrl: String,
- * type: EndpointType,
- * domHook: !Object
- * }>}
- */
-GrPluginEndpoints.prototype.getDetails = function(name, opt_options) {
- const type = opt_options && opt_options.type;
- const moduleName = opt_options && opt_options.moduleName;
- if (!this._endpoints[name]) {
- return [];
+ onDetachedEndpoint(endpoint, callback) {
+ if (this._callbacks[endpoint]) {
+ this._callbacks[endpoint] = this._callbacks[endpoint].filter(
+ cb => cb !== callback
+ );
+ }
}
- return this._endpoints[name]
- .filter(item => (!type || item.type === type) &&
- (!moduleName || moduleName == item.moduleName));
-};
-/**
- * Get detailed module names for instantiating at the endpoint.
- *
- * @param {string} name Endpoint name.
- * @param {?{
- * type: (string|undefined),
- * moduleName: (string|undefined)
- * }} opt_options
- * @return {!Array<string>}
- */
-GrPluginEndpoints.prototype.getModules = function(name, opt_options) {
- const modulesData = this.getDetails(name, opt_options);
- if (!modulesData.length) {
- return [];
+ _getOrCreateModuleInfo(plugin, opts) {
+ const {endpoint, slot, type, moduleName, domHook} = opts;
+ const existingModule = this._endpoints[endpoint].find(
+ info =>
+ info.plugin === plugin &&
+ info.moduleName === moduleName &&
+ info.domHook === domHook &&
+ info.slot === slot
+ );
+ if (existingModule) {
+ return existingModule;
+ } else {
+ const newModule = {
+ moduleName,
+ plugin,
+ pluginUrl: plugin._url,
+ type,
+ domHook,
+ slot,
+ };
+ this._endpoints[endpoint].push(newModule);
+ return newModule;
+ }
}
- return modulesData.map(m => m.moduleName);
-};
-/**
- * Get .html plugin URLs with element and module definitions.
- *
- * @param {string} name Endpoint name.
- * @param {?{
- * type: (string|undefined),
- * moduleName: (string|undefined)
- * }} opt_options
- * @return {!Array<!URL>}
- */
-GrPluginEndpoints.prototype.getPlugins = function(name, opt_options) {
- const modulesData =
- this.getDetails(name, opt_options).filter(
- data => data.pluginUrl.pathname.includes('.html'));
- if (!modulesData.length) {
- return [];
+ /**
+ * Register a plugin to an endpoint.
+ *
+ * Dynamic plugins are registered to a specific prefix, such as
+ * 'change-list-header'. These plugins are then fetched by prefix to determine
+ * which endpoints to dynamically add to the page.
+ *
+ * @param {Object} plugin
+ * @param {Object} opts
+ */
+ registerModule(plugin, opts) {
+ const {endpoint, dynamicEndpoint} = opts;
+ if (dynamicEndpoint) {
+ if (!this._dynamicPlugins[dynamicEndpoint]) {
+ this._dynamicPlugins[dynamicEndpoint] = new Set();
+ }
+ this._dynamicPlugins[dynamicEndpoint].add(endpoint);
+ }
+ if (!this._endpoints[endpoint]) {
+ this._endpoints[endpoint] = [];
+ }
+ const moduleInfo = this._getOrCreateModuleInfo(plugin, opts);
+ if (pluginLoader.arePluginsLoaded() && this._callbacks[endpoint]) {
+ this._callbacks[endpoint].forEach(callback => callback(moduleInfo));
+ }
}
- return Array.from(new Set(modulesData.map(m => m.pluginUrl)));
-};
+
+ getDynamicEndpoints(dynamicEndpoint) {
+ const plugins = this._dynamicPlugins[dynamicEndpoint];
+ if (!plugins) return [];
+ return Array.from(plugins);
+ }
+
+ /**
+ * Get detailed information about modules registered with an extension
+ * endpoint.
+ *
+ * @param {string} name Endpoint name.
+ * @param {?{
+ * type: (string|undefined),
+ * moduleName: (string|undefined)
+ * }} opt_options
+ * @return {!Array<{
+ * moduleName: string,
+ * plugin: Plugin,
+ * pluginUrl: String,
+ * type: EndpointType,
+ * domHook: !Object
+ * }>}
+ */
+ getDetails(name, opt_options) {
+ const type = opt_options && opt_options.type;
+ const moduleName = opt_options && opt_options.moduleName;
+ if (!this._endpoints[name]) {
+ return [];
+ }
+ return this._endpoints[name].filter(
+ item =>
+ (!type || item.type === type) &&
+ (!moduleName || moduleName == item.moduleName)
+ );
+ }
+
+ /**
+ * Get detailed module names for instantiating at the endpoint.
+ *
+ * @param {string} name Endpoint name.
+ * @param {?{
+ * type: (string|undefined),
+ * moduleName: (string|undefined)
+ * }} opt_options
+ * @return {!Array<string>}
+ */
+ getModules(name, opt_options) {
+ const modulesData = this.getDetails(name, opt_options);
+ if (!modulesData.length) {
+ return [];
+ }
+ return modulesData.map(m => m.moduleName);
+ }
+
+ /**
+ * Get plugin URLs with element and module definitions.
+ *
+ * @param {string} name Endpoint name.
+ * @param {?{
+ * type: (string|undefined),
+ * moduleName: (string|undefined)
+ * }} opt_options
+ * @return {!Array<!URL>}
+ */
+ getPlugins(name, opt_options) {
+ const modulesData = this.getDetails(name, opt_options);
+ if (!modulesData.length) {
+ return [];
+ }
+ return Array.from(new Set(modulesData.map(m => m.pluginUrl)));
+ }
+
+ importUrl(pluginUrl) {
+ let timerId;
+ return Promise
+ .race([
+ new Promise((resolve, reject) => {
+ this._importedUrls.add(pluginUrl.href);
+ importHref(pluginUrl, resolve, reject);
+ }),
+ // Timeout after 3s
+ new Promise(r => timerId = setTimeout(r, 3000)),
+ ])
+ .finally(() => {
+ if (timerId) clearTimeout(timerId);
+ });
+ }
+
+ /**
+ * Get plugin URLs with element and module definitions.
+ *
+ * @param {string} name Endpoint name.
+ * @param {?{
+ * type: (string|undefined),
+ * moduleName: (string|undefined)
+ * }} opt_options
+ * @return {!Array<!Promise<void>>}
+ */
+ getAndImportPlugins(name, opt_options) {
+ return Promise.all(
+ this.getPlugins(name, opt_options).map(pluginUrl => {
+ if (this._importedUrls.has(pluginUrl.href)) {
+ return Promise.resolve();
+ }
+
+ // TODO: we will deprecate html plugins entirely
+ // for now, keep the original behavior and import
+ // only for html ones
+ if (pluginUrl && pluginUrl.pathname.endsWith('.html')) {
+ return this.importUrl(pluginUrl);
+ } else {
+ return Promise.resolve();
+ }
+ })
+ );
+ }
+}
// TODO(dmfilippov): Convert to service and add to appContext
export let pluginEndpoints = new GrPluginEndpoints();
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints_test.js
similarity index 72%
rename from polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints_test.html
rename to polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints_test.js
index 3494e99..f1af433 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints_test.js
@@ -1,32 +1,22 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-plugin-endpoints</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
+import {resetPlugins} from '../../../test/test-utils.js';
import './gr-js-api-interface.js';
import {GrPluginEndpoints} from './gr-plugin-endpoints.js';
import {pluginLoader} from './gr-plugin-loader.js';
@@ -35,14 +25,12 @@
const pluginApi = _testOnly_initGerritPluginApi();
suite('gr-plugin-endpoints tests', () => {
- let sandbox;
let instance;
let pluginFoo;
let pluginBar;
let domHook;
setup(() => {
- sandbox = sinon.sandbox.create();
domHook = {};
instance = new GrPluginEndpoints();
pluginApi.install(p => { pluginFoo = p; }, '0.1',
@@ -67,11 +55,12 @@
domHook,
}
);
- sandbox.stub(pluginLoader, 'arePluginsLoaded').returns(true);
+ sinon.stub(pluginLoader, 'arePluginsLoaded').returns(true);
+ sinon.spy(instance, 'importUrl');
});
teardown(() => {
- sandbox.restore();
+ resetPlugins();
});
test('getDetails all', () => {
@@ -133,8 +122,16 @@
instance.getPlugins('a-place'), [pluginFoo._url]);
});
+ test('getAndImportPlugins', () => {
+ instance.getAndImportPlugins('a-place');
+ assert.isTrue(instance.importUrl.called);
+ assert.isTrue(instance.importUrl.calledOnce);
+ instance.getAndImportPlugins('a-place');
+ assert.isTrue(instance.importUrl.calledOnce);
+ });
+
test('onNewEndpoint', () => {
- const newModuleStub = sandbox.stub();
+ const newModuleStub = sinon.stub();
instance.onNewEndpoint('a-place', newModuleStub);
instance.registerModule(
pluginFoo,
@@ -177,4 +174,3 @@
]);
});
});
-</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader.js
index 6c5546e..fed91de 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader.js
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader.js
@@ -245,7 +245,7 @@
this._plugins.get(key).state = state;
} else {
// Plugin is not recorded for some reason.
- console.warn(`Plugin loaded separately: ${pluginUrl}`);
+ console.info(`Plugin loaded separately: ${pluginUrl}`);
this._plugins.set(key, {
name: key,
url: pluginUrl,
@@ -375,7 +375,8 @@
}
// theme is per host, should always load from assetsPath
- const isThemeFile = pathOrUrl.endsWith('static/gerrit-theme.html');
+ const isThemeFile = pathOrUrl.endsWith('static/gerrit-theme.html') ||
+ pathOrUrl.endsWith('static/gerrit-theme.js');
const shouldTryLoadFromAssetsPathFirst = !isThemeFile && assetsPath;
if (pathOrUrl.startsWith(PRELOADED_PROTOCOL) ||
pathOrUrl.startsWith('http')) {
@@ -416,7 +417,7 @@
() => {
reject(new Error(this._timeout()));
}, PLUGIN_LOADING_TIMEOUT_MS)),
- ]).then(() => {
+ ]).finally(() => {
if (timerId) clearTimeout(timerId);
});
}
@@ -445,4 +446,5 @@
export let pluginLoader = new PluginLoader();
export function _testOnly_resetPluginLoader() {
pluginLoader = new PluginLoader();
+ return pluginLoader;
}
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader_test.js
similarity index 78%
rename from polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader_test.html
rename to polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader_test.js
index ea1fcf2..e8839d6 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader_test.js
@@ -1,58 +1,44 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-plugin-host</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-js-api-interface></gr-js-api-interface>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-js-api-interface.js';
import {BaseUrlBehavior} from '../../../behaviors/base-url-behavior/base-url-behavior.js';
import {PRELOADED_PROTOCOL, PLUGIN_LOADING_TIMEOUT_MS} from './gr-api-utils.js';
-import {pluginLoader} from './gr-plugin-loader.js';
+import {_testOnly_resetPluginLoader} from './gr-plugin-loader.js';
import {resetPlugins} from '../../../test/test-utils.js';
import {_testOnly_flushPreinstalls} from './gr-gerrit.js';
import {_testOnly_initGerritPluginApi} from './gr-gerrit.js';
+const basicFixture = fixtureFromElement('gr-js-api-interface');
+
const pluginApi = _testOnly_initGerritPluginApi();
suite('gr-plugin-loader tests', () => {
let plugin;
- let sandbox;
+
let url;
let sendStub;
+ let pluginLoader;
setup(() => {
window.clock = sinon.useFakeTimers();
- sandbox = sinon.sandbox.create();
- sendStub = sandbox.stub().returns(Promise.resolve({status: 200}));
+
+ sendStub = sinon.stub().returns(Promise.resolve({status: 200}));
stub('gr-rest-api-interface', {
getAccount() {
return Promise.resolve({name: 'Judy Hopps'});
@@ -61,13 +47,13 @@
return sendStub(...args);
},
});
- sandbox.stub(document.body, 'appendChild');
- fixture('basic');
+ pluginLoader = _testOnly_resetPluginLoader();
+ sinon.stub(document.body, 'appendChild');
+ basicFixture.instantiate();
url = window.location.origin;
});
teardown(() => {
- sandbox.restore();
window.clock.restore();
resetPlugins();
});
@@ -86,25 +72,25 @@
assert.doesNotThrow(() => {
_testOnly_flushPreinstalls();
});
- window.Gerrit.flushPreinstalls = sandbox.stub();
+ window.Gerrit.flushPreinstalls = sinon.stub();
_testOnly_flushPreinstalls();
assert.isTrue(window.Gerrit.flushPreinstalls.calledOnce);
delete window.Gerrit.flushPreinstalls;
});
test('versioning', () => {
- const callback = sandbox.spy();
+ const callback = sinon.spy();
pluginApi.install(callback, '0.0pre-alpha');
assert(callback.notCalled);
});
test('report pluginsLoaded', done => {
- const pluginsLoadedStub = sandbox.stub(pluginLoader._getReporting(),
+ const pluginsLoadedStub = sinon.stub(pluginLoader._getReporting(),
'pluginsLoaded');
pluginsLoadedStub.reset();
window.Gerrit._loadPlugins([]);
flush(() => {
- assert.isTrue(pluginsLoadedStub.calledOnce);
+ assert.isTrue(pluginsLoadedStub.called);
done();
});
});
@@ -128,10 +114,10 @@
});
test('plugins installed successfully', done => {
- sandbox.stub(pluginLoader, '_loadJsPlugin', url => {
+ sinon.stub(pluginLoader, '_loadJsPlugin').callsFake( url => {
pluginApi.install(() => void 0, undefined, url);
});
- const pluginsLoadedStub = sandbox.stub(pluginLoader._getReporting(),
+ const pluginsLoadedStub = sinon.stub(pluginLoader._getReporting(),
'pluginsLoaded');
const plugins = [
@@ -148,7 +134,7 @@
});
test('isPluginEnabled and isPluginLoaded', done => {
- sandbox.stub(pluginLoader, '_loadJsPlugin', url => {
+ sinon.stub(pluginLoader, '_loadJsPlugin').callsFake( url => {
pluginApi.install(() => void 0, undefined, url);
});
@@ -178,10 +164,10 @@
'http://test.com/plugins/bar/static/test.js',
];
- const alertStub = sandbox.stub();
+ const alertStub = sinon.stub();
document.addEventListener('show-alert', alertStub);
- sandbox.stub(pluginLoader, '_loadJsPlugin', url => {
+ sinon.stub(pluginLoader, '_loadJsPlugin').callsFake( url => {
pluginApi.install(() => {
if (url === plugins[0]) {
throw new Error('failed');
@@ -189,7 +175,7 @@
}, undefined, url);
});
- const pluginsLoadedStub = sandbox.stub(pluginLoader._getReporting(),
+ const pluginsLoadedStub = sinon.stub(pluginLoader._getReporting(),
'pluginsLoaded');
pluginLoader.loadPlugins(plugins);
@@ -208,10 +194,10 @@
'http://test.com/plugins/bar/static/test.js',
];
- const alertStub = sandbox.stub();
+ const alertStub = sinon.stub();
document.addEventListener('show-alert', alertStub);
- sandbox.stub(pluginLoader, '_loadJsPlugin', url => {
+ sinon.stub(pluginLoader, '_loadJsPlugin').callsFake( url => {
pluginApi.install(() => {
if (url === plugins[0]) {
throw new Error('failed');
@@ -219,7 +205,7 @@
}, undefined, url);
});
- const pluginsLoadedStub = sandbox.stub(pluginLoader._getReporting(),
+ const pluginsLoadedStub = sinon.stub(pluginLoader._getReporting(),
'pluginsLoaded');
pluginLoader.loadPlugins(plugins);
@@ -243,16 +229,16 @@
'http://test.com/plugins/bar/static/test.js',
];
- const alertStub = sandbox.stub();
+ const alertStub = sinon.stub();
document.addEventListener('show-alert', alertStub);
- sandbox.stub(pluginLoader, '_loadJsPlugin', url => {
+ sinon.stub(pluginLoader, '_loadJsPlugin').callsFake( url => {
pluginApi.install(() => {
throw new Error('failed');
}, undefined, url);
});
- const pluginsLoadedStub = sandbox.stub(pluginLoader._getReporting(),
+ const pluginsLoadedStub = sinon.stub(pluginLoader._getReporting(),
'pluginsLoaded');
pluginLoader.loadPlugins(plugins);
@@ -271,15 +257,15 @@
'http://test.com/plugins/bar/static/test.js',
];
- const alertStub = sandbox.stub();
+ const alertStub = sinon.stub();
document.addEventListener('show-alert', alertStub);
- sandbox.stub(pluginLoader, '_loadJsPlugin', url => {
+ sinon.stub(pluginLoader, '_loadJsPlugin').callsFake( url => {
pluginApi.install(() => {
}, url === plugins[0] ? '' : 'alpha', url);
});
- const pluginsLoadedStub = sandbox.stub(pluginLoader._getReporting(),
+ const pluginsLoadedStub = sinon.stub(pluginLoader._getReporting(),
'pluginsLoaded');
pluginLoader.loadPlugins(plugins);
@@ -293,10 +279,10 @@
});
test('multiple assets for same plugin installed successfully', done => {
- sandbox.stub(pluginLoader, '_loadJsPlugin', url => {
+ sinon.stub(pluginLoader, '_loadJsPlugin').callsFake( url => {
pluginApi.install(() => void 0, undefined, url);
});
- const pluginsLoadedStub = sandbox.stub(pluginLoader._getReporting(),
+ const pluginsLoadedStub = sinon.stub(pluginLoader._getReporting(),
'pluginsLoaded');
const plugins = [
@@ -317,19 +303,19 @@
let importHtmlPluginStub;
let loadJsPluginStub;
setup(() => {
- importHtmlPluginStub = sandbox.stub();
- sandbox.stub(pluginLoader, '_loadHtmlPlugin', url => {
+ importHtmlPluginStub = sinon.stub();
+ sinon.stub(pluginLoader, '_loadHtmlPlugin').callsFake( url => {
importHtmlPluginStub(url);
});
- loadJsPluginStub = sandbox.stub();
- sandbox.stub(pluginLoader, '_createScriptTag', url => {
+ loadJsPluginStub = sinon.stub();
+ sinon.stub(pluginLoader, '_createScriptTag').callsFake( url => {
loadJsPluginStub(url);
});
});
test('invalid plugin path', () => {
- const failToLoadStub = sandbox.stub();
- sandbox.stub(pluginLoader, '_failToLoad', (...args) => {
+ const failToLoadStub = sinon.stub();
+ sinon.stub(pluginLoader, '_failToLoad').callsFake((...args) => {
failToLoadStub(...args);
});
@@ -362,7 +348,7 @@
test('relative path should honor getBaseUrl', () => {
const testUrl = '/test';
- sandbox.stub(BaseUrlBehavior, 'getBaseUrl', () => testUrl);
+ sinon.stub(BaseUrlBehavior, 'getBaseUrl').callsFake(() => testUrl);
pluginLoader.loadPlugins([
'foo/bar.js',
@@ -403,12 +389,12 @@
let loadJsPluginStub;
setup(() => {
window.ASSETS_PATH = 'https://cdn.com';
- importHtmlPluginStub = sandbox.stub();
- sandbox.stub(pluginLoader, '_loadHtmlPlugin', url => {
+ importHtmlPluginStub = sinon.stub();
+ sinon.stub(pluginLoader, '_loadHtmlPlugin').callsFake( url => {
importHtmlPluginStub(url);
});
- loadJsPluginStub = sandbox.stub();
- sandbox.stub(pluginLoader, '_createScriptTag', url => {
+ loadJsPluginStub = sinon.stub();
+ sinon.stub(pluginLoader, '_createScriptTag').callsFake( url => {
loadJsPluginStub(url);
});
});
@@ -484,7 +470,7 @@
installed = true;
}
}
- sandbox.stub(pluginLoader, '_loadJsPlugin', url => {
+ sinon.stub(pluginLoader, '_loadJsPlugin').callsFake( url => {
pluginApi.install(() => pluginCallback(url), undefined, url);
});
@@ -500,13 +486,16 @@
});
suite('preloaded plugins', () => {
+ teardown(() => {
+ window.Gerrit._preloadedPlugins = null;
+ });
test('skips preloaded plugins when load plugins', () => {
- const importHtmlPluginStub = sandbox.stub();
- sandbox.stub(pluginLoader, '_importHtmlPlugin', url => {
+ const importHtmlPluginStub = sinon.stub();
+ sinon.stub(pluginLoader, '_importHtmlPlugin').callsFake( url => {
importHtmlPluginStub(url);
});
- const loadJsPluginStub = sandbox.stub();
- sandbox.stub(pluginLoader, '_loadJsPlugin', url => {
+ const loadJsPluginStub = sinon.stub();
+ sinon.stub(pluginLoader, '_loadJsPlugin').callsFake( url => {
loadJsPluginStub(url);
});
@@ -532,11 +521,10 @@
assert.isTrue(
pluginLoader.isPluginPreloaded(PRELOADED_PROTOCOL + 'baz')
);
- window.Gerrit._preloadedPlugins = null;
});
test('preloaded plugins are installed', () => {
- const installStub = sandbox.stub();
+ const installStub = sinon.stub();
window.Gerrit._preloadedPlugins = {foo: installStub};
pluginLoader.installPreloadedPlugins();
assert.isTrue(installStub.called);
@@ -553,4 +541,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-rest-api.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-rest-api.js
index d84cd834..31ff8ee 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-rest-api.js
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-rest-api.js
@@ -17,6 +17,10 @@
let restApi;
+export function _testOnlyResetRestApi() {
+ restApi = null;
+}
+
function getRestApi() {
if (!restApi) {
restApi = document.createElement('gr-rest-api-interface');
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-rest-api_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-rest-api_test.js
similarity index 72%
rename from polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-rest-api_test.html
rename to polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-rest-api_test.js
index fcc3b669..53aaa1e 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-rest-api_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-rest-api_test.js
@@ -1,31 +1,21 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-plugin-rest-api</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-js-api-interface.js';
import {GrPluginRestApi} from './gr-plugin-rest-api.js';
import {_testOnly_initGerritPluginApi} from './gr-gerrit.js';
@@ -34,22 +24,21 @@
suite('gr-plugin-rest-api tests', () => {
let instance;
- let sandbox;
+
let getResponseObjectStub;
let sendStub;
let restApiStub;
setup(() => {
- sandbox = sinon.sandbox.create();
- getResponseObjectStub = sandbox.stub().returns(Promise.resolve());
- sendStub = sandbox.stub().returns(Promise.resolve({status: 200}));
+ getResponseObjectStub = sinon.stub().returns(Promise.resolve());
+ sendStub = sinon.stub().returns(Promise.resolve({status: 200}));
restApiStub = {
getAccount: () => Promise.resolve({name: 'Judy Hopps'}),
getResponseObject: getResponseObjectStub,
send: sendStub,
- getLoggedIn: sandbox.stub(),
- getVersion: sandbox.stub(),
- getConfig: sandbox.stub(),
+ getLoggedIn: sinon.stub(),
+ getVersion: sinon.stub(),
+ getConfig: sinon.stub(),
};
stub('gr-rest-api-interface', Object.keys(restApiStub).reduce((a, k) => {
a[k] = (...args) => restApiStub[k](...args);
@@ -60,10 +49,6 @@
instance = new GrPluginRestApi();
});
- teardown(() => {
- sandbox.restore();
- });
-
test('fetch', () => {
const payload = {foo: 'foo'};
return instance.fetch('HTTP_METHOD', '/url', payload).then(r => {
@@ -157,4 +142,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info_test.html b/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info_test.js
similarity index 81%
rename from polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info_test.html
rename to polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info_test.js
index b97b5b3..ee9fb13 100644
--- a/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info_test.js
@@ -1,59 +1,41 @@
-<!--
-@license
-Copyright (C) 2018 The Android Open Source Project
+/**
+ * @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.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-label-info</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-label-info></gr-label-info>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-label-info.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {isHidden} from '../../../test/test-utils.js';
+
+const basicFixture = fixtureFromElement('gr-label-info');
+
suite('gr-account-link tests', () => {
let element;
- let sandbox;
setup(() => {
- element = fixture('basic');
- sandbox = sinon.sandbox.create();
+ element = basicFixture.instantiate();
+
// Needed to trigger computed bindings.
element.account = {};
element.change = {labels: {}};
});
- teardown(() => {
- sandbox.restore();
- });
-
suite('remove reviewer votes', () => {
setup(() => {
- sandbox.stub(element, '_computeValueTooltip').returns('');
+ sinon.stub(element, '_computeValueTooltip').returns('');
element.account = {
_account_id: 1,
name: 'bojack',
@@ -91,7 +73,7 @@
test('deletes votes', () => {
const deleteResponse = Promise.resolve({ok: true});
- const deleteStub = sandbox.stub(
+ const deleteStub = sinon.stub(
element.$.restAPI, 'deleteVote').returns(deleteResponse);
element.change.removable_reviewers = [element.account];
@@ -246,4 +228,4 @@
.querySelector('.placeholder')));
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete_test.html b/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete_test.html
deleted file mode 100644
index 99a038e..0000000
--- a/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete_test.html
+++ /dev/null
@@ -1,62 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-labeled-autocomplete</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-labeled-autocomplete></gr-labeled-autocomplete>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-labeled-autocomplete.js';
-suite('gr-labeled-autocomplete tests', () => {
- let element;
- let sandbox;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- });
-
- teardown(() => { sandbox.restore(); });
-
- test('tapping trigger focuses autocomplete', () => {
- const e = {stopPropagation: () => undefined};
- sandbox.stub(e, 'stopPropagation');
- sandbox.stub(element.$.autocomplete, 'focus');
- element._handleTriggerClick(e);
- assert.isTrue(e.stopPropagation.calledOnce);
- assert.isTrue(element.$.autocomplete.focus.calledOnce);
- });
-
- test('setText', () => {
- sandbox.stub(element.$.autocomplete, 'setText');
- element.setText('foo-bar');
- assert.isTrue(element.$.autocomplete.setText.calledWith('foo-bar'));
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete_test.js b/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete_test.js
new file mode 100644
index 0000000..3e904a2
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete_test.js
@@ -0,0 +1,45 @@
+/**
+ * @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.
+ */
+
+import '../../../test/common-test-setup-karma.js';
+import './gr-labeled-autocomplete.js';
+
+const basicFixture = fixtureFromElement('gr-labeled-autocomplete');
+
+suite('gr-labeled-autocomplete tests', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ test('tapping trigger focuses autocomplete', () => {
+ const e = {stopPropagation: () => undefined};
+ sinon.stub(e, 'stopPropagation');
+ sinon.stub(element.$.autocomplete, 'focus');
+ element._handleTriggerClick(e);
+ assert.isTrue(e.stopPropagation.calledOnce);
+ assert.isTrue(element.$.autocomplete.focus.calledOnce);
+ });
+
+ test('setText', () => {
+ sinon.stub(element.$.autocomplete, 'setText');
+ element.setText('foo-bar');
+ assert.isTrue(element.$.autocomplete.setText.calledWith('foo-bar'));
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/shared/gr-lib-loader/gr-lib-loader.js b/polygerrit-ui/app/elements/shared/gr-lib-loader/gr-lib-loader.js
index e9cd441..3c3fc6a 100644
--- a/polygerrit-ui/app/elements/shared/gr-lib-loader/gr-lib-loader.js
+++ b/polygerrit-ui/app/elements/shared/gr-lib-loader/gr-lib-loader.js
@@ -15,7 +15,6 @@
* limitations under the License.
*/
import '../gr-js-api-interface/gr-js-api-interface.js';
-import {importHref} from '../../../scripts/import-href.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
@@ -23,7 +22,6 @@
import {htmlTemplate} from './gr-lib-loader_html.js';
const HLJS_PATH = 'bower_components/highlightjs/highlight.min.js';
-const DARK_THEME_PATH = 'styles/themes/dark-theme.html';
/** @extends PolymerElement */
class GrLibLoader extends GestureEventListeners(
@@ -76,28 +74,6 @@
}
/**
- * Loads the dark theme document. Returns a promise that resolves with a
- * custom-style DOM element.
- *
- * @return {!Promise<Element>}
- * @suppress {checkTypes}
- */
- getDarkTheme() {
- return new Promise((resolve, reject) => {
- importHref(
- this._getLibRoot() + DARK_THEME_PATH, () => {
- const module = document.createElement('style');
- module.setAttribute('include', 'dark-theme');
- const cs = document.createElement('custom-style');
- cs.appendChild(module);
-
- resolve(cs);
- },
- reject);
- });
- }
-
- /**
* Execute callbacks awaiting the HLJS lib load.
*/
_onHLJSLibLoaded() {
diff --git a/polygerrit-ui/app/elements/shared/gr-lib-loader/gr-lib-loader_test.html b/polygerrit-ui/app/elements/shared/gr-lib-loader/gr-lib-loader_test.js
similarity index 62%
rename from polygerrit-ui/app/elements/shared/gr-lib-loader/gr-lib-loader_test.html
rename to polygerrit-ui/app/elements/shared/gr-lib-loader/gr-lib-loader_test.js
index f2e5e3d..4231d71 100644
--- a/polygerrit-ui/app/elements/shared/gr-lib-loader/gr-lib-loader_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-lib-loader/gr-lib-loader_test.js
@@ -1,50 +1,34 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-lib-loader</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-lib-loader></gr-lib-loader>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-lib-loader.js';
+
+const basicFixture = fixtureFromElement('gr-lib-loader');
+
suite('gr-lib-loader tests', () => {
- let sandbox;
let element;
let resolveLoad;
let loadStub;
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
+ element = basicFixture.instantiate();
- loadStub = sandbox.stub(element, '_loadScript', () =>
+ loadStub = sinon.stub(element, '_loadScript').callsFake(() =>
new Promise(resolve => resolveLoad = resolve)
);
@@ -56,7 +40,6 @@
if (window.hljs) {
delete window.hljs;
}
- sandbox.restore();
// Because the element state is a singleton, clean it up.
element._hljsState.configured = false;
@@ -65,7 +48,7 @@
});
test('only load once', done => {
- sandbox.stub(element, '_getHLJSUrl').returns('');
+ sinon.stub(element, '_getHLJSUrl').returns('');
const firstCallHandler = sinon.stub();
element.getHLJS().then(firstCallHandler);
@@ -130,7 +113,7 @@
let root;
setup(() => {
- sandbox.stub(element, '_getLibRoot', () => root);
+ sinon.stub(element, '_getLibRoot').callsFake(() => root);
});
test('with no root', () => {
@@ -145,4 +128,3 @@
});
});
});
-</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-limited-text/gr-limited-text_test.html b/polygerrit-ui/app/elements/shared/gr-limited-text/gr-limited-text_test.html
deleted file mode 100644
index 889b786..0000000
--- a/polygerrit-ui/app/elements/shared/gr-limited-text/gr-limited-text_test.html
+++ /dev/null
@@ -1,103 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-limited-text</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-limited-text></gr-limited-text>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-limited-text.js';
-suite('gr-limited-text tests', () => {
- let element;
- let sandbox;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('_updateTitle', () => {
- const updateSpy = sandbox.spy(element, '_updateTitle');
- element.text = 'abc 123';
- flushAsynchronousOperations();
- assert.isTrue(updateSpy.calledOnce);
- assert.isNotOk(element.getAttribute('title'));
- assert.isFalse(element.hasTooltip);
-
- element.limit = 10;
- flushAsynchronousOperations();
- assert.isTrue(updateSpy.calledTwice);
- assert.isNotOk(element.getAttribute('title'));
- assert.isFalse(element.hasTooltip);
-
- element.limit = 3;
- flushAsynchronousOperations();
- assert.isTrue(updateSpy.calledThrice);
- assert.equal(element.getAttribute('title'), 'abc 123');
- assert.isTrue(element.hasTooltip);
-
- element.tooltipLimit = 3;
- flushAsynchronousOperations();
- assert.equal(element.getAttribute('title'), 'abc');
-
- element.tooltipLimit = 1024;
- element.limit = 100;
- flushAsynchronousOperations();
- assert.equal(updateSpy.callCount, 6);
- assert.isNotOk(element.getAttribute('title'));
- assert.isFalse(element.hasTooltip);
-
- element.limit = null;
- flushAsynchronousOperations();
- assert.equal(updateSpy.callCount, 7);
- assert.isNotOk(element.getAttribute('title'));
- assert.isFalse(element.hasTooltip);
- });
-
- test('_computeDisplayText', () => {
- assert.equal(element._computeDisplayText('foo bar', 100), 'foo bar');
- assert.equal(element._computeDisplayText('foo bar', 4), 'foo…');
- assert.equal(element._computeDisplayText('foo bar', null), 'foo bar');
- });
-
- test('when disable tooltip', () => {
- sandbox.spy(element, '_updateTitle');
- element.text = 'abcdefghijklmn';
- element.disableTooltip = true;
- element.limit = 10;
- flushAsynchronousOperations();
- assert.equal(element.getAttribute('title'), null);
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-limited-text/gr-limited-text_test.js b/polygerrit-ui/app/elements/shared/gr-limited-text/gr-limited-text_test.js
new file mode 100644
index 0000000..dda3324
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-limited-text/gr-limited-text_test.js
@@ -0,0 +1,83 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-limited-text.js';
+
+const basicFixture = fixtureFromElement('gr-limited-text');
+
+suite('gr-limited-text tests', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ test('_updateTitle', () => {
+ const updateSpy = sinon.spy(element, '_updateTitle');
+ element.text = 'abc 123';
+ flushAsynchronousOperations();
+ assert.isTrue(updateSpy.calledOnce);
+ assert.isNotOk(element.getAttribute('title'));
+ assert.isFalse(element.hasTooltip);
+
+ element.limit = 10;
+ flushAsynchronousOperations();
+ assert.isTrue(updateSpy.calledTwice);
+ assert.isNotOk(element.getAttribute('title'));
+ assert.isFalse(element.hasTooltip);
+
+ element.limit = 3;
+ flushAsynchronousOperations();
+ assert.isTrue(updateSpy.calledThrice);
+ assert.equal(element.getAttribute('title'), 'abc 123');
+ assert.isTrue(element.hasTooltip);
+
+ element.tooltipLimit = 3;
+ flushAsynchronousOperations();
+ assert.equal(element.getAttribute('title'), 'abc');
+
+ element.tooltipLimit = 1024;
+ element.limit = 100;
+ flushAsynchronousOperations();
+ assert.equal(updateSpy.callCount, 6);
+ assert.isNotOk(element.getAttribute('title'));
+ assert.isFalse(element.hasTooltip);
+
+ element.limit = null;
+ flushAsynchronousOperations();
+ assert.equal(updateSpy.callCount, 7);
+ assert.isNotOk(element.getAttribute('title'));
+ assert.isFalse(element.hasTooltip);
+ });
+
+ test('_computeDisplayText', () => {
+ assert.equal(element._computeDisplayText('foo bar', 100), 'foo bar');
+ assert.equal(element._computeDisplayText('foo bar', 4), 'foo…');
+ assert.equal(element._computeDisplayText('foo bar', null), 'foo bar');
+ });
+
+ test('when disable tooltip', () => {
+ sinon.spy(element, '_updateTitle');
+ element.text = 'abcdefghijklmn';
+ element.disableTooltip = true;
+ element.limit = 10;
+ flushAsynchronousOperations();
+ assert.equal(element.getAttribute('title'), null);
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/shared/gr-linked-chip/gr-linked-chip_test.html b/polygerrit-ui/app/elements/shared/gr-linked-chip/gr-linked-chip_test.html
deleted file mode 100644
index c8de3df..0000000
--- a/polygerrit-ui/app/elements/shared/gr-linked-chip/gr-linked-chip_test.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-linked-chip</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<!-- Can't use absolute path below for mock-interaction.js.
-Web component tester(wct) has a built-in http server and it serves "/components" directory (which is
-actually /node_modules directory). Also, wct patches some files to load modules from /components.
-With the absolute path, browser tries to load dom-module from 2 different places (/component/... and
-/node_modules/...) though this is actually the same file. This leads to a run-time error.
--->
-<script src="../../../node_modules/iron-test-helpers/mock-interactions.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-linked-chip></gr-linked-chip>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-linked-chip.js';
-suite('gr-linked-chip tests', () => {
- let element;
- let sandbox;
-
- setup(() => {
- element = fixture('basic');
- sandbox = sinon.sandbox.create();
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('remove fired', () => {
- const spy = sandbox.spy();
- element.addEventListener('remove', spy);
- flushAsynchronousOperations();
- MockInteractions.tap(element.$.remove);
- assert.isTrue(spy.called);
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-linked-chip/gr-linked-chip_test.js b/polygerrit-ui/app/elements/shared/gr-linked-chip/gr-linked-chip_test.js
new file mode 100644
index 0000000..b111e84
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-linked-chip/gr-linked-chip_test.js
@@ -0,0 +1,38 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-linked-chip.js';
+
+const basicFixture = fixtureFromElement('gr-linked-chip');
+
+suite('gr-linked-chip tests', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ test('remove fired', () => {
+ const spy = sinon.spy();
+ element.addEventListener('remove', spy);
+ flushAsynchronousOperations();
+ MockInteractions.tap(element.$.remove);
+ assert.isTrue(spy.called);
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/shared/gr-linked-text/gr-linked-text_test.html b/polygerrit-ui/app/elements/shared/gr-linked-text/gr-linked-text_test.js
similarity index 88%
rename from polygerrit-ui/app/elements/shared/gr-linked-text/gr-linked-text_test.html
rename to polygerrit-ui/app/elements/shared/gr-linked-text/gr-linked-text_test.js
index 4fa4390..a295d1a 100644
--- a/polygerrit-ui/app/elements/shared/gr-linked-text/gr-linked-text_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-linked-text/gr-linked-text_test.js
@@ -1,52 +1,42 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2015 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-linked-text</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-linked-text>
- <div id="output"></div>
- </gr-linked-text>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-linked-text.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const basicFixture = fixtureFromTemplate(html`
+<gr-linked-text>
+ <div id="output"></div>
+ </gr-linked-text>
+`);
suite('gr-linked-text tests', () => {
let element;
- let sandbox;
+
+ let originalCanonicalPath;
setup(() => {
- element = fixture('basic');
- sandbox = sinon.sandbox.create();
- sandbox.stub(GerritNav, 'mapCommentlinks', x => x);
+ originalCanonicalPath = window.CANONICAL_PATH;
+ element = basicFixture.instantiate();
+
+ sinon.stub(GerritNav, 'mapCommentlinks').value( x => x);
element.config = {
ph: {
match: '([Bb]ug|[Ii]ssue)\\s*#?(\\d+)',
@@ -90,7 +80,7 @@
});
teardown(() => {
- sandbox.restore();
+ window.CANONICAL_PATH = originalCanonicalPath;
});
test('URL pattern was parsed and linked.', () => {
@@ -366,11 +356,11 @@
});
test('_contentOrConfigChanged called with config', () => {
- const contentStub = sandbox.stub(element, '_contentChanged');
- const contentConfigStub = sandbox.stub(element, '_contentOrConfigChanged');
+ const contentStub = sinon.stub(element, '_contentChanged');
+ const contentConfigStub = sinon.stub(element, '_contentOrConfigChanged');
element.content = 'some text';
assert.isTrue(contentStub.called);
assert.isTrue(contentConfigStub.called);
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-list-view/gr-list-view_test.html b/polygerrit-ui/app/elements/shared/gr-list-view/gr-list-view_test.js
similarity index 68%
rename from polygerrit-ui/app/elements/shared/gr-list-view/gr-list-view_test.html
rename to polygerrit-ui/app/elements/shared/gr-list-view/gr-list-view_test.js
index 55aab82..93451ff 100644
--- a/polygerrit-ui/app/elements/shared/gr-list-view/gr-list-view_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-list-view/gr-list-view_test.js
@@ -1,52 +1,31 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-list-view</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-<script src="/node_modules/page/page.js"></script>
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-list-view></gr-list-view>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-list-view.js';
import page from 'page/page.mjs';
+const basicFixture = fixtureFromElement('gr-list-view');
+
suite('gr-list-view tests', () => {
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- });
-
- teardown(() => {
- sandbox.restore();
+ element = basicFixture.instantiate();
});
test('_computeNavLink', () => {
@@ -55,7 +34,7 @@
let filter = 'test';
const path = '/admin/projects';
- sandbox.stub(element, 'getBaseUrl', () => '');
+ sinon.stub(element, 'getBaseUrl').callsFake(() => '');
assert.equal(
element._computeNavLink(offset, 1, projectsPerPage, filter, path),
@@ -81,7 +60,7 @@
test('_onValueChange', done => {
element.path = '/admin/projects';
- sandbox.stub(page, 'show', url => {
+ sinon.stub(page, 'show').callsFake( url => {
assert.equal(url, '/admin/projects/q/filter:test');
done();
});
@@ -89,7 +68,7 @@
});
test('_filterChanged not reload when swap between falsy values', () => {
- sandbox.stub(element, '_debounceReload');
+ sinon.stub(element, '_debounceReload');
element.filter = null;
element.filter = undefined;
element.filter = '';
@@ -137,7 +116,7 @@
});
test('fires create clicked event when button tapped', () => {
- const clickHandler = sandbox.stub();
+ const clickHandler = sinon.stub();
element.addEventListener('create-clicked', clickHandler);
element.createNew = true;
flushAsynchronousOperations();
@@ -148,7 +127,7 @@
test('next/prev links change when path changes', () => {
const BRANCHES_PATH = '/path/to/branches';
const TAGS_PATH = '/path/to/tags';
- sandbox.stub(element, '_computeNavLink');
+ sinon.stub(element, '_computeNavLink');
element.offset = 0;
element.itemsPerPage = 25;
element.filter = '';
@@ -163,4 +142,4 @@
assert.equal(element._computePage(50, 25), 3);
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay_test.html b/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay_test.html
deleted file mode 100644
index d43c739..0000000
--- a/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay_test.html
+++ /dev/null
@@ -1,91 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-overlay</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/page/page.js"></script>
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-overlay>
- <div>content</div>
- </gr-overlay>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-overlay.js';
-suite('gr-overlay tests', () => {
- let element;
- let sandbox;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('events are fired on fullscreen view', done => {
- sandbox.stub(element, '_isMobile').returns(true);
- const openHandler = sandbox.stub();
- const closeHandler = sandbox.stub();
- element.addEventListener('fullscreen-overlay-opened', openHandler);
- element.addEventListener('fullscreen-overlay-closed', closeHandler);
-
- element.open().then(() => {
- assert.isTrue(element._isMobile.called);
- assert.isTrue(element._fullScreenOpen);
- assert.isTrue(openHandler.called);
-
- element._close();
- assert.isFalse(element._fullScreenOpen);
- assert.isTrue(closeHandler.called);
- done();
- });
- });
-
- test('events are not fired on desktop view', done => {
- sandbox.stub(element, '_isMobile').returns(false);
- const openHandler = sandbox.stub();
- const closeHandler = sandbox.stub();
- element.addEventListener('fullscreen-overlay-opened', openHandler);
- element.addEventListener('fullscreen-overlay-closed', closeHandler);
-
- element.open().then(() => {
- assert.isTrue(element._isMobile.called);
- assert.isFalse(element._fullScreenOpen);
- assert.isFalse(openHandler.called);
-
- element._close();
- assert.isFalse(element._fullScreenOpen);
- assert.isFalse(closeHandler.called);
- done();
- });
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay_test.js b/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay_test.js
new file mode 100644
index 0000000..f3c591b
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay_test.js
@@ -0,0 +1,73 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-overlay.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const basicFixture = fixtureFromTemplate(html`
+<gr-overlay>
+ <div>content</div>
+ </gr-overlay>
+`);
+
+suite('gr-overlay tests', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ test('events are fired on fullscreen view', done => {
+ sinon.stub(element, '_isMobile').returns(true);
+ const openHandler = sinon.stub();
+ const closeHandler = sinon.stub();
+ element.addEventListener('fullscreen-overlay-opened', openHandler);
+ element.addEventListener('fullscreen-overlay-closed', closeHandler);
+
+ element.open().then(() => {
+ assert.isTrue(element._isMobile.called);
+ assert.isTrue(element._fullScreenOpen);
+ assert.isTrue(openHandler.called);
+
+ element._close();
+ assert.isFalse(element._fullScreenOpen);
+ assert.isTrue(closeHandler.called);
+ done();
+ });
+ });
+
+ test('events are not fired on desktop view', done => {
+ sinon.stub(element, '_isMobile').returns(false);
+ const openHandler = sinon.stub();
+ const closeHandler = sinon.stub();
+ element.addEventListener('fullscreen-overlay-opened', openHandler);
+ element.addEventListener('fullscreen-overlay-closed', closeHandler);
+
+ element.open().then(() => {
+ assert.isTrue(element._isMobile.called);
+ assert.isFalse(element._fullScreenOpen);
+ assert.isFalse(openHandler.called);
+
+ element._close();
+ assert.isFalse(element._fullScreenOpen);
+ assert.isFalse(closeHandler.called);
+ done();
+ });
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/shared/gr-page-nav/gr-page-nav_test.html b/polygerrit-ui/app/elements/shared/gr-page-nav/gr-page-nav_test.html
deleted file mode 100644
index a54d7a3..0000000
--- a/polygerrit-ui/app/elements/shared/gr-page-nav/gr-page-nav_test.html
+++ /dev/null
@@ -1,89 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-page-nav</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/page/page.js"></script>
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-page-nav>
- <ul>
- <li>item</li>
- </ul>
- </gr-page-nav>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-page-nav.js';
-suite('gr-page-nav tests', () => {
- let element;
- let sandbox;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- flushAsynchronousOperations();
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('header is not pinned just below top', () => {
- sandbox.stub(element, '_getOffsetParent', () => 0);
- sandbox.stub(element, '_getOffsetTop', () => 10);
- sandbox.stub(element, '_getScrollY', () => 5);
- element._handleBodyScroll();
- assert.isFalse(element.$.nav.classList.contains('pinned'));
- });
-
- test('header is pinned when scroll down the page', () => {
- sandbox.stub(element, '_getOffsetParent', () => 0);
- sandbox.stub(element, '_getOffsetTop', () => 10);
- sandbox.stub(element, '_getScrollY', () => 25);
- window.scrollY = 100;
- element._handleBodyScroll();
- assert.isTrue(element.$.nav.classList.contains('pinned'));
- });
-
- test('header is not pinned just below top with header set', () => {
- element._headerHeight = 20;
- sandbox.stub(element, '_getScrollY', () => 15);
- window.scrollY = 100;
- element._handleBodyScroll();
- assert.isFalse(element.$.nav.classList.contains('pinned'));
- });
-
- test('header is pinned when scroll down the page with header set', () => {
- element._headerHeight = 20;
- sandbox.stub(element, '_getScrollY', () => 25);
- window.scrollY = 100;
- element._handleBodyScroll();
- assert.isTrue(element.$.nav.classList.contains('pinned'));
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-page-nav/gr-page-nav_test.js b/polygerrit-ui/app/elements/shared/gr-page-nav/gr-page-nav_test.js
new file mode 100644
index 0000000..2e40b27
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-page-nav/gr-page-nav_test.js
@@ -0,0 +1,71 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-page-nav.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const basicFixture = fixtureFromTemplate(html`
+<gr-page-nav>
+ <ul>
+ <li>item</li>
+ </ul>
+ </gr-page-nav>
+`);
+
+suite('gr-page-nav tests', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ flushAsynchronousOperations();
+ });
+
+ test('header is not pinned just below top', () => {
+ sinon.stub(element, '_getOffsetParent').callsFake(() => 0);
+ sinon.stub(element, '_getOffsetTop').callsFake(() => 10);
+ sinon.stub(element, '_getScrollY').callsFake(() => 5);
+ element._handleBodyScroll();
+ assert.isFalse(element.$.nav.classList.contains('pinned'));
+ });
+
+ test('header is pinned when scroll down the page', () => {
+ sinon.stub(element, '_getOffsetParent').callsFake(() => 0);
+ sinon.stub(element, '_getOffsetTop').callsFake(() => 10);
+ sinon.stub(element, '_getScrollY').callsFake(() => 25);
+ window.scrollY = 100;
+ element._handleBodyScroll();
+ assert.isTrue(element.$.nav.classList.contains('pinned'));
+ });
+
+ test('header is not pinned just below top with header set', () => {
+ element._headerHeight = 20;
+ sinon.stub(element, '_getScrollY').callsFake(() => 15);
+ window.scrollY = 100;
+ element._handleBodyScroll();
+ assert.isFalse(element.$.nav.classList.contains('pinned'));
+ });
+
+ test('header is pinned when scroll down the page with header set', () => {
+ element._headerHeight = 20;
+ sinon.stub(element, '_getScrollY').callsFake(() => 25);
+ window.scrollY = 100;
+ element._handleBodyScroll();
+ assert.isTrue(element.$.nav.classList.contains('pinned'));
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/shared/gr-repo-branch-picker/gr-repo-branch-picker_test.html b/polygerrit-ui/app/elements/shared/gr-repo-branch-picker/gr-repo-branch-picker_test.js
similarity index 68%
rename from polygerrit-ui/app/elements/shared/gr-repo-branch-picker/gr-repo-branch-picker_test.html
rename to polygerrit-ui/app/elements/shared/gr-repo-branch-picker/gr-repo-branch-picker_test.js
index 67b82f9..bfdbe41 100644
--- a/polygerrit-ui/app/elements/shared/gr-repo-branch-picker/gr-repo-branch-picker_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-repo-branch-picker/gr-repo-branch-picker_test.js
@@ -1,52 +1,35 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2018 The Android Open Source Project
+/**
+ * @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.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-repo-branch-picker</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-repo-branch-picker></gr-repo-branch-picker>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-repo-branch-picker.js';
+
+const basicFixture = fixtureFromElement('gr-repo-branch-picker');
+
suite('gr-repo-branch-picker tests', () => {
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
+ element = basicFixture.instantiate();
});
- teardown(() => { sandbox.restore(); });
-
suite('_getRepoSuggestions', () => {
setup(() => {
- sandbox.stub(element.$.restAPI, 'getRepos')
+ sinon.stub(element.$.restAPI, 'getRepos')
.returns(Promise.resolve([
{
id: 'plugins%2Favatars-external',
@@ -82,7 +65,7 @@
suite('_getRepoBranchesSuggestions', () => {
setup(() => {
- sandbox.stub(element.$.restAPI, 'getRepoBranches')
+ sinon.stub(element.$.restAPI, 'getRepoBranches')
.returns(Promise.resolve([
{ref: 'refs/heads/stable-2.10'},
{ref: 'refs/heads/stable-2.11'},
@@ -140,4 +123,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-auth_test.html b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-auth_test.js
similarity index 86%
rename from polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-auth_test.html
rename to polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-auth_test.js
index f3abdb0..af2efae 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-auth_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-auth_test.js
@@ -1,53 +1,37 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-auth</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import {BaseUrlBehavior} from '../../../behaviors/base-url-behavior/base-url-behavior.js';
import {Auth, authService} from './gr-auth.js';
import {appContext} from '../../../services/app-context.js';
suite('gr-auth', () => {
let auth;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
auth = authService;
});
- teardown(() => {
- sandbox.restore();
- });
-
suite('Auth class methods', () => {
let fakeFetch;
setup(() => {
auth = new Auth();
- fakeFetch = sandbox.stub(window, 'fetch');
+ fakeFetch = sinon.stub(window, 'fetch');
});
test('auth-check returns 403', done => {
@@ -93,7 +77,7 @@
setup(() => {
auth = new Auth();
clock = sinon.useFakeTimers();
- fakeFetch = sandbox.stub(window, 'fetch');
+ fakeFetch = sinon.stub(window, 'fetch');
});
test('cache auth-check result', done => {
@@ -228,7 +212,7 @@
suite('default (xsrf token header)', () => {
setup(() => {
- sandbox.stub(window, 'fetch').returns(Promise.resolve({ok: true}));
+ sinon.stub(window, 'fetch').returns(Promise.resolve({ok: true}));
});
test('GET', done => {
@@ -241,7 +225,7 @@
});
test('POST', done => {
- sandbox.stub(auth, '_getCookie')
+ sinon.stub(auth, '_getCookie')
.withArgs('XSRF_TOKEN')
.returns('foobar');
auth.fetch('/url', {method: 'POST'}).then(() => {
@@ -256,7 +240,7 @@
suite('cors (access token)', () => {
setup(() => {
- sandbox.stub(window, 'fetch').returns(Promise.resolve({ok: true}));
+ sinon.stub(window, 'fetch').returns(Promise.resolve({ok: true}));
});
let getToken;
@@ -269,14 +253,14 @@
};
setup(() => {
- getToken = sandbox.stub();
+ getToken = sinon.stub();
getToken.returns(Promise.resolve(makeToken()));
auth.setup(getToken);
});
test('base url support', done => {
const baseUrl = 'http://foo';
- sandbox.stub(BaseUrlBehavior, 'getBaseUrl').returns(baseUrl);
+ sinon.stub(BaseUrlBehavior, 'getBaseUrl').returns(baseUrl);
auth.fetch(baseUrl + '/url', {bar: 'bar'}).then(() => {
const [url] = fetch.lastCall.args;
assert.equal(url, 'http://foo/a/url?access_token=zbaz');
@@ -313,7 +297,7 @@
});
test('getToken refreshes token', done => {
- sandbox.stub(auth, '_isTokenValid');
+ sinon.stub(auth, '_isTokenValid');
auth._isTokenValid
.onFirstCall().returns(true)
.onSecondCall()
@@ -391,4 +375,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-etag-decorator_test.html b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-etag-decorator_test.js
similarity index 62%
rename from polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-etag-decorator_test.html
rename to polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-etag-decorator_test.js
index cfa164f..e5217a4 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-etag-decorator_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-etag-decorator_test.js
@@ -1,36 +1,25 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-etag-decorator</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import {GrEtagDecorator} from './gr-etag-decorator.js';
suite('gr-etag-decorator', () => {
let etag;
- let sandbox;
const fakeRequest = (opt_etag, opt_status) => {
const headers = new Headers();
@@ -42,14 +31,9 @@
};
setup(() => {
- sandbox = sinon.sandbox.create();
etag = new GrEtagDecorator();
});
- teardown(() => {
- sandbox.restore();
- });
-
test('exists', () => {
assert.isOk(etag);
});
@@ -96,4 +80,4 @@
assert.strictEqual(etag.getCachedPayload('/foo'), 'new payload');
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
index de4f12d..3c76ee1 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
@@ -45,12 +45,44 @@
const CREATE_DRAFT_UNEXPECTED_STATUS_MESSAGE =
'Saving draft resulted in HTTP 200 (OK) but expected HTTP 201 (Created)';
-const HEADER_REPORTING_BLACKLIST = /^set-cookie$/i;
+const HEADER_REPORTING_BLOCK_REGEX = /^set-cookie$/i;
const ANONYMIZED_CHANGE_BASE_URL = '/changes/*~*';
const ANONYMIZED_REVISION_BASE_URL = ANONYMIZED_CHANGE_BASE_URL +
'/revisions/*';
+let siteBasedCache = new SiteBasedCache(); // Shared across instances.
+let fetchPromisesCache = new FetchPromisesCache(); // Shared across instances.
+let pendingRequest = {}; // Shared across instances.
+let grEtagDecorator = new GrEtagDecorator; // Shared across instances.
+let projectLookup = {}; // Shared across instances.
+
+export function _testOnlyResetGrRestApiSharedObjects() {
+ for (const key in fetchPromisesCache._data) {
+ if (fetchPromisesCache._data.hasOwnProperty(key)) {
+ // reject already fulfilled promise does nothing
+ fetchPromisesCache._data[key].reject();
+ }
+ }
+
+ for (const key in pendingRequest) {
+ if (!pendingRequest.hasOwnProperty(key)) {
+ continue;
+ }
+ for (const req of pendingRequest[key]) {
+ // reject already fulfilled promise does nothing
+ req.reject();
+ }
+ }
+
+ siteBasedCache = new SiteBasedCache();
+ fetchPromisesCache = new FetchPromisesCache();
+ pendingRequest = {};
+ grEtagDecorator = new GrEtagDecorator;
+ projectLookup = {};
+ authService.clearCache();
+}
+
/**
* @extends PolymerElement
*/
@@ -89,26 +121,26 @@
return {
_cache: {
type: Object,
- value: new SiteBasedCache(), // Shared across instances.
+ value: siteBasedCache, // Shared across instances.
},
_sharedFetchPromises: {
type: Object,
- value: new FetchPromisesCache(), // Shared across instances.
+ value: fetchPromisesCache, // Shared across instances.
},
_pendingRequests: {
type: Object,
- value: {}, // Intentional to share the object across instances.
+ value: pendingRequest, // Intentional to share the object across instances.
},
_etags: {
type: Object,
- value: new GrEtagDecorator(), // Share across instances.
+ value: grEtagDecorator, // Share across instances.
},
/**
* Used to maintain a mapping of changeNums to project names.
*/
_projectLookup: {
type: Object,
- value: {}, // Intentional to share the object across instances.
+ value: projectLookup, // Intentional to share the object across instances.
},
};
}
@@ -1940,10 +1972,15 @@
}
saveChangeReviewed(changeNum, reviewed) {
- return this._getChangeURLAndSend({
- changeNum,
- method: 'PUT',
- endpoint: reviewed ? '/reviewed' : '/unreviewed',
+ return this.getConfig().then(config => {
+ const isAttentionSetEnabled = !!config && !!config.change
+ && config.change.enable_attention_set;
+ if (isAttentionSetEnabled) return Promise.resolve();
+ return this._getChangeURLAndSend({
+ changeNum,
+ method: 'PUT',
+ endpoint: reviewed ? '/reviewed' : '/unreviewed',
+ });
});
}
@@ -2325,6 +2362,26 @@
});
}
+ addToAttentionSet(changeNum, user, reason) {
+ return this._getChangeURLAndSend({
+ changeNum,
+ method: 'POST',
+ endpoint: '/attention',
+ body: {user, reason},
+ reportUrlAsIs: true,
+ });
+ }
+
+ removeFromAttentionSet(changeNum, user, reason) {
+ return this._getChangeURLAndSend({
+ changeNum,
+ method: 'DELETE',
+ endpoint: `/attention/${user}`,
+ anonymizedEndpoint: '/attention/*',
+ body: {reason},
+ });
+ }
+
/**
* @suppress {checkTypes}
* Resulted in error: Promise.prototype.then does not match formal
@@ -2747,7 +2804,7 @@
// Read the response headers into an object representation.
const headers = Array.from(result.headers.entries())
.reduce((obj, [key, val]) => {
- if (!HEADER_REPORTING_BLACKLIST.test(key)) {
+ if (!HEADER_REPORTING_BLOCK_REGEX.test(key)) {
obj[key] = val;
}
return obj;
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.js
similarity index 84%
rename from polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html
rename to polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.js
index 0a51d26..639b768 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.js
@@ -1,86 +1,73 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-rest-api-interface</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-rest-api-interface></gr-rest-api-interface>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-rest-api-interface.js';
import {mockPromise} from '../../../test/test-utils.js';
import {GrReviewerUpdatesParser} from './gr-reviewer-updates-parser.js';
import {authService} from './gr-auth.js';
+const basicFixture = fixtureFromElement('gr-rest-api-interface');
+
suite('gr-rest-api-interface tests', () => {
let element;
- let sandbox;
+
let ctr = 0;
+ let originalCanonicalPath;
setup(() => {
// Modify CANONICAL_PATH to effectively reset cache.
ctr += 1;
+ originalCanonicalPath = window.CANONICAL_PATH;
window.CANONICAL_PATH = `test${ctr}`;
- sandbox = sinon.sandbox.create();
const testJSON = ')]}\'\n{"hello": "bonjour"}';
- sandbox.stub(window, 'fetch').returns(Promise.resolve({
+ sinon.stub(window, 'fetch').returns(Promise.resolve({
ok: true,
text() {
return Promise.resolve(testJSON);
},
}));
// fake auth
- sandbox.stub(authService, 'authCheck').returns(Promise.resolve(true));
- element = fixture('basic');
+ sinon.stub(authService, 'authCheck').returns(Promise.resolve(true));
+ element = basicFixture.instantiate();
element._projectLookup = {};
});
teardown(() => {
- sandbox.restore();
+ window.CANONICAL_PATH = originalCanonicalPath;
});
test('parent diff comments are properly grouped', done => {
- sandbox.stub(element._restApiHelper, 'fetchJSON', () => Promise.resolve({
- '/COMMIT_MSG': [],
- 'sieve.go': [
- {
- updated: '2017-02-03 22:32:28.000000000',
- message: 'this isn’t quite right',
- },
- {
- side: 'PARENT',
- message: 'how did this work in the first place?',
- updated: '2017-02-03 22:33:28.000000000',
- },
- ],
- }));
+ sinon.stub(element._restApiHelper, 'fetchJSON')
+ .callsFake(() => Promise.resolve({
+ '/COMMIT_MSG': [],
+ 'sieve.go': [
+ {
+ updated: '2017-02-03 22:32:28.000000000',
+ message: 'this isn’t quite right',
+ },
+ {
+ side: 'PARENT',
+ message: 'how did this work in the first place?',
+ updated: '2017-02-03 22:33:28.000000000',
+ },
+ ],
+ }));
element._getDiffComments('42', '', 'PARENT', 1, 'sieve.go').then(
obj => {
assert.equal(obj.baseComments.length, 1);
@@ -206,9 +193,9 @@
});
test('differing patch diff comments are properly grouped', done => {
- sandbox.stub(element, 'getFromProjectLookup')
+ sinon.stub(element, 'getFromProjectLookup')
.returns(Promise.resolve('test'));
- sandbox.stub(element._restApiHelper, 'fetchJSON', request => {
+ sinon.stub(element._restApiHelper, 'fetchJSON').callsFake( request => {
const url = request.url;
if (url === '/changes/test~42/revisions/1') {
return Promise.resolve({
@@ -323,7 +310,7 @@
});
test('server error', done => {
- const getResponseObjectStub = sandbox.stub(element, 'getResponseObject');
+ const getResponseObjectStub = sinon.stub(element, 'getResponseObject');
window.fetch.returns(Promise.resolve({ok: false}));
const serverErrorEventPromise = new Promise(resolve => {
element.addEventListener('server-error', resolve);
@@ -337,8 +324,8 @@
});
test('legacy n,z key in change url is replaced', async () => {
- sandbox.stub(element, 'getConfig', async () => { return {}; });
- const stub = sandbox.stub(element._restApiHelper, 'fetchJSON')
+ sinon.stub(element, 'getConfig').callsFake( async () => { return {}; });
+ const stub = sinon.stub(element._restApiHelper, 'fetchJSON')
.returns(Promise.resolve([]));
await element.getChanges(1, null, 'n,z');
assert.equal(stub.lastCall.args[0].params.S, 0);
@@ -346,7 +333,7 @@
test('saveDiffPreferences invalidates cache line', () => {
const cacheKey = '/accounts/self/preferences.diff';
- const sendStub = sandbox.stub(element._restApiHelper, 'send');
+ const sendStub = sinon.stub(element._restApiHelper, 'send');
element._cache.set(cacheKey, {tab_size: 4});
element.saveDiffPreferences({tab_size: 8});
assert.isTrue(sendStub.called);
@@ -356,8 +343,8 @@
test('getAccount when resp is null does not add anything to the cache',
done => {
const cacheKey = '/accounts/self/detail';
- const stub = sandbox.stub(element._restApiHelper, 'fetchCacheURL',
- () => Promise.resolve());
+ const stub = sinon.stub(element._restApiHelper, 'fetchCacheURL')
+ .callsFake(() => Promise.resolve());
element.getAccount().then(() => {
assert.isTrue(stub.called);
@@ -372,8 +359,8 @@
test('getAccount does not add to the cache when resp.status is 403',
done => {
const cacheKey = '/accounts/self/detail';
- const stub = sandbox.stub(element._restApiHelper, 'fetchCacheURL',
- () => Promise.resolve());
+ const stub = sinon.stub(element._restApiHelper, 'fetchCacheURL')
+ .callsFake(() => Promise.resolve());
element.getAccount().then(() => {
assert.isTrue(stub.called);
@@ -386,7 +373,7 @@
test('getAccount when resp is successful', done => {
const cacheKey = '/accounts/self/detail';
- const stub = sandbox.stub(element._restApiHelper, 'fetchCacheURL',
+ const stub = sinon.stub(element._restApiHelper, 'fetchCacheURL').callsFake(
() => Promise.resolve());
element.getAccount().then(response => {
@@ -400,12 +387,13 @@
});
const preferenceSetup = function(testJSON, loggedIn, smallScreen) {
- sandbox.stub(element, 'getLoggedIn', () => Promise.resolve(loggedIn));
- sandbox.stub(element, '_isNarrowScreen', () => smallScreen);
- sandbox.stub(
+ sinon.stub(element, 'getLoggedIn')
+ .callsFake(() => Promise.resolve(loggedIn));
+ sinon.stub(element, '_isNarrowScreen').callsFake(() => smallScreen);
+ sinon.stub(
element._restApiHelper,
- 'fetchCacheURL',
- () => Promise.resolve(testJSON));
+ 'fetchCacheURL')
+ .callsFake(() => Promise.resolve(testJSON));
};
test('getPreferences returns correctly on small screens logged in',
@@ -468,14 +456,14 @@
});
test('savPreferences normalizes download scheme', () => {
- const sendStub = sandbox.stub(element._restApiHelper, 'send');
+ const sendStub = sinon.stub(element._restApiHelper, 'send');
element.savePreferences({download_scheme: 'HTTP'});
assert.isTrue(sendStub.called);
assert.equal(sendStub.lastCall.args[0].body.download_scheme, 'http');
});
test('getDiffPreferences returns correct defaults', done => {
- sandbox.stub(element, 'getLoggedIn', () => Promise.resolve(false));
+ sinon.stub(element, 'getLoggedIn').callsFake(() => Promise.resolve(false));
element.getDiffPreferences().then(obj => {
assert.equal(obj.auto_hide_diff_table_header, true);
@@ -497,14 +485,14 @@
});
test('saveDiffPreferences set show_tabs to false', () => {
- const sendStub = sandbox.stub(element._restApiHelper, 'send');
+ const sendStub = sinon.stub(element._restApiHelper, 'send');
element.saveDiffPreferences({show_tabs: false});
assert.isTrue(sendStub.called);
assert.equal(sendStub.lastCall.args[0].body.show_tabs, false);
});
test('getEditPreferences returns correct defaults', done => {
- sandbox.stub(element, 'getLoggedIn', () => Promise.resolve(false));
+ sinon.stub(element, 'getLoggedIn').callsFake(() => Promise.resolve(false));
element.getEditPreferences().then(obj => {
assert.equal(obj.auto_close_brackets, false);
@@ -528,14 +516,14 @@
});
test('saveEditPreferences set show_tabs to false', () => {
- const sendStub = sandbox.stub(element._restApiHelper, 'send');
+ const sendStub = sinon.stub(element._restApiHelper, 'send');
element.saveEditPreferences({show_tabs: false});
assert.isTrue(sendStub.called);
assert.equal(sendStub.lastCall.args[0].body.show_tabs, false);
});
test('confirmEmail', () => {
- const sendStub = sandbox.spy(element._restApiHelper, 'send');
+ const sendStub = sinon.spy(element._restApiHelper, 'send');
element.confirmEmail('foo');
assert.isTrue(sendStub.calledOnce);
assert.equal(sendStub.lastCall.args[0].method, 'PUT');
@@ -545,7 +533,7 @@
});
test('setAccountStatus', () => {
- const sendStub = sandbox.stub(element._restApiHelper, 'send')
+ const sendStub = sinon.stub(element._restApiHelper, 'send')
.returns(Promise.resolve('OOO'));
element._cache.set('/accounts/self/detail', {});
return element.setAccountStatus('OOO').then(() => {
@@ -564,7 +552,8 @@
suite('draft comments', () => {
test('_sendDiffDraftRequest pending requests tracked', () => {
const obj = element._pendingRequests;
- sandbox.stub(element, '_getChangeURLAndSend', () => mockPromise());
+ sinon.stub(element, '_getChangeURLAndSend')
+ .callsFake(() => mockPromise());
assert.notOk(element.hasPendingDiffDrafts());
element._sendDiffDraftRequest(null, null, null, {});
@@ -586,8 +575,8 @@
suite('_failForCreate200', () => {
test('_sendDiffDraftRequest checks for 200 on create', () => {
const sendPromise = Promise.resolve();
- sandbox.stub(element, '_getChangeURLAndSend').returns(sendPromise);
- const failStub = sandbox.stub(element, '_failForCreate200')
+ sinon.stub(element, '_getChangeURLAndSend').returns(sendPromise);
+ const failStub = sinon.stub(element, '_failForCreate200')
.returns(Promise.resolve());
return element._sendDiffDraftRequest('PUT', 123, 4, {}).then(() => {
assert.isTrue(failStub.calledOnce);
@@ -596,9 +585,9 @@
});
test('_sendDiffDraftRequest no checks for 200 on non create', () => {
- sandbox.stub(element, '_getChangeURLAndSend')
+ sinon.stub(element, '_getChangeURLAndSend')
.returns(Promise.resolve());
- const failStub = sandbox.stub(element, '_failForCreate200')
+ const failStub = sinon.stub(element, '_failForCreate200')
.returns(Promise.resolve());
return element._sendDiffDraftRequest('PUT', 123, 4, {id: '123'})
.then(() => {
@@ -650,9 +639,9 @@
const change_num = '1';
const file_name = 'index.php';
const file_contents = '<?php';
- sandbox.stub(element._restApiHelper, 'send').returns(
+ sinon.stub(element._restApiHelper, 'send').returns(
Promise.resolve([change_num, file_name, file_contents]));
- sandbox.stub(element, 'getResponseObject')
+ sinon.stub(element, 'getResponseObject')
.returns(Promise.resolve([change_num, file_name, file_contents]));
element._cache.set('/changes/' + change_num + '/edit/' + file_name, {});
return element.saveChangeEdit(change_num, file_name, file_contents)
@@ -671,9 +660,9 @@
element._projectLookup = {1: 'test'};
const change_num = '1';
const message = 'this is a commit message';
- sandbox.stub(element._restApiHelper, 'send').returns(
+ sinon.stub(element._restApiHelper, 'send').returns(
Promise.resolve([change_num, message]));
- sandbox.stub(element, 'getResponseObject')
+ sinon.stub(element, 'getResponseObject')
.returns(Promise.resolve([change_num, message]));
element._cache.set('/changes/' + change_num + '/message', {});
return element.putChangeCommitMessage(change_num, message).then(() => {
@@ -690,9 +679,9 @@
element._projectLookup = {1: 'test'};
const change_num = '1';
const messageId = 'abc';
- sandbox.stub(element._restApiHelper, 'send').returns(
+ sinon.stub(element._restApiHelper, 'send').returns(
Promise.resolve([change_num, messageId]));
- sandbox.stub(element, 'getResponseObject')
+ sinon.stub(element, 'getResponseObject')
.returns(Promise.resolve([change_num, messageId]));
return element.deleteChangeCommitMessage(change_num, messageId).then(() => {
assert.isTrue(element._restApiHelper.send.calledOnce);
@@ -706,7 +695,7 @@
});
test('startWorkInProgress', () => {
- const sendStub = sandbox.stub(element, '_getChangeURLAndSend')
+ const sendStub = sinon.stub(element, '_getChangeURLAndSend')
.returns(Promise.resolve('ok'));
element.startWorkInProgress('42');
assert.isTrue(sendStub.calledOnce);
@@ -727,7 +716,7 @@
});
test('startReview', () => {
- const sendStub = sandbox.stub(element, '_getChangeURLAndSend')
+ const sendStub = sinon.stub(element, '_getChangeURLAndSend')
.returns(Promise.resolve({}));
element.startReview('42', {message: 'Please review.'});
assert.isTrue(sendStub.calledOnce);
@@ -740,7 +729,7 @@
});
test('deleteComment', () => {
- const sendStub = sandbox.stub(element, '_getChangeURLAndSend')
+ const sendStub = sinon.stub(element, '_getChangeURLAndSend')
.returns(Promise.resolve('some response'));
return element.deleteComment('foo', 'bar', '01234', 'removal reason')
.then(response => {
@@ -757,7 +746,7 @@
});
test('createRepo encodes name', () => {
- const sendStub = sandbox.stub(element._restApiHelper, 'send')
+ const sendStub = sinon.stub(element._restApiHelper, 'send')
.returns(Promise.resolve());
return element.createRepo({name: 'x/y'}).then(() => {
assert.isTrue(sendStub.calledOnce);
@@ -766,7 +755,7 @@
});
test('queryChangeFiles', () => {
- const fetchStub = sandbox.stub(element, '_getChangeURLAndFetch')
+ const fetchStub = sinon.stub(element, '_getChangeURLAndFetch')
.returns(Promise.resolve());
return element.queryChangeFiles('42', 'edit', 'test/path.js').then(() => {
assert.equal(fetchStub.lastCall.args[0].changeNum, '42');
@@ -818,7 +807,7 @@
let fetchCacheURLStub;
setup(() => {
fetchCacheURLStub =
- sandbox.stub(element._restApiHelper, 'fetchCacheURL');
+ sinon.stub(element._restApiHelper, 'fetchCacheURL');
});
test('normal use', () => {
@@ -905,7 +894,7 @@
let fetchCacheURLStub;
setup(() => {
fetchCacheURLStub =
- sandbox.stub(element._restApiHelper, 'fetchCacheURL');
+ sinon.stub(element._restApiHelper, 'fetchCacheURL');
});
test('normal use', () => {
@@ -934,13 +923,13 @@
});
test('gerrit auth is used', () => {
- sandbox.stub(authService, 'fetch').returns(Promise.resolve());
+ sinon.stub(authService, 'fetch').returns(Promise.resolve());
element._restApiHelper.fetchJSON({url: 'foo'});
assert(authService.fetch.called);
});
test('getSuggestedAccounts does not return _fetchJSON', () => {
- const _fetchJSONSpy = sandbox.spy(element._restApiHelper, 'fetchJSON');
+ const _fetchJSONSpy = sinon.spy(element._restApiHelper, 'fetchJSON');
return element.getSuggestedAccounts().then(accts => {
assert.isFalse(_fetchJSONSpy.called);
assert.equal(accts.length, 0);
@@ -948,8 +937,8 @@
});
test('_fetchJSON gets called by getSuggestedAccounts', () => {
- const _fetchJSONStub = sandbox.stub(element._restApiHelper, 'fetchJSON',
- () => Promise.resolve());
+ const _fetchJSONStub = sinon.stub(element._restApiHelper, 'fetchJSON')
+ .callsFake(() => Promise.resolve());
return element.getSuggestedAccounts('own').then(() => {
assert.deepEqual(_fetchJSONStub.lastCall.args[0].params, {
q: 'own',
@@ -963,15 +952,15 @@
let toHexStub;
setup(() => {
- toHexStub = sandbox.stub(element, 'listChangesOptionsToHex',
+ toHexStub = sinon.stub(element, 'listChangesOptionsToHex').callsFake(
options => 'deadbeef');
- sandbox.stub(element, '_getChangeDetail',
+ sinon.stub(element, '_getChangeDetail').callsFake(
async (changeNum, options) => { return {changeNum, options}; });
});
test('signed pushes disabled', async () => {
const {PUSH_CERTIFICATES} = element.ListChangesOption;
- sandbox.stub(element, 'getConfig', async () => { return {}; });
+ sinon.stub(element, 'getConfig').callsFake( async () => { return {}; });
const {changeNum, options} = await element.getChangeDetail(123);
assert.strictEqual(123, changeNum);
assert.strictEqual('deadbeef', options);
@@ -981,7 +970,7 @@
test('signed pushes enabled', async () => {
const {PUSH_CERTIFICATES} = element.ListChangesOption;
- sandbox.stub(element, 'getConfig', async () => {
+ sinon.stub(element, 'getConfig').callsFake( async () => {
return {receive: {enable_signed_push: true}};
});
const {changeNum, options} = await element.getChangeDetail(123);
@@ -993,7 +982,7 @@
});
test('GrReviewerUpdatesParser.parse is used', () => {
- sandbox.stub(GrReviewerUpdatesParser, 'parse').returns(
+ sinon.stub(GrReviewerUpdatesParser, 'parse').returns(
Promise.resolve('foo'));
return element.getChangeDetail(42).then(result => {
assert.isTrue(GrReviewerUpdatesParser.parse.calledOnce);
@@ -1007,8 +996,8 @@
const expectedUrl =
window.CANONICAL_PATH + '/changes/test~4321/detail?'+
'0=5&1=1&2=6&3=7&4=1&5=4';
- sandbox.stub(element._etags, 'getOptions');
- sandbox.stub(element._etags, 'collect');
+ sinon.stub(element._etags, 'getOptions');
+ sinon.stub(element._etags, 'collect');
return element._getChangeDetail(changeNum, '516714').then(() => {
assert.isTrue(element._etags.getOptions.calledWithExactly(
expectedUrl));
@@ -1018,9 +1007,9 @@
test('_getChangeDetail calls errFn on 500', () => {
const errFn = sinon.stub();
- sandbox.stub(element, 'getChangeActionURL')
+ sinon.stub(element, 'getChangeActionURL')
.returns(Promise.resolve(''));
- sandbox.stub(element._restApiHelper, 'fetchRawJSON')
+ sinon.stub(element._restApiHelper, 'fetchRawJSON')
.returns(Promise.resolve({ok: false, status: 500}));
return element._getChangeDetail(123, '516714', errFn).then(() => {
assert.isTrue(errFn.called);
@@ -1028,13 +1017,13 @@
});
test('_getChangeDetail populates _projectLookup', () => {
- sandbox.stub(element, 'getChangeActionURL')
+ sinon.stub(element, 'getChangeActionURL')
.returns(Promise.resolve(''));
- sandbox.stub(element._restApiHelper, 'fetchRawJSON')
+ sinon.stub(element._restApiHelper, 'fetchRawJSON')
.returns(Promise.resolve({ok: true}));
const mockResponse = {_number: 1, project: 'test'};
- sandbox.stub(element._restApiHelper, 'readResponsePayload')
+ sinon.stub(element._restApiHelper, 'readResponsePayload')
.returns(Promise.resolve({
parsed: mockResponse,
raw: JSON.stringify(mockResponse),
@@ -1056,16 +1045,16 @@
const mockResponse = {foo: 'bar', baz: 42};
mockResponseSerial = element.JSON_PREFIX +
JSON.stringify(mockResponse);
- sandbox.stub(element._restApiHelper, 'urlWithParams')
+ sinon.stub(element._restApiHelper, 'urlWithParams')
.returns(requestUrl);
- sandbox.stub(element, 'getChangeActionURL')
+ sinon.stub(element, 'getChangeActionURL')
.returns(Promise.resolve(requestUrl));
- collectSpy = sandbox.spy(element._etags, 'collect');
- getPayloadSpy = sandbox.spy(element._etags, 'getCachedPayload');
+ collectSpy = sinon.spy(element._etags, 'collect');
+ getPayloadSpy = sinon.spy(element._etags, 'getCachedPayload');
});
test('contributes to cache', () => {
- sandbox.stub(element._restApiHelper, 'fetchRawJSON')
+ sinon.stub(element._restApiHelper, 'fetchRawJSON')
.returns(Promise.resolve({
text: () => Promise.resolve(mockResponseSerial),
status: 200,
@@ -1081,7 +1070,7 @@
});
test('uses cache on HTTP 304', () => {
- sandbox.stub(element._restApiHelper, 'fetchRawJSON')
+ sinon.stub(element._restApiHelper, 'fetchRawJSON')
.returns(Promise.resolve({
text: () => Promise.resolve(mockResponseSerial),
status: 304,
@@ -1103,7 +1092,7 @@
suite('getFromProjectLookup', () => {
test('getChange fails', () => {
- sandbox.stub(element, 'getChange')
+ sinon.stub(element, 'getChange')
.returns(Promise.resolve(null));
return element.getFromProjectLookup().then(val => {
assert.strictEqual(val, undefined);
@@ -1112,7 +1101,7 @@
});
test('getChange succeeds, no project', () => {
- sandbox.stub(element, 'getChange').returns(Promise.resolve(null));
+ sinon.stub(element, 'getChange').returns(Promise.resolve(null));
return element.getFromProjectLookup().then(val => {
assert.strictEqual(val, undefined);
assert.deepEqual(element._projectLookup, {});
@@ -1120,7 +1109,7 @@
});
test('getChange succeeds with project', () => {
- sandbox.stub(element, 'getChange')
+ sinon.stub(element, 'getChange')
.returns(Promise.resolve({project: 'project'}));
return element.getFromProjectLookup('test').then(val => {
assert.equal(val, 'project');
@@ -1131,7 +1120,7 @@
suite('getChanges populates _projectLookup', () => {
test('multiple queries', () => {
- sandbox.stub(element._restApiHelper, 'fetchJSON')
+ sinon.stub(element._restApiHelper, 'fetchJSON')
.returns(Promise.resolve([
[
{_number: 1, project: 'test'},
@@ -1151,7 +1140,7 @@
});
test('no query', () => {
- sandbox.stub(element._restApiHelper, 'fetchJSON')
+ sinon.stub(element._restApiHelper, 'fetchJSON')
.returns(Promise.resolve([
{_number: 1, project: 'test'},
{_number: 2, project: 'test'},
@@ -1171,7 +1160,7 @@
test('_getChangeURLAndFetch', () => {
element._projectLookup = {1: 'test'};
- const fetchStub = sandbox.stub(element._restApiHelper, 'fetchJSON')
+ const fetchStub = sinon.stub(element._restApiHelper, 'fetchJSON')
.returns(Promise.resolve());
const req = {changeNum: 1, endpoint: '/test', patchNum: 1};
return element._getChangeURLAndFetch(req).then(() => {
@@ -1182,7 +1171,7 @@
test('_getChangeURLAndSend', () => {
element._projectLookup = {1: 'test'};
- const sendStub = sandbox.stub(element._restApiHelper, 'send')
+ const sendStub = sinon.stub(element._restApiHelper, 'send')
.returns(Promise.resolve());
const req = {
@@ -1220,7 +1209,7 @@
});
test('setChangeTopic', () => {
- const sendSpy = sandbox.spy(element, '_getChangeURLAndSend');
+ const sendSpy = sinon.spy(element, '_getChangeURLAndSend');
return element.setChangeTopic(123, 'foo-bar').then(() => {
assert.isTrue(sendSpy.calledOnce);
assert.deepEqual(sendSpy.lastCall.args[0].body, {topic: 'foo-bar'});
@@ -1228,7 +1217,7 @@
});
test('setChangeHashtag', () => {
- const sendSpy = sandbox.spy(element, '_getChangeURLAndSend');
+ const sendSpy = sinon.spy(element, '_getChangeURLAndSend');
return element.setChangeHashtag(123, 'foo-bar').then(() => {
assert.isTrue(sendSpy.calledOnce);
assert.equal(sendSpy.lastCall.args[0].body, 'foo-bar');
@@ -1236,7 +1225,7 @@
});
test('generateAccountHttpPassword', () => {
- const sendSpy = sandbox.spy(element._restApiHelper, 'send');
+ const sendSpy = sinon.spy(element._restApiHelper, 'send');
return element.generateAccountHttpPassword().then(() => {
assert.isTrue(sendSpy.calledOnce);
assert.deepEqual(sendSpy.lastCall.args[0].body, {generate: true});
@@ -1245,7 +1234,7 @@
suite('getChangeFiles', () => {
test('patch only', () => {
- const fetchStub = sandbox.stub(element, '_getChangeURLAndFetch')
+ const fetchStub = sinon.stub(element, '_getChangeURLAndFetch')
.returns(Promise.resolve());
const range = {basePatchNum: 'PARENT', patchNum: 2};
return element.getChangeFiles(123, range).then(() => {
@@ -1256,7 +1245,7 @@
});
test('simple range', () => {
- const fetchStub = sandbox.stub(element, '_getChangeURLAndFetch')
+ const fetchStub = sinon.stub(element, '_getChangeURLAndFetch')
.returns(Promise.resolve());
const range = {basePatchNum: 4, patchNum: 5};
return element.getChangeFiles(123, range).then(() => {
@@ -1269,7 +1258,7 @@
});
test('parent index', () => {
- const fetchStub = sandbox.stub(element, '_getChangeURLAndFetch')
+ const fetchStub = sinon.stub(element, '_getChangeURLAndFetch')
.returns(Promise.resolve());
const range = {basePatchNum: -3, patchNum: 5};
return element.getChangeFiles(123, range).then(() => {
@@ -1284,7 +1273,7 @@
suite('getDiff', () => {
test('patchOnly', () => {
- const fetchStub = sandbox.stub(element, '_getChangeURLAndFetch')
+ const fetchStub = sinon.stub(element, '_getChangeURLAndFetch')
.returns(Promise.resolve());
return element.getDiff(123, 'PARENT', 2, 'foo/bar.baz').then(() => {
assert.isTrue(fetchStub.calledOnce);
@@ -1296,7 +1285,7 @@
});
test('simple range', () => {
- const fetchStub = sandbox.stub(element, '_getChangeURLAndFetch')
+ const fetchStub = sinon.stub(element, '_getChangeURLAndFetch')
.returns(Promise.resolve());
return element.getDiff(123, 4, 5, 'foo/bar.baz').then(() => {
assert.isTrue(fetchStub.calledOnce);
@@ -1308,7 +1297,7 @@
});
test('parent index', () => {
- const fetchStub = sandbox.stub(element, '_getChangeURLAndFetch')
+ const fetchStub = sinon.stub(element, '_getChangeURLAndFetch')
.returns(Promise.resolve());
return element.getDiff(123, -3, 5, 'foo/bar.baz').then(() => {
assert.isTrue(fetchStub.calledOnce);
@@ -1321,7 +1310,7 @@
});
test('getDashboard', () => {
- const fetchCacheURLStub = sandbox.stub(element._restApiHelper,
+ const fetchCacheURLStub = sinon.stub(element._restApiHelper,
'fetchCacheURL');
element.getDashboard('gerrit/project', 'default:main');
assert.isTrue(fetchCacheURLStub.calledOnce);
@@ -1331,7 +1320,7 @@
});
test('getFileContent', () => {
- sandbox.stub(element, '_getChangeURLAndSend')
+ sinon.stub(element, '_getChangeURLAndSend')
.returns(Promise.resolve({
ok: 'true',
headers: {
@@ -1343,7 +1332,7 @@
},
}));
- sandbox.stub(element, 'getResponseObject')
+ sinon.stub(element, 'getResponseObject')
.returns(Promise.resolve('new content'));
const edit = element.getFileContent('1', 'tst/path', 'EDIT').then(res => {
@@ -1366,8 +1355,8 @@
done();
};
element.addEventListener('server-error', handler);
- sandbox.stub(authService, 'fetch').returns(Promise.resolve(res));
- sandbox.stub(element, '_changeBaseURL').returns(Promise.resolve(''));
+ sinon.stub(authService, 'fetch').returns(Promise.resolve(res));
+ sinon.stub(element, '_changeBaseURL').returns(Promise.resolve(''));
element.getFileContent('1', 'tst/path', '1').then(() => {
flushAsynchronousOperations();
@@ -1378,9 +1367,9 @@
test('getChangeFilesOrEditFiles is edit-sensitive', () => {
const fn = element.getChangeOrEditFiles.bind(element);
- const getChangeFilesStub = sandbox.stub(element, 'getChangeFiles')
+ const getChangeFilesStub = sinon.stub(element, 'getChangeFiles')
.returns(Promise.resolve({}));
- const getChangeEditFilesStub = sandbox.stub(element, 'getChangeEditFiles')
+ const getChangeEditFilesStub = sinon.stub(element, 'getChangeEditFiles')
.returns(Promise.resolve({}));
return fn('1', {patchNum: 'edit'}).then(() => {
@@ -1394,13 +1383,13 @@
});
test('_fetch forwards request and logs', () => {
- const logStub = sandbox.stub(element._restApiHelper, '_logCall');
+ const logStub = sinon.stub(element._restApiHelper, '_logCall');
const response = {status: 404, text: sinon.stub()};
const url = 'my url';
const fetchOptions = {method: 'DELETE'};
- sandbox.stub(element._auth, 'fetch').returns(Promise.resolve(response));
+ sinon.stub(element._auth, 'fetch').returns(Promise.resolve(response));
const startTime = 123;
- sandbox.stub(Date, 'now').returns(startTime);
+ sinon.stub(Date, 'now').returns(startTime);
const req = {url, fetchOptions};
return element._restApiHelper.fetch(req).then(() => {
assert.isTrue(logStub.calledOnce);
@@ -1410,7 +1399,7 @@
});
test('_logCall only reports requests with anonymized URLss', () => {
- sandbox.stub(Date, 'now').returns(200);
+ sinon.stub(Date, 'now').returns(200);
const handler = sinon.stub();
element.addEventListener('rpc-log', handler);
@@ -1424,10 +1413,10 @@
});
test('saveChangeStarred', async () => {
- sandbox.stub(element, 'getFromProjectLookup')
+ sinon.stub(element, 'getFromProjectLookup')
.returns(Promise.resolve('test'));
const sendStub =
- sandbox.stub(element._restApiHelper, 'send').returns(Promise.resolve());
+ sinon.stub(element._restApiHelper, 'send').returns(Promise.resolve());
await element.saveChangeStarred(123, true);
assert.isTrue(sendStub.calledOnce);
@@ -1446,4 +1435,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper_test.html b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper_test.js
similarity index 73%
rename from polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper_test.html
rename to polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper_test.js
index 32d2166..8acba73 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper_test.js
@@ -1,47 +1,37 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2019 The Android Open Source Project
+/**
+ * @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.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-rest-api-helper</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<script type="module">
-import '../../../../test/common-test-setup.js';
+import '../../../../test/common-test-setup-karma.js';
import {SiteBasedCache} from './gr-rest-api-helper.js';
import {FetchPromisesCache, GrRestApiHelper} from './gr-rest-api-helper.js';
import {authService} from '../gr-auth.js';
suite('gr-rest-api-helper tests', () => {
let helper;
- let sandbox;
+
let cache;
let fetchPromisesCache;
+ let originalCanonicalPath;
setup(() => {
- sandbox = sinon.sandbox.create();
cache = new SiteBasedCache();
fetchPromisesCache = new FetchPromisesCache();
+ originalCanonicalPath = window.CANONICAL_PATH;
window.CANONICAL_PATH = 'testhelper';
const mockRestApiInterface = {
@@ -50,7 +40,7 @@
};
const testJSON = ')]}\'\n{"hello": "bonjour"}';
- sandbox.stub(window, 'fetch').returns(Promise.resolve({
+ sinon.stub(window, 'fetch').returns(Promise.resolve({
ok: true,
text() {
return Promise.resolve(testJSON);
@@ -62,12 +52,12 @@
});
teardown(() => {
- sandbox.restore();
+ window.CANONICAL_PATH = originalCanonicalPath;
});
suite('fetchJSON()', () => {
test('Sets header to accept application/json', () => {
- const authFetchStub = sandbox.stub(helper._auth, 'fetch')
+ const authFetchStub = sinon.stub(helper._auth, 'fetch')
.returns(Promise.resolve());
helper.fetchJSON({url: '/dummy/url'});
assert.isTrue(authFetchStub.called);
@@ -76,7 +66,7 @@
});
test('Use header option accept when provided', () => {
- const authFetchStub = sandbox.stub(helper._auth, 'fetch')
+ const authFetchStub = sinon.stub(helper._auth, 'fetch')
.returns(Promise.resolve());
const headers = new Headers();
headers.append('Accept', '*/*');
@@ -97,7 +87,7 @@
test('cached results', done => {
let n = 0;
- sandbox.stub(helper, 'fetchJSON', () => Promise.resolve(++n));
+ sinon.stub(helper, 'fetchJSON').callsFake(() => Promise.resolve(++n));
const promises = [];
promises.push(helper.fetchCacheURL('/foo'));
promises.push(helper.fetchCacheURL('/foo'));
@@ -171,4 +161,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser_test.html b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser_test.js
similarity index 85%
rename from polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser_test.html
rename to polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser_test.js
index fa54d6b..f408a97 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser_test.js
@@ -1,53 +1,38 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-reviewer-updates-parser</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import {GrReviewerUpdatesParser} from './gr-reviewer-updates-parser.js';
import {parseDate} from '../../../utils/date-util.js';
suite('gr-reviewer-updates-parser tests', () => {
- let sandbox;
let instance;
setup(() => {
- sandbox = sinon.sandbox.create();
- });
- teardown(() => {
- sandbox.restore();
});
test('ignores changes without messages', () => {
const change = {};
- sandbox.stub(
+ sinon.stub(
GrReviewerUpdatesParser.prototype, '_filterRemovedMessages');
- sandbox.stub(
+ sinon.stub(
GrReviewerUpdatesParser.prototype, '_groupUpdates');
- sandbox.stub(
+ sinon.stub(
GrReviewerUpdatesParser.prototype, '_formatUpdates');
assert.strictEqual(GrReviewerUpdatesParser.parse(change), change);
assert.isFalse(
@@ -62,11 +47,11 @@
const change = {
messages: [],
};
- sandbox.stub(
+ sinon.stub(
GrReviewerUpdatesParser.prototype, '_filterRemovedMessages');
- sandbox.stub(
+ sinon.stub(
GrReviewerUpdatesParser.prototype, '_groupUpdates');
- sandbox.stub(
+ sinon.stub(
GrReviewerUpdatesParser.prototype, '_formatUpdates');
assert.strictEqual(GrReviewerUpdatesParser.parse(change), change);
assert.isFalse(
@@ -82,11 +67,11 @@
messages: [],
reviewer_updates: [],
};
- sandbox.stub(
+ sinon.stub(
GrReviewerUpdatesParser.prototype, '_filterRemovedMessages');
- sandbox.stub(
+ sinon.stub(
GrReviewerUpdatesParser.prototype, '_groupUpdates');
- sandbox.stub(
+ sinon.stub(
GrReviewerUpdatesParser.prototype, '_formatUpdates');
assert.strictEqual(GrReviewerUpdatesParser.parse(change), change);
assert.isFalse(
@@ -303,4 +288,4 @@
assert.equal(updates[3].date, tplus(500));
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-select/gr-select_test.html b/polygerrit-ui/app/elements/shared/gr-select/gr-select_test.js
similarity index 60%
rename from polygerrit-ui/app/elements/shared/gr-select/gr-select_test.html
rename to polygerrit-ui/app/elements/shared/gr-select/gr-select_test.js
index 670f383..c697850 100644
--- a/polygerrit-ui/app/elements/shared/gr-select/gr-select_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-select/gr-select_test.js
@@ -1,59 +1,46 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
+import '../../../test/common-test-setup-karma.js';
+import './gr-select.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-select</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-select>
+const basicFixture = fixtureFromTemplate(html`
+<gr-select>
<select>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
</gr-select>
- </template>
-</test-fixture>
+`);
-<test-fixture id="noOptions">
- <template>
- <gr-select>
+const noOptionsFixture = fixtureFromTemplate(html`
+<gr-select>
<select>
</select>
</gr-select>
- </template>
-</test-fixture>
+`);
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-select.js';
suite('gr-select tests', () => {
let element;
setup(() => {
- element = fixture('basic');
+ element = basicFixture.instantiate();
});
test('bindValue must be set to the first option value', () => {
@@ -109,7 +96,7 @@
let element;
setup(() => {
- element = fixture('noOptions');
+ element = noOptionsFixture.instantiate();
});
test('bindValue must not be changed', () => {
@@ -117,4 +104,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-shell-command/gr-shell-command_test.html b/polygerrit-ui/app/elements/shared/gr-shell-command/gr-shell-command_test.html
deleted file mode 100644
index ee0b64f..0000000
--- a/polygerrit-ui/app/elements/shared/gr-shell-command/gr-shell-command_test.html
+++ /dev/null
@@ -1,61 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-shell-command</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-shell-command></gr-shell-command>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-shell-command.js';
-suite('gr-shell-command tests', () => {
- let element;
- let sandbox;
-
- setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- element.text = `git fetch http://gerrit@localhost:8080/a/test-project
- refs/changes/05/5/1 && git checkout FETCH_HEAD`;
- flushAsynchronousOperations();
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('focusOnCopy', () => {
- const focusStub = sandbox.stub(element.shadowRoot
- .querySelector('gr-copy-clipboard'),
- 'focusOnCopy');
- element.focusOnCopy();
- assert.isTrue(focusStub.called);
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-shell-command/gr-shell-command_test.js b/polygerrit-ui/app/elements/shared/gr-shell-command/gr-shell-command_test.js
new file mode 100644
index 0000000..5e20717
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-shell-command/gr-shell-command_test.js
@@ -0,0 +1,41 @@
+/**
+ * @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.
+ */
+
+import '../../../test/common-test-setup-karma.js';
+import './gr-shell-command.js';
+
+const basicFixture = fixtureFromElement('gr-shell-command');
+
+suite('gr-shell-command tests', () => {
+ let element;
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ element.text = `git fetch http://gerrit@localhost:8080/a/test-project
+ refs/changes/05/5/1 && git checkout FETCH_HEAD`;
+ flushAsynchronousOperations();
+ });
+
+ test('focusOnCopy', () => {
+ const focusStub = sinon.stub(element.shadowRoot
+ .querySelector('gr-copy-clipboard'),
+ 'focusOnCopy');
+ element.focusOnCopy();
+ assert.isTrue(focusStub.called);
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/shared/gr-storage/gr-storage_test.html b/polygerrit-ui/app/elements/shared/gr-storage/gr-storage_test.js
similarity index 75%
rename from polygerrit-ui/app/elements/shared/gr-storage/gr-storage_test.html
rename to polygerrit-ui/app/elements/shared/gr-storage/gr-storage_test.js
index b560c56..99f953f 100644
--- a/polygerrit-ui/app/elements/shared/gr-storage/gr-storage_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-storage/gr-storage_test.js
@@ -1,41 +1,27 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-storage</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-storage></gr-storage>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-storage.js';
+
+const basicFixture = fixtureFromElement('gr-storage');
+
suite('gr-storage tests', () => {
let element;
- let sandbox;
function mockStorage(opt_quotaExceeded) {
return {
@@ -50,13 +36,11 @@
}
setup(() => {
- element = fixture('basic');
- sandbox = sinon.sandbox.create();
+ element = basicFixture.instantiate();
+
element._storage = mockStorage();
});
- teardown(() => sandbox.restore());
-
test('storing, retrieving and erasing drafts', () => {
const changeNum = 1234;
const patchNum = 5;
@@ -106,7 +90,7 @@
// Make sure that the call to cleanup doesn't get throttled.
element._lastCleanup = 0;
- const cleanupSpy = sandbox.spy(element, '_cleanupItems');
+ const cleanupSpy = sinon.spy(element, '_cleanupItems');
// Create a message with a timestamp that is a second behind the max age.
element._storage.setItem(key, JSON.stringify({
@@ -166,7 +150,7 @@
});
test('editable content items', () => {
- const cleanupStub = sandbox.stub(element, '_cleanupItems');
+ const cleanupStub = sinon.stub(element, '_cleanupItems');
const key = 'testKey';
const computedKey = element._getEditableContentKey(key);
// Key correctly computed.
@@ -192,4 +176,4 @@
assert.isNotOk(element._storage.getItem(computedKey));
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea_test.html b/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea_test.js
similarity index 80%
rename from polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea_test.html
rename to polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea_test.js
index bcf1207..2aa7697 100644
--- a/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea_test.js
@@ -1,63 +1,40 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-textarea</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-textarea></gr-textarea>
- </template>
-</test-fixture>
-
-<test-fixture id="monospace">
- <template>
- <gr-textarea monospace="true"></gr-textarea>
- </template>
-</test-fixture>
-
-<test-fixture id="hideBorder">
- <template>
- <gr-textarea hide-border="true"></gr-textarea>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
+import '../../../test/common-test-setup-karma.js';
import './gr-textarea.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const basicFixture = fixtureFromElement('gr-textarea');
+
+const monospaceFixture = fixtureFromTemplate(html`
+<gr-textarea monospace="true"></gr-textarea>
+`);
+
+const hideBorderFixture = fixtureFromTemplate(html`
+<gr-textarea hide-border="true"></gr-textarea>
+`);
+
suite('gr-textarea tests', () => {
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('basic');
- sandbox.stub(element.reporting, 'reportInteraction');
- });
-
- teardown(() => {
- sandbox.restore();
+ element = basicFixture.instantiate();
+ sinon.stub(element.reporting, 'reportInteraction');
});
test('monospace is set properly', () => {
@@ -154,7 +131,7 @@
// Since selectionStart is on Chrome set always on end of text, we
// stub it to 1
const text = ': hello';
- sandbox.stub(element.$, 'textarea', {
+ sinon.stub(element.$, 'textarea').value( {
selectionStart: 1,
value: text,
textarea: {
@@ -169,7 +146,7 @@
assert.equal(element._currentSearchString, '');
});
test('emoji selector closes when text changes before the colon', () => {
- const resetStub = sandbox.stub(element, '_resetEmojiDropdown');
+ const resetStub = sinon.stub(element, '_resetEmojiDropdown');
MockInteractions.focus(element.$.textarea);
flushAsynchronousOperations();
element.$.textarea.selectionStart = 10;
@@ -189,7 +166,7 @@
});
test('_resetEmojiDropdown', () => {
- const closeSpy = sandbox.spy(element, 'closeDropdown');
+ const closeSpy = sinon.spy(element, 'closeDropdown');
element._resetEmojiDropdown();
assert.equal(element._currentSearchString, '');
assert.isTrue(element._hideAutocomplete);
@@ -203,7 +180,7 @@
test('_determineSuggestions', () => {
const emojiText = 'tear';
- const formatSpy = sandbox.spy(element, '_formatSuggestions');
+ const formatSpy = sinon.spy(element, '_formatSuggestions');
element._determineSuggestions(emojiText);
assert.isTrue(formatSpy.called);
assert.isTrue(formatSpy.lastCall.calledWithExactly(
@@ -244,7 +221,7 @@
});
test('emoji dropdown is closed when iron-overlay-closed is fired', () => {
- const resetSpy = sandbox.spy(element, '_resetEmojiDropdown');
+ const resetSpy = sinon.spy(element, '_resetEmojiDropdown');
element.$.emojiSuggestions.dispatchEvent(
new CustomEvent('dropdown-closed', {
composed: true, bubbles: true,
@@ -273,7 +250,7 @@
}
test('escape key', () => {
- const resetSpy = sandbox.spy(element, '_resetEmojiDropdown');
+ const resetSpy = sinon.spy(element, '_resetEmojiDropdown');
MockInteractions.pressAndReleaseKeyOn(element.$.textarea, 27);
assert.isFalse(resetSpy.called);
setupDropdown();
@@ -283,7 +260,7 @@
});
test('up key', () => {
- const upSpy = sandbox.spy(element.$.emojiSuggestions, 'cursorUp');
+ const upSpy = sinon.spy(element.$.emojiSuggestions, 'cursorUp');
MockInteractions.pressAndReleaseKeyOn(element.$.textarea, 38);
assert.isFalse(upSpy.called);
setupDropdown();
@@ -292,7 +269,7 @@
});
test('down key', () => {
- const downSpy = sandbox.spy(element.$.emojiSuggestions, 'cursorDown');
+ const downSpy = sinon.spy(element.$.emojiSuggestions, 'cursorDown');
MockInteractions.pressAndReleaseKeyOn(element.$.textarea, 40);
assert.isFalse(downSpy.called);
setupDropdown();
@@ -301,7 +278,7 @@
});
test('enter key', () => {
- const enterSpy = sandbox.spy(element.$.emojiSuggestions,
+ const enterSpy = sinon.spy(element.$.emojiSuggestions,
'getCursorTarget');
MockInteractions.pressAndReleaseKeyOn(element.$.textarea, 13);
assert.isFalse(enterSpy.called);
@@ -313,7 +290,7 @@
});
test('enter key - ignored on just colon without more information', () => {
- const enterSpy = sandbox.spy(element.$.emojiSuggestions,
+ const enterSpy = sinon.spy(element.$.emojiSuggestions,
'getCursorTarget');
MockInteractions.pressAndReleaseKeyOn(element.$.textarea, 13);
assert.isFalse(enterSpy.called);
@@ -335,15 +312,9 @@
// properties before ready() is called.
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('monospace');
- });
-
- teardown(() => {
- sandbox.restore();
+ element = monospaceFixture.instantiate();
});
test('monospace is set properly', () => {
@@ -359,15 +330,9 @@
// properties before ready() is called.
let element;
- let sandbox;
setup(() => {
- sandbox = sinon.sandbox.create();
- element = fixture('hideBorder');
- });
-
- teardown(() => {
- sandbox.restore();
+ element = hideBorderFixture.instantiate();
});
test('hideBorder is set properly', () => {
@@ -375,4 +340,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/elements/shared/gr-tooltip-content/gr-tooltip-content_test.html b/polygerrit-ui/app/elements/shared/gr-tooltip-content/gr-tooltip-content_test.html
deleted file mode 100644
index a8fc18a..0000000
--- a/polygerrit-ui/app/elements/shared/gr-tooltip-content/gr-tooltip-content_test.html
+++ /dev/null
@@ -1,61 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-storage</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-tooltip-content>
- </gr-tooltip-content>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-tooltip-content.js';
-import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
-suite('gr-tooltip-content tests', () => {
- let element;
- setup(() => {
- element = fixture('basic');
- });
-
- test('icon is not visible by default', () => {
- assert.equal(dom(element.root)
- .querySelector('iron-icon').hidden, true);
- });
-
- test('position-below attribute is reflected', () => {
- assert.isFalse(element.hasAttribute('position-below'));
- element.positionBelow = true;
- assert.isTrue(element.hasAttribute('position-below'));
- });
-
- test('icon is visible with showIcon property', () => {
- element.showIcon = true;
- assert.equal(dom(element.root)
- .querySelector('iron-icon').hidden, false);
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-tooltip-content/gr-tooltip-content_test.js b/polygerrit-ui/app/elements/shared/gr-tooltip-content/gr-tooltip-content_test.js
new file mode 100644
index 0000000..f905eaa
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-tooltip-content/gr-tooltip-content_test.js
@@ -0,0 +1,51 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-tooltip-content.js';
+import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const basicFixture = fixtureFromTemplate(html`
+<gr-tooltip-content>
+ </gr-tooltip-content>
+`);
+
+suite('gr-tooltip-content tests', () => {
+ let element;
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ test('icon is not visible by default', () => {
+ assert.equal(dom(element.root)
+ .querySelector('iron-icon').hidden, true);
+ });
+
+ test('position-below attribute is reflected', () => {
+ assert.isFalse(element.hasAttribute('position-below'));
+ element.positionBelow = true;
+ assert.isTrue(element.hasAttribute('position-below'));
+ });
+
+ test('icon is visible with showIcon property', () => {
+ element.showIcon = true;
+ assert.equal(dom(element.root)
+ .querySelector('iron-icon').hidden, false);
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip_test.html b/polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip_test.html
deleted file mode 100644
index b69d945..0000000
--- a/polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip_test.html
+++ /dev/null
@@ -1,66 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-storage</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-tooltip>
- </gr-tooltip>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './gr-tooltip.js';
-suite('gr-tooltip tests', () => {
- let element;
- setup(() => {
- element = fixture('basic');
- });
-
- test('max-width is respected if set', () => {
- element.text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit' +
- ', sed do eiusmod tempor incididunt ut labore et dolore magna aliqua';
- element.maxWidth = '50px';
- assert.equal(getComputedStyle(element).width, '50px');
- });
-
- test('the correct arrow is displayed', () => {
- assert.equal(getComputedStyle(element.shadowRoot
- .querySelector('.arrowPositionBelow')).display,
- 'none');
- assert.notEqual(getComputedStyle(element.shadowRoot
- .querySelector('.arrowPositionAbove'))
- .display, 'none');
- element.positionBelow = true;
- assert.notEqual(getComputedStyle(element.shadowRoot
- .querySelector('.arrowPositionBelow'))
- .display, 'none');
- assert.equal(getComputedStyle(element.shadowRoot
- .querySelector('.arrowPositionAbove'))
- .display, 'none');
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip_test.js b/polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip_test.js
new file mode 100644
index 0000000..b5f068c
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip_test.js
@@ -0,0 +1,56 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './gr-tooltip.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const basicFixture = fixtureFromTemplate(html`
+<gr-tooltip>
+ </gr-tooltip>
+`);
+
+suite('gr-tooltip tests', () => {
+ let element;
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ test('max-width is respected if set', () => {
+ element.text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit' +
+ ', sed do eiusmod tempor incididunt ut labore et dolore magna aliqua';
+ element.maxWidth = '50px';
+ assert.equal(getComputedStyle(element).width, '50px');
+ });
+
+ test('the correct arrow is displayed', () => {
+ assert.equal(getComputedStyle(element.shadowRoot
+ .querySelector('.arrowPositionBelow')).display,
+ 'none');
+ assert.notEqual(getComputedStyle(element.shadowRoot
+ .querySelector('.arrowPositionAbove'))
+ .display, 'none');
+ element.positionBelow = true;
+ assert.notEqual(getComputedStyle(element.shadowRoot
+ .querySelector('.arrowPositionBelow'))
+ .display, 'none');
+ assert.equal(getComputedStyle(element.shadowRoot
+ .querySelector('.arrowPositionAbove'))
+ .display, 'none');
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/shared/revision-info/revision-info_test.html b/polygerrit-ui/app/elements/shared/revision-info/revision-info_test.html
deleted file mode 100644
index 2d89b30..0000000
--- a/polygerrit-ui/app/elements/shared/revision-info/revision-info_test.html
+++ /dev/null
@@ -1,90 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>revision-info</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<script type="module">
-import '../../../test/common-test-setup.js';
-import './revision-info.js';
-import {RevisionInfo} from './revision-info.js';
-suite('revision-info tests', () => {
- let mockChange;
-
- setup(() => {
- mockChange = {
- revisions: {
- r1: {_number: 1, commit: {parents: [
- {commit: 'p1'},
- {commit: 'p2'},
- {commit: 'p3'},
- ]}},
- r2: {_number: 2, commit: {parents: [
- {commit: 'p1'},
- {commit: 'p4'},
- ]}},
- r3: {_number: 3, commit: {parents: [{commit: 'p5'}]}},
- r4: {_number: 4, commit: {parents: [
- {commit: 'p2'},
- {commit: 'p3'},
- ]}},
- r5: {_number: 5, commit: {parents: [
- {commit: 'p5'},
- {commit: 'p2'},
- {commit: 'p3'},
- ]}},
- },
- };
- });
-
- test('getMaxParents', () => {
- const ri = new RevisionInfo(mockChange);
- assert.equal(ri.getMaxParents(), 3);
- });
-
- test('getParentCountMap', () => {
- const ri = new RevisionInfo(mockChange);
- assert.deepEqual(ri.getParentCountMap(), {1: 3, 2: 2, 3: 1, 4: 2, 5: 3});
- });
-
- test('getParentCount', () => {
- const ri = new RevisionInfo(mockChange);
- assert.deepEqual(ri.getParentCount(1), 3);
- assert.deepEqual(ri.getParentCount(3), 1);
- });
-
- test('getParentCount', () => {
- const ri = new RevisionInfo(mockChange);
- assert.deepEqual(ri.getParentCount(1), 3);
- assert.deepEqual(ri.getParentCount(3), 1);
- });
-
- test('getParentId', () => {
- const ri = new RevisionInfo(mockChange);
- assert.deepEqual(ri.getParentId(1, 2), 'p3');
- assert.deepEqual(ri.getParentId(2, 1), 'p4');
- assert.deepEqual(ri.getParentId(3, 0), 'p5');
- });
-});
-</script>
diff --git a/polygerrit-ui/app/elements/shared/revision-info/revision-info_test.js b/polygerrit-ui/app/elements/shared/revision-info/revision-info_test.js
new file mode 100644
index 0000000..7d0dd4f
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/revision-info/revision-info_test.js
@@ -0,0 +1,79 @@
+/**
+ * @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 '../../../test/common-test-setup-karma.js';
+import './revision-info.js';
+import {RevisionInfo} from './revision-info.js';
+suite('revision-info tests', () => {
+ let mockChange;
+
+ setup(() => {
+ mockChange = {
+ revisions: {
+ r1: {_number: 1, commit: {parents: [
+ {commit: 'p1'},
+ {commit: 'p2'},
+ {commit: 'p3'},
+ ]}},
+ r2: {_number: 2, commit: {parents: [
+ {commit: 'p1'},
+ {commit: 'p4'},
+ ]}},
+ r3: {_number: 3, commit: {parents: [{commit: 'p5'}]}},
+ r4: {_number: 4, commit: {parents: [
+ {commit: 'p2'},
+ {commit: 'p3'},
+ ]}},
+ r5: {_number: 5, commit: {parents: [
+ {commit: 'p5'},
+ {commit: 'p2'},
+ {commit: 'p3'},
+ ]}},
+ },
+ };
+ });
+
+ test('getMaxParents', () => {
+ const ri = new RevisionInfo(mockChange);
+ assert.equal(ri.getMaxParents(), 3);
+ });
+
+ test('getParentCountMap', () => {
+ const ri = new RevisionInfo(mockChange);
+ assert.deepEqual(ri.getParentCountMap(), {1: 3, 2: 2, 3: 1, 4: 2, 5: 3});
+ });
+
+ test('getParentCount', () => {
+ const ri = new RevisionInfo(mockChange);
+ assert.deepEqual(ri.getParentCount(1), 3);
+ assert.deepEqual(ri.getParentCount(3), 1);
+ });
+
+ test('getParentCount', () => {
+ const ri = new RevisionInfo(mockChange);
+ assert.deepEqual(ri.getParentCount(1), 3);
+ assert.deepEqual(ri.getParentCount(3), 1);
+ });
+
+ test('getParentId', () => {
+ const ri = new RevisionInfo(mockChange);
+ assert.deepEqual(ri.getParentId(1, 2), 'p3');
+ assert.deepEqual(ri.getParentId(2, 1), 'p4');
+ assert.deepEqual(ri.getParentId(3, 0), 'p5');
+ });
+});
+
diff --git a/polygerrit-ui/app/elements/test/plugin.html b/polygerrit-ui/app/elements/test/plugin.html
deleted file mode 100644
index ecd9007..0000000
--- a/polygerrit-ui/app/elements/test/plugin.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<dom-module id="my-plugin">
- <script>
- Gerrit.install(plugin => {
- plugin.registerStyleModule('app-theme', 'myplugin-app-theme');
- plugin.registerStyleModule('app-theme-light', 'myplugin-app-theme-light');
- plugin.registerStyleModule('app-theme-dark', 'myplugin-app-theme-dark');
- });
- </script>
-</dom-module>
-
-<dom-module id="myplugin-app-theme">
- <template>
- <style>
- html {
- --primary-text-color: #F00BAA;
- }
- </style>
- </template>
-</dom-module>
-
-<dom-module id="myplugin-app-theme-light">
- <template>
- <style>
- html {
- --header-background-color: #F01BAA;
- --header-title-content: "MyGerrit";
- --footer-background-color: #F02BAA;
- }
- </style>
- </template>
-</dom-module>
-
-<dom-module id="myplugin-app-theme-dark">
- <template>
- <style>
- html {
- --primary-text-color: red;
- --header-background-color: black;
- --header-title-content: "MyGerrit Dark";
- --footer-background-color: yellow;
- }
- </style>
- </template>
-</dom-module>
diff --git a/polygerrit-ui/app/embed/README.md b/polygerrit-ui/app/embed/README.md
index 8860878..4e1677de 100644
--- a/polygerrit-ui/app/embed/README.md
+++ b/polygerrit-ui/app/embed/README.md
@@ -10,4 +10,4 @@
All supported attributes defined in `polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js`, you can pass them by just assigning them to the `gr-app` element.
-To customize the style of the diff, you can use `css variables`, all supported variables defined in `polygerrit-ui/app/styles/themes/app-theme.html` and `polygerrit-ui/app/styles/themes/dark-theme.html`.
+To customize the style of the diff, you can use `css variables`, all supported variables defined in `polygerrit-ui/app/styles/themes/app-theme.js` and `polygerrit-ui/app/styles/themes/dark-theme.js`.
diff --git a/polygerrit-ui/app/embed/gr-diff-app-context-init_test.html b/polygerrit-ui/app/embed/gr-diff-app-context-init_test.html
deleted file mode 100644
index 3aed13f..0000000
--- a/polygerrit-ui/app/embed/gr-diff-app-context-init_test.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2020 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<script type="module">
- import '../test/common-test-setup.js';
- import {appContext} from '../services/app-context.js';
- import {initDiffAppContext} from './gr-diff-app-context-init.js';
- suite('gr diff app context initializer tests', () => {
- setup(() => {
- initDiffAppContext();
- });
-
- test('all services initialized and are singletons', () => {
- Object.keys(appContext).forEach(serviceName => {
- const service = appContext[serviceName];
- assert.isNotNull(service);
- const service2 = appContext[serviceName];
- assert.strictEqual(service, service2);
- });
- });
- });
-</script>
\ No newline at end of file
diff --git a/polygerrit-ui/app/embed/gr-diff-app-context-init_test.js b/polygerrit-ui/app/embed/gr-diff-app-context-init_test.js
new file mode 100644
index 0000000..832c931
--- /dev/null
+++ b/polygerrit-ui/app/embed/gr-diff-app-context-init_test.js
@@ -0,0 +1,35 @@
+/**
+ * @license
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import '../test/common-test-setup-karma.js';
+import {appContext} from '../services/app-context.js';
+import {initDiffAppContext} from './gr-diff-app-context-init.js';
+suite('gr diff app context initializer tests', () => {
+ setup(() => {
+ initDiffAppContext();
+ });
+
+ test('all services initialized and are singletons', () => {
+ Object.keys(appContext).forEach(serviceName => {
+ const service = appContext[serviceName];
+ assert.isNotNull(service);
+ const service2 = appContext[serviceName];
+ assert.strictEqual(service, service2);
+ });
+ });
+});
+
diff --git a/polygerrit-ui/app/polymer.json b/polygerrit-ui/app/polymer.json
index 411c969..affa7f2 100644
--- a/polygerrit-ui/app/polymer.json
+++ b/polygerrit-ui/app/polymer.json
@@ -1,5 +1,5 @@
{
- "entrypoint": "elements/gr-app.html",
+ "shell": "elements/gr-app.js",
"sources": [
"behaviors/**/*",
"elements/**/*",
diff --git a/polygerrit-ui/app/rules.bzl b/polygerrit-ui/app/rules.bzl
index bc2830d..1492ad8 100644
--- a/polygerrit-ui/app/rules.bzl
+++ b/polygerrit-ui/app/rules.bzl
@@ -8,10 +8,10 @@
name: rule name
srcs: source files
outs: array with a single item - the output file name
- entry_point: application entry-point
+ entry_point: application js entry-point
"""
- app_name = entry_point.split(".html")[0].split("/").pop() # eg: gr-app
+ app_name = entry_point.split(".js")[0].split("/").pop() # eg: gr-app
native.filegroup(
name = app_name + "-full-src",
@@ -24,7 +24,7 @@
name = app_name + "-bundle-js",
srcs = [app_name + "-full-src"],
config_file = ":rollup.config.js",
- entry_point = "elements/" + app_name + ".js",
+ entry_point = entry_point,
rollup_bin = "//tools/node_tools:rollup-bin",
sourcemap = "hidden",
deps = [
@@ -36,7 +36,6 @@
name = name + "_app_sources",
srcs = [
app_name + "-bundle-js.js",
- entry_point,
],
)
@@ -46,15 +45,6 @@
)
native.filegroup(
- name = name + "_theme_sources",
- srcs = native.glob(
- ["styles/themes/*.html"],
- # app-theme.html already included via an import in gr-app.html.
- exclude = ["styles/themes/app-theme.html"],
- ),
- )
-
- native.filegroup(
name = name + "_top_sources",
srcs = [
"favicon.ico",
@@ -68,7 +58,6 @@
srcs = [
name + "_app_sources",
name + "_css_sources",
- name + "_theme_sources",
name + "_top_sources",
"//lib/fonts:robotofonts",
"//lib/js:highlightjs__files",
@@ -84,7 +73,6 @@
"cp $(locations //lib/fonts:robotofonts) $$TMP/polygerrit_ui/fonts/",
"for f in $(locations " + name + "_top_sources); do cp $$f $$TMP/polygerrit_ui/; done",
"for f in $(locations " + name + "_css_sources); do cp $$f $$TMP/polygerrit_ui/styles; done",
- "for f in $(locations " + name + "_theme_sources); do cp $$f $$TMP/polygerrit_ui/styles/themes; done",
"for f in $(locations //lib/js:highlightjs__files); do cp $$f $$TMP/polygerrit_ui/bower_components/highlightjs/ ; done",
"cp $(location @ui_npm//:node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js) $$TMP/polygerrit_ui/bower_components/webcomponentsjs/webcomponents-lite.js",
"cp $$FONT_DIR/roboto/*.ttf $$TMP/polygerrit_ui/fonts/roboto/",
@@ -94,63 +82,3 @@
"zip -qr $$ROOT/$@ *",
]),
)
-
-def _wct_test(name, srcs, split_index, split_count):
- """Macro to define single WCT suite
-
- Defines a private macro for a portion of test files with split_index.
- The actual split happens in test/tests.js file
-
- Args:
- name: name of generated sh_test
- srcs: source files
- split_index: index WCT suite. Must be less than split_count
- split_count: total number of WCT suites
- """
- str_index = str(split_index)
- config_json = struct(splitIndex = split_index, splitCount = split_count).to_json()
- native.sh_test(
- name = name,
- size = "enormous",
- srcs = ["wct_test.sh"],
- args = [
- "$(location @ui_dev_npm//web-component-tester/bin:wct)",
- config_json,
- ],
- data = [
- "@ui_dev_npm//web-component-tester/bin:wct",
- ] + srcs,
- # Should not run sandboxed.
- tags = [
- "local",
- "manual",
- "wct",
- ],
- )
-
-def wct_suite(name, srcs, split_count):
- """Define test suites for WCT tests.
-
- All tests files are split to split_count WCT suites
-
- Args:
- name: rule name. The macro create a test suite rule with the name name+"_test"
- srcs: source files
- split_count: number of sh_test (i.e. WCT suites)
- """
- tests = []
- for i in range(split_count):
- test_name = "wct_test_" + str(i)
- _wct_test(test_name, srcs, i, split_count)
- tests.append(test_name)
-
- native.test_suite(
- name = name + "_test",
- tests = tests,
- # Setup tags for suite as well.
- # This excludes tests from the wildcard expansion (//...)
- tags = [
- "local",
- "manual",
- ],
- )
diff --git a/polygerrit-ui/app/run_test.sh b/polygerrit-ui/app/run_test.sh
index a5231a1..2ca1118 100755
--- a/polygerrit-ui/app/run_test.sh
+++ b/polygerrit-ui/app/run_test.sh
@@ -6,13 +6,6 @@
bazel_bin=bazel
fi
-# WCT tests are not hermetic, and need extra environment variables.
-# TODO(hanwen): does $DISPLAY even work on OSX?
${bazel_bin} test \
- --test_env="HOME=$HOME" \
- --test_env="WCT_ARGS=${WCT_ARGS}" \
- --test_env="DISPLAY=${DISPLAY}" \
- --test_env="WCT_HEADLESS_MODE=${WCT_HEADLESS_MODE}" \
"$@" \
- //polygerrit-ui/app:wct_test \
//polygerrit-ui:karma_test
diff --git a/polygerrit-ui/app/scripts/gr-display-name-utils/gr-display-name-utils_test.html b/polygerrit-ui/app/scripts/gr-display-name-utils/gr-display-name-utils_test.js
similarity index 80%
rename from polygerrit-ui/app/scripts/gr-display-name-utils/gr-display-name-utils_test.html
rename to polygerrit-ui/app/scripts/gr-display-name-utils/gr-display-name-utils_test.js
index 818ddaa..94d96ad 100644
--- a/polygerrit-ui/app/scripts/gr-display-name-utils/gr-display-name-utils_test.html
+++ b/polygerrit-ui/app/scripts/gr-display-name-utils/gr-display-name-utils_test.js
@@ -1,31 +1,21 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2019 The Android Open Source Project
+/**
+ * @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.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-display-name-utils</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<script type="module">
-import '../../test/common-test-setup.js';
+import '../../test/common-test-setup-karma.js';
import {GrDisplayNameUtils} from './gr-display-name-utils.js';
suite('gr-display-name-utils tests', () => {
@@ -200,4 +190,4 @@
assert.equal(GrDisplayNameUtils._accountEmail(undefined), '');
});
});
-</script>
+
diff --git a/polygerrit-ui/app/scripts/gr-email-suggestions-provider/gr-email-suggestions-provider_test.html b/polygerrit-ui/app/scripts/gr-email-suggestions-provider/gr-email-suggestions-provider_test.html
deleted file mode 100644
index 80d3590..0000000
--- a/polygerrit-ui/app/scripts/gr-email-suggestions-provider/gr-email-suggestions-provider_test.html
+++ /dev/null
@@ -1,97 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-email-suggestions-provider</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../test/common-test-setup.js';
-import '../../elements/shared/gr-rest-api-interface/gr-rest-api-interface.js';
-import {GrEmailSuggestionsProvider} from './gr-email-suggestions-provider.js';
-
-suite('GrEmailSuggestionsProvider tests', () => {
- let sandbox;
- let restAPI;
- let provider;
- const account1 = {
- name: 'Some name',
- email: 'some@example.com',
- };
- const account2 = {
- email: 'other@example.com',
- _account_id: 3,
- };
-
- setup(() => {
- sandbox = sinon.sandbox.create();
-
- stub('gr-rest-api-interface', {
- getConfig() { return Promise.resolve({}); },
- });
- restAPI = fixture('basic');
- provider = new GrEmailSuggestionsProvider(restAPI);
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('getSuggestions', done => {
- const getSuggestedAccountsStub =
- sandbox.stub(restAPI, 'getSuggestedAccounts')
- .returns(Promise.resolve([account1, account2]));
-
- provider.getSuggestions('Some input').then(res => {
- assert.deepEqual(res, [account1, account2]);
- assert.isTrue(getSuggestedAccountsStub.calledOnce);
- assert.equal(getSuggestedAccountsStub.lastCall.args[0], 'Some input');
- done();
- });
- });
-
- test('makeSuggestionItem', () => {
- assert.deepEqual(provider.makeSuggestionItem(account1), {
- name: 'Some name <some@example.com>',
- value: {
- account: account1,
- count: 1,
- },
- });
-
- assert.deepEqual(provider.makeSuggestionItem(account2), {
- name: 'other@example.com <other@example.com>',
- value: {
- account: account2,
- count: 1,
- },
- });
- });
-});
-</script>
diff --git a/polygerrit-ui/app/scripts/gr-email-suggestions-provider/gr-email-suggestions-provider_test.js b/polygerrit-ui/app/scripts/gr-email-suggestions-provider/gr-email-suggestions-provider_test.js
new file mode 100644
index 0000000..7c40b7a
--- /dev/null
+++ b/polygerrit-ui/app/scripts/gr-email-suggestions-provider/gr-email-suggestions-provider_test.js
@@ -0,0 +1,78 @@
+/**
+ * @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.
+ */
+
+import '../../test/common-test-setup-karma.js';
+import '../../elements/shared/gr-rest-api-interface/gr-rest-api-interface.js';
+import {GrEmailSuggestionsProvider} from './gr-email-suggestions-provider.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const basicFixture = fixtureFromTemplate(html`
+<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
+`);
+
+suite('GrEmailSuggestionsProvider tests', () => {
+ let restAPI;
+ let provider;
+ const account1 = {
+ name: 'Some name',
+ email: 'some@example.com',
+ };
+ const account2 = {
+ email: 'other@example.com',
+ _account_id: 3,
+ };
+
+ setup(() => {
+ stub('gr-rest-api-interface', {
+ getConfig() { return Promise.resolve({}); },
+ });
+ restAPI = basicFixture.instantiate();
+ provider = new GrEmailSuggestionsProvider(restAPI);
+ });
+
+ test('getSuggestions', done => {
+ const getSuggestedAccountsStub =
+ sinon.stub(restAPI, 'getSuggestedAccounts')
+ .returns(Promise.resolve([account1, account2]));
+
+ provider.getSuggestions('Some input').then(res => {
+ assert.deepEqual(res, [account1, account2]);
+ assert.isTrue(getSuggestedAccountsStub.calledOnce);
+ assert.equal(getSuggestedAccountsStub.lastCall.args[0], 'Some input');
+ done();
+ });
+ });
+
+ test('makeSuggestionItem', () => {
+ assert.deepEqual(provider.makeSuggestionItem(account1), {
+ name: 'Some name <some@example.com>',
+ value: {
+ account: account1,
+ count: 1,
+ },
+ });
+
+ assert.deepEqual(provider.makeSuggestionItem(account2), {
+ name: 'other@example.com <other@example.com>',
+ value: {
+ account: account2,
+ count: 1,
+ },
+ });
+ });
+});
+
diff --git a/polygerrit-ui/app/scripts/gr-group-suggestions-provider/gr-group-suggestions-provider_test.html b/polygerrit-ui/app/scripts/gr-group-suggestions-provider/gr-group-suggestions-provider_test.html
deleted file mode 100644
index 2111b7e..0000000
--- a/polygerrit-ui/app/scripts/gr-group-suggestions-provider/gr-group-suggestions-provider_test.html
+++ /dev/null
@@ -1,105 +0,0 @@
-<!DOCTYPE html>
-<!--
-@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.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-group-suggestions-provider</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../test/common-test-setup.js';
-import '../../elements/shared/gr-rest-api-interface/gr-rest-api-interface.js';
-import {GrGroupSuggestionsProvider} from './gr-group-suggestions-provider.js';
-
-suite('GrGroupSuggestionsProvider tests', () => {
- let sandbox;
- let restAPI;
- let provider;
- const group1 = {
- name: 'Some name',
- id: 1,
- };
- const group2 = {
- name: 'Other name',
- id: 3,
- url: 'abcd',
- };
-
- setup(() => {
- sandbox = sinon.sandbox.create();
-
- stub('gr-rest-api-interface', {
- getConfig() { return Promise.resolve({}); },
- });
- restAPI = fixture('basic');
- provider = new GrGroupSuggestionsProvider(restAPI);
- });
-
- teardown(() => {
- sandbox.restore();
- });
-
- test('getSuggestions', done => {
- const getSuggestedAccountsStub =
- sandbox.stub(restAPI, 'getSuggestedGroups')
- .returns(Promise.resolve({
- 'Some name': {id: 1},
- 'Other name': {id: 3, url: 'abcd'},
- }));
-
- provider.getSuggestions('Some input').then(res => {
- assert.deepEqual(res, [group1, group2]);
- assert.isTrue(getSuggestedAccountsStub.calledOnce);
- assert.equal(getSuggestedAccountsStub.lastCall.args[0], 'Some input');
- done();
- });
- });
-
- test('makeSuggestionItem', () => {
- assert.deepEqual(provider.makeSuggestionItem(group1), {
- name: 'Some name',
- value: {
- group: {
- name: 'Some name',
- id: 1,
- },
- },
- });
-
- assert.deepEqual(provider.makeSuggestionItem(group2), {
- name: 'Other name',
- value: {
- group: {
- name: 'Other name',
- id: 3,
- },
- },
- });
- });
-});
-</script>
diff --git a/polygerrit-ui/app/scripts/gr-group-suggestions-provider/gr-group-suggestions-provider_test.js b/polygerrit-ui/app/scripts/gr-group-suggestions-provider/gr-group-suggestions-provider_test.js
new file mode 100644
index 0000000..0939f76
--- /dev/null
+++ b/polygerrit-ui/app/scripts/gr-group-suggestions-provider/gr-group-suggestions-provider_test.js
@@ -0,0 +1,86 @@
+/**
+ * @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.
+ */
+
+import '../../test/common-test-setup-karma.js';
+import '../../elements/shared/gr-rest-api-interface/gr-rest-api-interface.js';
+import {GrGroupSuggestionsProvider} from './gr-group-suggestions-provider.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const basicFixture = fixtureFromTemplate(html`
+<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
+`);
+
+suite('GrGroupSuggestionsProvider tests', () => {
+ let restAPI;
+ let provider;
+ const group1 = {
+ name: 'Some name',
+ id: 1,
+ };
+ const group2 = {
+ name: 'Other name',
+ id: 3,
+ url: 'abcd',
+ };
+
+ setup(() => {
+ stub('gr-rest-api-interface', {
+ getConfig() { return Promise.resolve({}); },
+ });
+ restAPI = basicFixture.instantiate();
+ provider = new GrGroupSuggestionsProvider(restAPI);
+ });
+
+ test('getSuggestions', done => {
+ const getSuggestedAccountsStub =
+ sinon.stub(restAPI, 'getSuggestedGroups')
+ .returns(Promise.resolve({
+ 'Some name': {id: 1},
+ 'Other name': {id: 3, url: 'abcd'},
+ }));
+
+ provider.getSuggestions('Some input').then(res => {
+ assert.deepEqual(res, [group1, group2]);
+ assert.isTrue(getSuggestedAccountsStub.calledOnce);
+ assert.equal(getSuggestedAccountsStub.lastCall.args[0], 'Some input');
+ done();
+ });
+ });
+
+ test('makeSuggestionItem', () => {
+ assert.deepEqual(provider.makeSuggestionItem(group1), {
+ name: 'Some name',
+ value: {
+ group: {
+ name: 'Some name',
+ id: 1,
+ },
+ },
+ });
+
+ assert.deepEqual(provider.makeSuggestionItem(group2), {
+ name: 'Other name',
+ value: {
+ group: {
+ name: 'Other name',
+ id: 3,
+ },
+ },
+ });
+ });
+});
+
diff --git a/polygerrit-ui/app/scripts/gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider_test.html b/polygerrit-ui/app/scripts/gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider_test.js
similarity index 79%
rename from polygerrit-ui/app/scripts/gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider_test.html
rename to polygerrit-ui/app/scripts/gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider_test.js
index 8774d48..fba4b26 100644
--- a/polygerrit-ui/app/scripts/gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider_test.html
+++ b/polygerrit-ui/app/scripts/gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider_test.js
@@ -1,44 +1,31 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2019 The Android Open Source Project
+/**
+ * @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.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-reviewer-suggestions-provider</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../test/common-test-setup.js';
+import '../../test/common-test-setup-karma.js';
import '../../elements/shared/gr-rest-api-interface/gr-rest-api-interface.js';
import {GrDisplayNameUtils} from '../gr-display-name-utils/gr-display-name-utils.js';
import {GrReviewerSuggestionsProvider, SUGGESTIONS_PROVIDERS_USERS_TYPES} from './gr-reviewer-suggestions-provider.js';
+import {html} from '@polymer/polymer/lib/utils/html-tag.js';
+
+const basicFixture = fixtureFromTemplate(html`
+<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
+`);
suite('GrReviewerSuggestionsProvider tests', () => {
- let sandbox;
let _nextAccountId = 0;
const makeAccount = function(opt_status) {
const accountId = ++_nextAccountId;
@@ -91,7 +78,7 @@
getConfig() { return Promise.resolve({}); },
});
- restAPI = fixture('basic');
+ restAPI = basicFixture.instantiate();
change = {
_number: 42,
owner,
@@ -100,13 +87,10 @@
REVIEWER: [existingReviewer2],
},
};
- sandbox = sinon.sandbox.create();
+
return flush(done);
});
- teardown(() => {
- sandbox.restore();
- });
suite('allowAnyUser set to false', () => {
setup(done => {
provider = GrReviewerSuggestionsProvider.create(restAPI, change._number,
@@ -180,7 +164,7 @@
value: {account, count: 1},
});
- sandbox.stub(GrDisplayNameUtils, '_accountEmail',
+ sinon.stub(GrDisplayNameUtils, '_accountEmail').callsFake(
() => '');
suggestion = provider.makeSuggestionItem(account3);
@@ -219,10 +203,10 @@
test('getChangeSuggestedReviewers is used', done => {
const suggestReviewerStub =
- sandbox.stub(restAPI, 'getChangeSuggestedReviewers')
+ sinon.stub(restAPI, 'getChangeSuggestedReviewers')
.returns(Promise.resolve([]));
const suggestAccountStub =
- sandbox.stub(restAPI, 'getSuggestedAccounts')
+ sinon.stub(restAPI, 'getSuggestedAccounts')
.returns(Promise.resolve([]));
provider.getSuggestions('').then(() => {
@@ -243,10 +227,10 @@
test('getSuggestedAccounts is used', done => {
const suggestReviewerStub =
- sandbox.stub(restAPI, 'getChangeSuggestedReviewers')
+ sinon.stub(restAPI, 'getChangeSuggestedReviewers')
.returns(Promise.resolve([]));
const suggestAccountStub =
- sandbox.stub(restAPI, 'getSuggestedAccounts')
+ sinon.stub(restAPI, 'getSuggestedAccounts')
.returns(Promise.resolve([]));
provider.getSuggestions('').then(() => {
@@ -258,4 +242,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/services/app-context-init_test.html b/polygerrit-ui/app/services/app-context-init_test.html
deleted file mode 100644
index f5dc7d1..0000000
--- a/polygerrit-ui/app/services/app-context-init_test.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2020 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<script type="module">
- import '../test/common-test-setup.js';
- import {appContext} from './app-context.js';
- import {initAppContext} from './app-context-init.js';
- suite('app context initializer tests', () => {
- setup(() => {
- initAppContext();
- });
-
- test('all services initialized and are singletons', () => {
- Object.keys(appContext).forEach(serviceName => {
- const service = appContext[serviceName];
- assert.isNotNull(service);
- const service2 = appContext[serviceName];
- assert.strictEqual(service, service2);
- });
- });
- });
-</script>
\ No newline at end of file
diff --git a/polygerrit-ui/app/services/app-context-init_test.js b/polygerrit-ui/app/services/app-context-init_test.js
new file mode 100644
index 0000000..9d22ec2
--- /dev/null
+++ b/polygerrit-ui/app/services/app-context-init_test.js
@@ -0,0 +1,35 @@
+/**
+ * @license
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import '../test/common-test-setup-karma.js';
+import {appContext} from './app-context.js';
+import {initAppContext} from './app-context-init.js';
+suite('app context initializer tests', () => {
+ setup(() => {
+ initAppContext();
+ });
+
+ test('all services initialized and are singletons', () => {
+ Object.keys(appContext).forEach(serviceName => {
+ const service = appContext[serviceName];
+ assert.isNotNull(service);
+ const service2 = appContext[serviceName];
+ assert.strictEqual(service, service2);
+ });
+ });
+});
+
diff --git a/polygerrit-ui/app/services/flags_test.html b/polygerrit-ui/app/services/flags_test.html
deleted file mode 100644
index 51efb0d..0000000
--- a/polygerrit-ui/app/services/flags_test.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2020 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<script>
- window.ENABLED_EXPERIMENTS = ['a', 'a'];
-</script>
-
-<script type="module">
- import '../test/common-test-setup.js';
- import {FlagsService} from './flags.js';
- suite('flags tests', () => {
- const flags = new FlagsService();
-
- test('isEnabled', () => {
- assert.equal(flags.isEnabled('a'), true);
- assert.equal(flags.isEnabled('random'), false);
- });
-
- test('enabledExperiments', () => {
- assert.deepEqual(flags.enabledExperiments, ['a']);
- });
- });
-</script>
\ No newline at end of file
diff --git a/polygerrit-ui/app/services/flags_test.js b/polygerrit-ui/app/services/flags_test.js
new file mode 100644
index 0000000..ae1033e
--- /dev/null
+++ b/polygerrit-ui/app/services/flags_test.js
@@ -0,0 +1,44 @@
+/**
+ * @license
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import '../test/common-test-setup-karma.js';
+import {FlagsService} from './flags.js';
+
+suite('flags tests', () => {
+ let originalEnabledExperiments;
+ let flags;
+
+ suiteSetup(() => {
+ originalEnabledExperiments = window.ENABLED_EXPERIMENTS;
+ window.ENABLED_EXPERIMENTS = ['a', 'a'];
+ flags = new FlagsService();
+ });
+
+ suiteTeardown(() => {
+ window.ENABLED_EXPERIMENTS = originalEnabledExperiments;
+ });
+
+ test('isEnabled', () => {
+ assert.equal(flags.isEnabled('a'), true);
+ assert.equal(flags.isEnabled('random'), false);
+ });
+
+ test('enabledExperiments', () => {
+ assert.deepEqual(flags.enabledExperiments, ['a']);
+ });
+});
+
diff --git a/polygerrit-ui/app/services/gr-event-interface/gr-event-interface_test.html b/polygerrit-ui/app/services/gr-event-interface/gr-event-interface_test.js
similarity index 69%
rename from polygerrit-ui/app/services/gr-event-interface/gr-event-interface_test.html
rename to polygerrit-ui/app/services/gr-event-interface/gr-event-interface_test.js
index ef2c539..1cdd6e3 100644
--- a/polygerrit-ui/app/services/gr-event-interface/gr-event-interface_test.html
+++ b/polygerrit-ui/app/services/gr-event-interface/gr-event-interface_test.js
@@ -1,56 +1,37 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2019 The Android Open Source Project
+/**
+ * @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.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-api-interface</title>
-
-<script src="../../../node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<test-fixture id="basic">
- <template>
- <gr-js-api-interface></gr-js-api-interface>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../test/common-test-setup.js';
+import '../../test/common-test-setup-karma.js';
import '../../elements/shared/gr-js-api-interface/gr-js-api-interface.js';
import {EventEmitter} from './gr-event-interface.js';
import {_testOnly_initGerritPluginApi} from '../../elements/shared/gr-js-api-interface/gr-gerrit.js';
+const basicFixture = fixtureFromElement('gr-js-api-interface');
+
const pluginApi = _testOnly_initGerritPluginApi();
suite('gr-event-interface tests', () => {
- let sandbox;
-
setup(() => {
- sandbox = sinon.sandbox.create();
- });
- teardown(() => {
- sandbox.restore();
});
suite('test on Gerrit', () => {
setup(() => {
- fixture('basic');
+ basicFixture.instantiate();
pluginApi.removeAllListeners();
});
@@ -149,4 +130,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/services/gr-reporting/gr-reporting_mock_test.html b/polygerrit-ui/app/services/gr-reporting/gr-reporting_mock_test.html
deleted file mode 100644
index e33a214..0000000
--- a/polygerrit-ui/app/services/gr-reporting/gr-reporting_mock_test.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2020 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<script type="module">
- import '../../test/common-test-setup.js';
- import {GrReporting} from './gr-reporting.js';
- import {grReportingMock} from './gr-reporting_mock.js';
- suite('gr-reporting_mock tests', () => {
- test('mocks all public methods', () => {
- const methods = Object.getOwnPropertyNames(GrReporting.prototype)
- .filter(name => typeof GrReporting.prototype[name] === 'function')
- .filter(name => !name.startsWith('_') && name !== 'constructor')
- .sort();
- const mockMethods = Object.getOwnPropertyNames(grReportingMock)
- .sort();
- assert.deepEqual(methods, mockMethods);
- });
- });
-</script>
\ No newline at end of file
diff --git a/polygerrit-ui/app/services/gr-reporting/gr-reporting_mock_test.js b/polygerrit-ui/app/services/gr-reporting/gr-reporting_mock_test.js
new file mode 100644
index 0000000..7c70e10
--- /dev/null
+++ b/polygerrit-ui/app/services/gr-reporting/gr-reporting_mock_test.js
@@ -0,0 +1,32 @@
+/**
+ * @license
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import '../../test/common-test-setup-karma.js';
+import {GrReporting} from './gr-reporting.js';
+import {grReportingMock} from './gr-reporting_mock.js';
+suite('gr-reporting_mock tests', () => {
+ test('mocks all public methods', () => {
+ const methods = Object.getOwnPropertyNames(GrReporting.prototype)
+ .filter(name => typeof GrReporting.prototype[name] === 'function')
+ .filter(name => !name.startsWith('_') && name !== 'constructor')
+ .sort();
+ const mockMethods = Object.getOwnPropertyNames(grReportingMock)
+ .sort();
+ assert.deepEqual(methods, mockMethods);
+ });
+});
+
diff --git a/polygerrit-ui/app/services/gr-reporting/gr-reporting_test.html b/polygerrit-ui/app/services/gr-reporting/gr-reporting_test.js
similarity index 83%
rename from polygerrit-ui/app/services/gr-reporting/gr-reporting_test.html
rename to polygerrit-ui/app/services/gr-reporting/gr-reporting_test.js
index e309c8c..01ba3cb 100644
--- a/polygerrit-ui/app/services/gr-reporting/gr-reporting_test.html
+++ b/polygerrit-ui/app/services/gr-reporting/gr-reporting_test.js
@@ -1,52 +1,39 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2016 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>gr-reporting</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-services-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-
-<script type="module">
-import '../../test/common-test-setup.js';
+import '../../test/common-test-setup-karma.js';
import {GrReporting, DEFAULT_STARTUP_TIMERS, initErrorReporter} from './gr-reporting.js';
import {appContext} from '../app-context.js';
suite('gr-reporting tests', () => {
let service;
- let sandbox;
+
let clock;
let fakePerformance;
const NOW_TIME = 100;
setup(() => {
- sandbox = sinon.sandbox.create();
clock = sinon.useFakeTimers(NOW_TIME);
service = new GrReporting(appContext.flagsService);
service._baselines = Object.assign({}, DEFAULT_STARTUP_TIMERS);
- sandbox.stub(service, 'reporter');
+ sinon.stub(service, 'reporter');
});
teardown(() => {
- sandbox.restore();
clock.restore();
});
@@ -56,9 +43,8 @@
loadEventEnd: 2,
};
fakePerformance.toJSON = () => fakePerformance;
- sinon.stub(service, 'performanceTiming',
- {get() { return fakePerformance; }});
- sandbox.stub(window.performance, 'now').returns(42);
+ sinon.stub(service, 'performanceTiming').get(() => fakePerformance);
+ sinon.stub(window.performance, 'now').returns(42);
service.appStarted();
assert.isTrue(
service.reporter.calledWithMatch(
@@ -73,7 +59,7 @@
});
test('WebComponentsReady', () => {
- sandbox.stub(window.performance, 'now').returns(42);
+ sinon.stub(window.performance, 'now').returns(42);
service.timeEnd('WebComponentsReady');
assert.isTrue(service.reporter.calledWithMatch(
'timing-report', 'UI Latency', 'WebComponentsReady', 42
@@ -82,7 +68,7 @@
test('beforeLocationChanged', () => {
service._baselines['garbage'] = 'monster';
- sandbox.stub(service, 'time');
+ sinon.stub(service, 'time');
service.beforeLocationChanged();
assert.isTrue(service.time.calledWithExactly('DashboardDisplayed'));
assert.isTrue(service.time.calledWithExactly('ChangeDisplayed'));
@@ -93,7 +79,7 @@
});
test('changeDisplayed', () => {
- sandbox.spy(service, 'timeEnd');
+ sinon.spy(service, 'timeEnd');
service.changeDisplayed();
assert.isFalse(service.timeEnd.calledWith('ChangeDisplayed'));
assert.isTrue(service.timeEnd.calledWith('StartupChangeDisplayed'));
@@ -102,7 +88,7 @@
});
test('changeFullyLoaded', () => {
- sandbox.spy(service, 'timeEnd');
+ sinon.spy(service, 'timeEnd');
service.changeFullyLoaded();
assert.isFalse(
service.timeEnd.calledWithExactly('ChangeFullyLoaded'));
@@ -113,7 +99,7 @@
});
test('diffViewDisplayed', () => {
- sandbox.spy(service, 'timeEnd');
+ sinon.spy(service, 'timeEnd');
service.diffViewDisplayed();
assert.isFalse(service.timeEnd.calledWith('DiffViewDisplayed'));
assert.isTrue(service.timeEnd.calledWith('StartupDiffViewDisplayed'));
@@ -122,7 +108,7 @@
});
test('fileListDisplayed', () => {
- sandbox.spy(service, 'timeEnd');
+ sinon.spy(service, 'timeEnd');
service.fileListDisplayed();
assert.isFalse(
service.timeEnd.calledWithExactly('FileListDisplayed'));
@@ -133,7 +119,7 @@
});
test('dashboardDisplayed', () => {
- sandbox.spy(service, 'timeEnd');
+ sinon.spy(service, 'timeEnd');
service.dashboardDisplayed();
assert.isFalse(service.timeEnd.calledWith('DashboardDisplayed'));
assert.isTrue(service.timeEnd.calledWith('StartupDashboardDisplayed'));
@@ -142,8 +128,8 @@
});
test('dashboardDisplayed details', () => {
- sandbox.spy(service, 'timeEnd');
- sandbox.stub(window, 'performance', {
+ sinon.spy(service, 'timeEnd');
+ sinon.stub(window, 'performance').value( {
memory: {
usedJSHeapSize: 1024 * 1024,
},
@@ -186,8 +172,8 @@
};
setup(() => {
- sandbox.spy(service, 'timeEnd');
- nowStub = sandbox.stub(window.performance, 'now');
+ sinon.spy(service, 'timeEnd');
+ nowStub = sinon.stub(window.performance, 'now');
visibilityStateStub = {
value: value => {
Object.defineProperty(document, 'visibilityState',
@@ -239,7 +225,7 @@
visibilityStateStub.value('visible');
nowStub.returns(15);
service.beforeLocationChanged();
- service.timeEnd.reset();
+ service.timeEnd.resetHistory();
service.dashboardDisplayed();
assert.isTrue(
service.timeEnd.calledWithMatch('DashboardDisplayed',
@@ -249,7 +235,7 @@
});
test('time and timeEnd', () => {
- const nowStub = sandbox.stub(window.performance, 'now').returns(0);
+ const nowStub = sinon.stub(window.performance, 'now').returns(0);
service.time('foo');
nowStub.returns(1);
service.time('bar');
@@ -266,7 +252,7 @@
});
test('timer object', () => {
- const nowStub = sandbox.stub(window.performance, 'now').returns(100);
+ const nowStub = sinon.stub(window.performance, 'now').returns(100);
const timer = service.getTimer('foo-bar');
nowStub.returns(150);
timer.end();
@@ -284,7 +270,7 @@
});
test('timer object maximum', () => {
- const nowStub = sandbox.stub(window.performance, 'now').returns(100);
+ const nowStub = sinon.stub(window.performance, 'now').returns(100);
const timer = service.getTimer('foo-bar').withMaximum(100);
nowStub.returns(150);
timer.end();
@@ -298,8 +284,8 @@
test('recordDraftInteraction', () => {
const key = 'TimeBetweenDraftActions';
- const nowStub = sandbox.stub(window.performance, 'now').returns(100);
- const timingStub = sandbox.stub(service, '_reportTiming');
+ const nowStub = sinon.stub(window.performance, 'now').returns(100);
+ const timingStub = sinon.stub(service, '_reportTiming');
service.recordDraftInteraction();
assert.isFalse(timingStub.called);
@@ -321,7 +307,7 @@
});
test('timeEndWithAverage', () => {
- const nowStub = sandbox.stub(window.performance, 'now').returns(0);
+ const nowStub = sinon.stub(window.performance, 'now').returns(0);
nowStub.returns(1000);
service.time('foo');
nowStub.returns(1100);
@@ -342,7 +328,7 @@
test('reportInteraction', () => {
service.reporter.restore();
- sandbox.spy(service, '_reportEvent');
+ sinon.spy(service, '_reportEvent');
service.pluginsLoaded(); // so we don't cache
service.reportInteraction('button-click', {name: 'sendReply'});
assert.isTrue(service._reportEvent.getCall(2).calledWithMatch(
@@ -356,9 +342,9 @@
test('report start time', () => {
service.reporter.restore();
- sandbox.stub(window.performance, 'now').returns(42);
- sandbox.spy(service, '_reportEvent');
- const dispatchStub = sandbox.spy(document, 'dispatchEvent');
+ sinon.stub(window.performance, 'now').returns(42);
+ sinon.spy(service, '_reportEvent');
+ const dispatchStub = sinon.spy(document, 'dispatchEvent');
service.pluginsLoaded();
service.time('timeAction');
service.timeEnd('timeAction');
@@ -377,11 +363,11 @@
suite('plugins', () => {
setup(() => {
service.reporter.restore();
- sandbox.stub(service, '_reportEvent');
+ sinon.stub(service, '_reportEvent');
});
test('pluginsLoaded reports time', () => {
- sandbox.stub(window.performance, 'now').returns(42);
+ sinon.stub(window.performance, 'now').returns(42);
service.pluginsLoaded();
assert.isTrue(service._reportEvent.calledWithMatch(
{
@@ -463,7 +449,7 @@
this.handlers[type] = handler;
},
};
- sandbox.stub(console, 'error');
+ sinon.stub(console, 'error');
Object.defineProperty(appContext, 'reportingService', {
get() {
return service;
@@ -510,4 +496,4 @@
});
});
});
-</script>
+
diff --git a/polygerrit-ui/app/styles/fonts.css b/polygerrit-ui/app/styles/fonts.css
index 6d0a6c1..d81c296 100644
--- a/polygerrit-ui/app/styles/fonts.css
+++ b/polygerrit-ui/app/styles/fonts.css
@@ -9,7 +9,7 @@
font-style: normal;
font-weight: 400;
font-display: swap;
- src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v17/mem8YaGs126MiZpBA-UFW50bf8pkAp6a.woff2) format('woff2');
+ src: local('Open Sans Regular'), local('OpenSans-Regular'), url(../fonts/opensans-latin-ext-400.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@@ -18,7 +18,7 @@
font-style: normal;
font-weight: 400;
font-display: swap;
- src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v17/mem8YaGs126MiZpBA-UFVZ0bf8pkAg.woff2) format('woff2');
+ src: local('Open Sans Regular'), local('OpenSans-Regular'), url(../fonts/opensans-latin-400.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@@ -27,7 +27,7 @@
font-style: normal;
font-weight: 600;
font-display: swap;
- src: local('Open Sans SemiBold'), local('OpenSans-SemiBold'), url(https://fonts.gstatic.com/s/opensans/v17/mem5YaGs126MiZpBA-UNirkOXOhpKKSTj5PW.woff2) format('woff2');
+ src: local('Open Sans SemiBold'), local('OpenSans-SemiBold'), url(../fonts/opensans-latin-ext-600.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@@ -36,7 +36,7 @@
font-style: normal;
font-weight: 600;
font-display: swap;
- src: local('Open Sans SemiBold'), local('OpenSans-SemiBold'), url(https://fonts.gstatic.com/s/opensans/v17/mem5YaGs126MiZpBA-UNirkOUuhpKKSTjw.woff2) format('woff2');
+ src: local('Open Sans SemiBold'), local('OpenSans-SemiBold'), url(../fonts/opensans-latin-600.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@@ -45,7 +45,7 @@
font-style: normal;
font-weight: 700;
font-display: swap;
- src: local('Open Sans Bold'), local('OpenSans-Bold'), url(https://fonts.gstatic.com/s/opensans/v17/mem5YaGs126MiZpBA-UN7rgOXOhpKKSTj5PW.woff2) format('woff2');
+ src: local('Open Sans Bold'), local('OpenSans-Bold'), url(../fonts/opensans-latin-ext-700.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@@ -54,7 +54,7 @@
font-style: normal;
font-weight: 700;
font-display: swap;
- src: local('Open Sans Bold'), local('OpenSans-Bold'), url(https://fonts.gstatic.com/s/opensans/v17/mem5YaGs126MiZpBA-UN7rgOUuhpKKSTjw.woff2) format('woff2');
+ src: local('Open Sans Bold'), local('OpenSans-Bold'), url(../fonts/opensans-latin-700.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@@ -63,7 +63,7 @@
font-style: normal;
font-weight: 400;
font-display: swap;
- src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Mu7GxKKTU1Kvnz.woff2) format('woff2');
+ src: local('Roboto'), local('Roboto-Regular'), url(../fonts/roboto-latin-ext-400.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@@ -72,7 +72,7 @@
font-style: normal;
font-weight: 400;
font-display: swap;
- src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Mu4mxKKTU1Kg.woff2) format('woff2');
+ src: local('Roboto'), local('Roboto-Regular'), url(../fonts/roboto-latin-400.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@@ -81,7 +81,7 @@
font-style: normal;
font-weight: 500;
font-display: swap;
- src: local('Roboto Medium'), local('Roboto-Medium'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmEU9fChc4AMP6lbBP.woff2) format('woff2');
+ src: local('Roboto Medium'), local('Roboto-Medium'), url(../fonts/roboto-latin-ext-500.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@@ -90,7 +90,7 @@
font-style: normal;
font-weight: 500;
font-display: swap;
- src: local('Roboto Medium'), local('Roboto-Medium'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmEU9fBBc4AMP6lQ.woff2) format('woff2');
+ src: local('Roboto Medium'), local('Roboto-Medium'), url(../fonts/roboto-latin-500.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@@ -99,7 +99,7 @@
font-style: normal;
font-weight: 700;
font-display: swap;
- src: local('Roboto Bold'), local('Roboto-Bold'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmWUlfChc4AMP6lbBP.woff2) format('woff2');
+ src: local('Roboto Bold'), local('Roboto-Bold'), url(../fonts/roboto-latin-ext-700.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@@ -108,7 +108,7 @@
font-style: normal;
font-weight: 700;
font-display: swap;
- src: local('Roboto Bold'), local('Roboto-Bold'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmWUlfBBc4AMP6lQ.woff2) format('woff2');
+ src: local('Roboto Bold'), local('Roboto-Bold'), url(../fonts/roboto-latin-700.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@@ -117,7 +117,7 @@
font-style: normal;
font-weight: 400;
font-display: swap;
- src: local('Roboto Mono'), local('RobotoMono-Regular'), url(https://fonts.gstatic.com/s/robotomono/v7/L0x5DF4xlVMF-BfR8bXMIjhFq3-cXbKDO1w.woff2) format('woff2');
+ src: local('Roboto Mono'), local('RobotoMono-Regular'), url(../fonts/roboto-mono-latin-ext-400.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@@ -126,7 +126,7 @@
font-style: normal;
font-weight: 400;
font-display: swap;
- src: local('Roboto Mono'), local('RobotoMono-Regular'), url(https://fonts.gstatic.com/s/robotomono/v7/L0x5DF4xlVMF-BfR8bXMIjhLq3-cXbKD.woff2) format('woff2');
+ src: local('Roboto Mono'), local('RobotoMono-Regular'), url(../fonts/roboto-mono-latin-400.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@@ -135,7 +135,7 @@
font-style: normal;
font-weight: 500;
font-display: swap;
- src: local('Roboto Mono Medium'), local('RobotoMono-Medium'), url(https://fonts.gstatic.com/s/robotomono/v7/L0xkDF4xlVMF-BfR8bXMIjC4iGq_f7-pAVU_Lrg.woff2) format('woff2');
+ src: local('Roboto Mono Medium'), local('RobotoMono-Medium'), url(../fonts/roboto-mono-latin-ext-500.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@@ -144,7 +144,7 @@
font-style: normal;
font-weight: 500;
font-display: swap;
- src: local('Roboto Mono Medium'), local('RobotoMono-Medium'), url(https://fonts.gstatic.com/s/robotomono/v7/L0xkDF4xlVMF-BfR8bXMIjC4iGqxf7-pAVU_.woff2) format('woff2');
+ src: local('Roboto Mono Medium'), local('RobotoMono-Medium'), url(../fonts/roboto-mono-latin-500.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@@ -153,7 +153,7 @@
font-style: normal;
font-weight: 700;
font-display: swap;
- src: local('Roboto Mono Bold'), local('RobotoMono-Bold'), url(https://fonts.gstatic.com/s/robotomono/v7/L0xkDF4xlVMF-BfR8bXMIjDwjmq_f7-pAVU_Lrg.woff2) format('woff2');
+ src: local('Roboto Mono Bold'), local('RobotoMono-Bold'), url(../fonts/roboto-mono-latin-ext-700.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@@ -162,6 +162,6 @@
font-style: normal;
font-weight: 700;
font-display: swap;
- src: local('Roboto Mono Bold'), local('RobotoMono-Bold'), url(https://fonts.gstatic.com/s/robotomono/v7/L0xkDF4xlVMF-BfR8bXMIjDwjmqxf7-pAVU_.woff2) format('woff2');
+ src: local('Roboto Mono Bold'), local('RobotoMono-Bold'), url(../fonts/roboto-mono-latin-700.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
diff --git a/polygerrit-ui/app/styles/gr-change-list-styles.js b/polygerrit-ui/app/styles/gr-change-list-styles.js
index 4f4d7e3..a7f231b 100644
--- a/polygerrit-ui/app/styles/gr-change-list-styles.js
+++ b/polygerrit-ui/app/styles/gr-change-list-styles.js
@@ -121,8 +121,7 @@
@media only screen and (max-width: 100em) {
.assignee,
.branch,
- .owner,
- .reviewers {
+ .owner {
max-width: 10rem;
}
}
diff --git a/polygerrit-ui/app/styles/themes/app-theme.js b/polygerrit-ui/app/styles/themes/app-theme.js
index 718d6a5..1a8296f 100644
--- a/polygerrit-ui/app/styles/themes/app-theme.js
+++ b/polygerrit-ui/app/styles/themes/app-theme.js
@@ -16,217 +16,211 @@
*/
const $_documentContainer = document.createElement('template');
-$_documentContainer.innerHTML = `<custom-style><style is="custom-style">
-html {
- /**
- * When adding a new color variable make sure to also add it to the other
- * theme files in the same directory.
- *
- * For colors prefer lower case hex colors.
- *
- * Note that plugins might be using these variables, so removing a variable
- * can be a breaking change that should go into the release notes.
- */
-
- /* text colors */
- --primary-text-color: black;
- --link-color: #2a66d9;
- --comment-text-color: black;
- --deemphasized-text-color: #5F6368;
- --default-button-text-color: #2a66d9;
- --error-text-color: red;
- --primary-button-text-color: white;
- /* Used on text color for change list that doesn't need user's attention. */
- --reviewed-text-color: black;
- --vote-text-color: black;
- --status-text-color: white;
- --tooltip-text-color: white;
- --negative-red-text-color: #d93025;
- --positive-green-text-color: #188038;
-
- /* background colors */
- /* primary background colors */
- --background-color-primary: #ffffff;
- --background-color-secondary: #f8f9fa;
- --background-color-tertiary: #f1f3f4;
- /* directly derived from primary background colors */
- --chip-background-color: var(--background-color-tertiary);
- --default-button-background-color: var(--background-color-primary);
- --dialog-background-color: var(--background-color-primary);
- --dropdown-background-color: var(--background-color-primary);
- --expanded-background-color: var(--background-color-tertiary);
- --select-background-color: var(--background-color-secondary);
- --shell-command-background-color: var(--background-color-secondary);
- --shell-command-decoration-background-color: var(--background-color-tertiary);
- --table-header-background-color: var(--background-color-secondary);
- --table-subheader-background-color: var(--background-color-tertiary);
- --view-background-color: var(--background-color-primary);
- /* unique background colors */
- --assignee-highlight-color: #fcfad6;
- --edit-mode-background-color: #ebf5fb;
- --emphasis-color: #fff9c4;
- --hover-background-color: rgba(161, 194, 250, 0.2);
- --disabled-button-background-color: #e8eaed;
- --primary-button-background-color: #2a66d9;
- --selection-background-color: rgba(161, 194, 250, 0.1);
- --tooltip-background-color: #333;
- /* comment background colors */
- --comment-background-color: #e8eaed;
- --robot-comment-background-color: #e8f0fe;
- --unresolved-comment-background-color: #fef7e0;
- /* vote background colors */
- --vote-color-approved: #9fcc6b;
- --vote-color-disliked: #f7c4cb;
- --vote-color-neutral: #ebf5fb;
- --vote-color-recommended: #c9dfaf;
- --vote-color-rejected: #f7a1ad;
-
- /* misc colors */
- --border-color: #e8e8e8;
- --comment-separator-color: #dadce0;
-
- /* status colors */
- --status-merged: #188038;
- --status-abandoned: #5f6368;
- --status-wip: #795548;
- --status-private: #a142f4;
- --status-conflict: #d93025;
- --status-active: #1976d2;
- --status-ready: #b80672;
- --status-custom: #681da8;
-
- /* fonts */
- --font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
- --header-font-family: 'Open Sans', 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
- --monospace-font-family: 'Roboto Mono', 'SF Mono', 'Lucida Console', Monaco, monospace;
- --font-size-code: 12px; /* 12px mono */
- --font-size-mono: .929rem; /* 13px mono */
- --font-size-small: .857rem; /* 12px */
- --font-size-normal: 1rem; /* 14px */
- --font-size-h3: 1.143rem; /* 16px */
- --font-size-h2: 1.429rem; /* 20px */
- --font-size-h1: 1.714rem; /* 24px */
- --line-height-code: 1.334; /* 16px */
- --line-height-mono: 1.286rem; /* 18px */
- --line-height-small: 1.143rem; /* 16px */
- --line-height-normal: 1.429rem; /* 20px */
- --line-height-h3: 1.714rem; /* 24px */
- --line-height-h2: 2rem; /* 28px */
- --line-height-h1: 2.286rem; /* 32px */
- --font-weight-normal: 400; /* 400 is the same as 'normal' */
- --font-weight-bold: 500;
- --font-weight-h1: 400;
- --font-weight-h2: 400;
- --font-weight-h3: 400;
-
- /* spacing */
- --spacing-xxs: 1px;
- --spacing-xs: 2px;
- --spacing-s: 4px;
- --spacing-m: 8px;
- --spacing-l: 12px;
- --spacing-xl: 16px;
- --spacing-xxl: 24px;
-
- /* header and footer */
- --footer-background-color: transparent;
- --footer-border-top: none;
- --header-background-color: var(--background-color-tertiary);
- --header-border-bottom: 1px solid var(--border-color);
- --header-border-image: '';
- --header-box-shadow: none;
- --header-padding: 0 var(--spacing-l);
- --header-icon-size: 0em;
- --header-icon: none;
- --header-text-color: black;
- --header-title-content: 'Gerrit';
- --header-title-font-size: 1.75rem;
-
- /* diff colors */
- --dark-add-highlight-color: #aaf2aa;
- --dark-rebased-add-highlight-color: #d7d7f9;
- --dark-rebased-remove-highlight-color: #f7e8b7;
- --dark-remove-highlight-color: #ffcdd2;
- --diff-blank-background-color: var(--background-color-secondary);
- --diff-context-control-background-color: #fff7d4;
- --diff-context-control-border-color: #f6e6a5;
- --diff-context-control-color: var(--deemphasized-text-color);
- --diff-highlight-range-color: rgba(255, 213, 0, 0.5);
- --diff-highlight-range-hover-color: rgba(255, 255, 0, 0.5);
- --diff-selection-background-color: #c7dbf9;
- --diff-tab-indicator-color: var(--deemphasized-text-color);
- --diff-trailing-whitespace-indicator: #ff9ad2;
- --light-add-highlight-color: #d8fed8;
- --light-rebased-add-highlight-color: #eef;
- --light-remove-add-highlight-color: #fff8dc;
- --light-remove-highlight-color: #ffebee;
- --coverage-covered: #e0f2f1;
- --coverage-not-covered: #ffd1a4;
-
- /* syntax colors */
- --syntax-attr-color: #219;
- --syntax-attribute-color: var(--primary-text-color);
- --syntax-built_in-color: #30a;
- --syntax-comment-color: #3f7f5f;
- --syntax-default-color: var(--primary-text-color);
- --syntax-doctag-weight: bold;
- --syntax-function-color: var(--primary-text-color);
- --syntax-keyword-color: #9e0069;
- --syntax-link-color: #219;
- --syntax-literal-color: #219;
- --syntax-meta-color: #ff1717;
- --syntax-meta-keyword-color: #219;
- --syntax-number-color: #164;
- --syntax-params-color: var(--primary-text-color);
- --syntax-regexp-color: #fa8602;
- --syntax-selector-attr-color: #fa8602;
- --syntax-selector-class-color: #164;
- --syntax-selector-id-color: #2a00ff;
- --syntax-selector-pseudo-color: #fa8602;
- --syntax-string-color: #2a00ff;
- --syntax-tag-color: #170;
- --syntax-template-tag-color: #fa8602;
- --syntax-template-variable-color: #0000c0;
- --syntax-title-color: #0000c0;
- --syntax-type-color: #2a66d9;
- --syntax-variable-color: var(--primary-text-color);
-
- /* elevation */
- --elevation-level-1: 0px 1px 2px 0px rgba(60, 64, 67, .30), 0px 1px 3px 1px rgba(60, 64, 67, .15);
- --elevation-level-2: 0px 1px 2px 0px rgba(60, 64, 67, .30), 0px 2px 6px 2px rgba(60, 64, 67, .15);
- --elevation-level-3: 0px 1px 3px 0px rgba(60, 64, 67, .30), 0px 4px 8px 3px rgba(60, 64, 67, .15);
- --elevation-level-4: 0px 2px 3px 0px rgba(60, 64, 67, .30), 0px 6px 10px 4px rgba(60, 64, 67, .15);
- --elevation-level-5: 0px 4px 4px 0px rgba(60, 64, 67, .30), 0px 8px 12px 6px rgba(60, 64, 67, .15);
-
- /* misc */
- --border-radius: 4px;
- --reply-overlay-z-index: 1000;
-
- /* paper and iron component overrides */
- --iron-overlay-backdrop-background-color: black;
- --iron-overlay-backdrop-opacity: 0.32;
- --iron-overlay-backdrop: {
- transition: none;
- };
-}
-@media screen and (max-width: 50em) {
+$_documentContainer.innerHTML = `
+<custom-style id="light-theme"><style is="custom-style">
html {
+ /**
+ * When adding a new color variable make sure to also add it to the other
+ * theme files in the same directory.
+ *
+ * For colors prefer lower case hex colors.
+ *
+ * Note that plugins might be using these variables, so removing a variable
+ * can be a breaking change that should go into the release notes.
+ */
+
+ /* text colors */
+ --primary-text-color: black;
+ --link-color: #2a66d9;
+ --comment-text-color: black;
+ --deemphasized-text-color: #5F6368;
+ --default-button-text-color: #2a66d9;
+ --error-text-color: red;
+ --primary-button-text-color: white;
+ /* Used on text color for change list that doesn't need user's attention. */
+ --reviewed-text-color: black;
+ --vote-text-color: black;
+ --status-text-color: white;
+ --tooltip-text-color: white;
+ --negative-red-text-color: #d93025;
+ --positive-green-text-color: #188038;
+
+ /* background colors */
+ /* primary background colors */
+ --background-color-primary: #ffffff;
+ --background-color-secondary: #f8f9fa;
+ --background-color-tertiary: #f1f3f4;
+ /* directly derived from primary background colors */
+ --chip-background-color: var(--background-color-tertiary);
+ --default-button-background-color: var(--background-color-primary);
+ --dialog-background-color: var(--background-color-primary);
+ --dropdown-background-color: var(--background-color-primary);
+ --expanded-background-color: var(--background-color-tertiary);
+ --select-background-color: var(--background-color-secondary);
+ --shell-command-background-color: var(--background-color-secondary);
+ --shell-command-decoration-background-color: var(--background-color-tertiary);
+ --table-header-background-color: var(--background-color-secondary);
+ --table-subheader-background-color: var(--background-color-tertiary);
+ --view-background-color: var(--background-color-primary);
+ /* unique background colors */
+ --assignee-highlight-color: #fcfad6;
+ --edit-mode-background-color: #ebf5fb;
+ --emphasis-color: #fff9c4;
+ --hover-background-color: rgba(161, 194, 250, 0.2);
+ --disabled-button-background-color: #e8eaed;
+ --primary-button-background-color: #2a66d9;
+ --selection-background-color: rgba(161, 194, 250, 0.1);
+ --tooltip-background-color: #333;
+ /* comment background colors */
+ --comment-background-color: #e8eaed;
+ --robot-comment-background-color: #e8f0fe;
+ --unresolved-comment-background-color: #fef7e0;
+ /* vote background colors */
+ --vote-color-approved: #9fcc6b;
+ --vote-color-disliked: #f7c4cb;
+ --vote-color-neutral: #ebf5fb;
+ --vote-color-recommended: #c9dfaf;
+ --vote-color-rejected: #f7a1ad;
+
+ /* misc colors */
+ --border-color: #e8e8e8;
+ --comment-separator-color: #dadce0;
+
+ /* status colors */
+ --status-merged: #188038;
+ --status-abandoned: #5f6368;
+ --status-wip: #795548;
+ --status-private: #a142f4;
+ --status-conflict: #d93025;
+ --status-active: #1976d2;
+ --status-ready: #b80672;
+ --status-custom: #681da8;
+
+ /* fonts */
+ --font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
+ --header-font-family: 'Open Sans', 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
+ --monospace-font-family: 'Roboto Mono', 'SF Mono', 'Lucida Console', Monaco, monospace;
+ --font-size-code: 12px; /* 12px mono */
+ --font-size-mono: .929rem; /* 13px mono */
+ --font-size-small: .857rem; /* 12px */
+ --font-size-normal: 1rem; /* 14px */
+ --font-size-h3: 1.143rem; /* 16px */
+ --font-size-h2: 1.429rem; /* 20px */
+ --font-size-h1: 1.714rem; /* 24px */
+ --line-height-code: 1.334; /* 16px */
+ --line-height-mono: 1.286rem; /* 18px */
+ --line-height-small: 1.143rem; /* 16px */
+ --line-height-normal: 1.429rem; /* 20px */
+ --line-height-h3: 1.714rem; /* 24px */
+ --line-height-h2: 2rem; /* 28px */
+ --line-height-h1: 2.286rem; /* 32px */
+ --font-weight-normal: 400; /* 400 is the same as 'normal' */
+ --font-weight-bold: 500;
+ --font-weight-h1: 400;
+ --font-weight-h2: 400;
+ --font-weight-h3: 400;
+
+ /* spacing */
--spacing-xxs: 1px;
- --spacing-xs: 1px;
- --spacing-s: 2px;
- --spacing-m: 4px;
- --spacing-l: 8px;
- --spacing-xl: 12px;
- --spacing-xxl: 16px;
+ --spacing-xs: 2px;
+ --spacing-s: 4px;
+ --spacing-m: 8px;
+ --spacing-l: 12px;
+ --spacing-xl: 16px;
+ --spacing-xxl: 24px;
+
+ /* header and footer */
+ --footer-background-color: transparent;
+ --footer-border-top: none;
+ --header-background-color: var(--background-color-tertiary);
+ --header-border-bottom: 1px solid var(--border-color);
+ --header-border-image: '';
+ --header-box-shadow: none;
+ --header-padding: 0 var(--spacing-l);
+ --header-icon-size: 0em;
+ --header-icon: none;
+ --header-text-color: black;
+ --header-title-content: 'Gerrit';
+ --header-title-font-size: 1.75rem;
+
+ /* diff colors */
+ --dark-add-highlight-color: #aaf2aa;
+ --dark-rebased-add-highlight-color: #d7d7f9;
+ --dark-rebased-remove-highlight-color: #f7e8b7;
+ --dark-remove-highlight-color: #ffcdd2;
+ --diff-blank-background-color: var(--background-color-secondary);
+ --diff-context-control-background-color: #fff7d4;
+ --diff-context-control-border-color: #f6e6a5;
+ --diff-context-control-color: var(--deemphasized-text-color);
+ --diff-highlight-range-color: rgba(255, 213, 0, 0.5);
+ --diff-highlight-range-hover-color: rgba(255, 255, 0, 0.5);
+ --diff-selection-background-color: #c7dbf9;
+ --diff-tab-indicator-color: var(--deemphasized-text-color);
+ --diff-trailing-whitespace-indicator: #ff9ad2;
+ --light-add-highlight-color: #d8fed8;
+ --light-rebased-add-highlight-color: #eef;
+ --light-remove-add-highlight-color: #fff8dc;
+ --light-remove-highlight-color: #ffebee;
+ --coverage-covered: #e0f2f1;
+ --coverage-not-covered: #ffd1a4;
+
+ /* syntax colors */
+ --syntax-attr-color: #219;
+ --syntax-attribute-color: var(--primary-text-color);
+ --syntax-built_in-color: #30a;
+ --syntax-comment-color: #3f7f5f;
+ --syntax-default-color: var(--primary-text-color);
+ --syntax-doctag-weight: bold;
+ --syntax-function-color: var(--primary-text-color);
+ --syntax-keyword-color: #9e0069;
+ --syntax-link-color: #219;
+ --syntax-literal-color: #219;
+ --syntax-meta-color: #ff1717;
+ --syntax-meta-keyword-color: #219;
+ --syntax-number-color: #164;
+ --syntax-params-color: var(--primary-text-color);
+ --syntax-regexp-color: #fa8602;
+ --syntax-selector-attr-color: #fa8602;
+ --syntax-selector-class-color: #164;
+ --syntax-selector-id-color: #2a00ff;
+ --syntax-selector-pseudo-color: #fa8602;
+ --syntax-string-color: #2a00ff;
+ --syntax-tag-color: #170;
+ --syntax-template-tag-color: #fa8602;
+ --syntax-template-variable-color: #0000c0;
+ --syntax-title-color: #0000c0;
+ --syntax-type-color: #2a66d9;
+ --syntax-variable-color: var(--primary-text-color);
+
+ /* elevation */
+ --elevation-level-1: 0px 1px 2px 0px rgba(60, 64, 67, .30), 0px 1px 3px 1px rgba(60, 64, 67, .15);
+ --elevation-level-2: 0px 1px 2px 0px rgba(60, 64, 67, .30), 0px 2px 6px 2px rgba(60, 64, 67, .15);
+ --elevation-level-3: 0px 1px 3px 0px rgba(60, 64, 67, .30), 0px 4px 8px 3px rgba(60, 64, 67, .15);
+ --elevation-level-4: 0px 2px 3px 0px rgba(60, 64, 67, .30), 0px 6px 10px 4px rgba(60, 64, 67, .15);
+ --elevation-level-5: 0px 4px 4px 0px rgba(60, 64, 67, .30), 0px 8px 12px 6px rgba(60, 64, 67, .15);
+
+ /* misc */
+ --border-radius: 4px;
+ --reply-overlay-z-index: 1000;
+
+ /* paper and iron component overrides */
+ --iron-overlay-backdrop-background-color: black;
+ --iron-overlay-backdrop-opacity: 0.32;
+ --iron-overlay-backdrop: {
+ transition: none;
+ };
}
-}
+ @media screen and (max-width: 50em) {
+ html {
+ --spacing-xxs: 1px;
+ --spacing-xs: 1px;
+ --spacing-s: 2px;
+ --spacing-m: 4px;
+ --spacing-l: 8px;
+ --spacing-xl: 12px;
+ --spacing-xxl: 16px;
+ }
+ }
</style></custom-style>`;
-document.head.appendChild($_documentContainer.content);
-
-/*
- FIXME(polymer-modulizer): the above comments were extracted
- from HTML and may be out of place here. Review them and
- then delete this comment!
-*/
-
+document.head.appendChild($_documentContainer.content);
\ No newline at end of file
diff --git a/polygerrit-ui/app/styles/themes/dark-theme.html b/polygerrit-ui/app/styles/themes/dark-theme.js
similarity index 82%
rename from polygerrit-ui/app/styles/themes/dark-theme.html
rename to polygerrit-ui/app/styles/themes/dark-theme.js
index 18b2fd6..684f2fe 100644
--- a/polygerrit-ui/app/styles/themes/dark-theme.html
+++ b/polygerrit-ui/app/styles/themes/dark-theme.js
@@ -1,24 +1,27 @@
-<!--
-@license
-Copyright (C) 2019 The Android Open Source Project
+/**
+ * @license
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<dom-module id="dark-theme">
- <custom-style><style is="custom-style">
+function getStyleEl() {
+ const $_documentContainer = document.createElement('template');
+ $_documentContainer.innerHTML = `
+ <custom-style id="dark-theme"><style is="custom-style">
html {
/**
- * Sections and variables must stay consistent with app-theme.html.
+ * Sections and variables must stay consistent with app-theme.js.
*
* Only modify color variables in this theme file. dark-theme extends
* app-theme, so there is no need to repeat all variables, but for colors
@@ -153,5 +156,18 @@
/* rules applied to <html> */
background-color: var(--view-background-color);
}
- </style></custom-style>
-</dom-module>
+ </style></custom-style>`;
+
+ return $_documentContainer;
+}
+
+export function applyTheme() {
+ document.head.appendChild(getStyleEl().content);
+}
+
+export function removeTheme() {
+ const darkThemeEls = document.head.querySelectorAll('#dark-theme');
+ if (darkThemeEls.length) {
+ darkThemeEls.forEach(darkThemeEl => darkThemeEl.remove());
+ }
+}
diff --git a/polygerrit-ui/app/test/common-test-setup-karma.js b/polygerrit-ui/app/test/common-test-setup-karma.js
index 4fd3b03..cc934fc 100644
--- a/polygerrit-ui/app/test/common-test-setup-karma.js
+++ b/polygerrit-ui/app/test/common-test-setup-karma.js
@@ -14,11 +14,47 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
import './common-test-setup.js';
import '@polymer/test-fixture/test-fixture.js';
import 'chai/chai.js';
self.assert = window.chai.assert;
+self.expect = window.chai.expect;
+
+window.addEventListener('error', e => {
+ // For uncaught error mochajs doesn't print the full stack trace.
+ // We should print it ourselves.
+ console.error(e.error.stack.toString());
+});
+
+let originalOnBeforeUnload;
+
+suiteSetup(() => {
+ // This suiteSetup() method is called only once before all tests
+
+ // Can't use window.addEventListener("beforeunload",...) here,
+ // the handler is raised too late.
+ originalOnBeforeUnload = window.onbeforeunload;
+ window.onbeforeunload = e => {
+ // If a test reloads a page, we can't prevent it.
+ // However we can print earror and the stack trace with assert.fail
+ try {
+ throw new Error();
+ } catch (e) {
+ console.error('Page reloading attempt detected.');
+ console.error(e.stack.toString());
+ }
+ originalOnBeforeUnload(e);
+ };
+});
+
+suiteTeardown(() => {
+ // This suiteTeardown() method is called only once after all tests
+ window.onbeforeunload = originalOnBeforeUnload;
+});
+
+// Tests can use fake timers (sandbox.useFakeTimers)
+// Keep the original one for use in test utils methods.
+const nativeSetTimeout = window.setTimeout;
/**
* Triggers a flush of any pending events, observations, etc and calls you back
@@ -33,10 +69,10 @@
// (https://github.com/Polymer/polymer-dev/issues/851)
window.Polymer.dom.flush();
if (callback) {
- window.setTimeout(callback, 0);
+ nativeSetTimeout(callback, 0);
} else {
return new Promise(resolve => {
- window.setTimeout(resolve, 0);
+ nativeSetTimeout(resolve, 0);
});
}
}
diff --git a/polygerrit-ui/app/test/common-test-setup.js b/polygerrit-ui/app/test/common-test-setup.js
index 5131b9d..36e27ba 100644
--- a/polygerrit-ui/app/test/common-test-setup.js
+++ b/polygerrit-ui/app/test/common-test-setup.js
@@ -18,20 +18,19 @@
// TODO(dmfilippov): remove bundled-polymer.js imports when the following issue
// https://github.com/Polymer/polymer-resin/issues/9 is resolved.
import '../scripts/bundled-polymer.js';
-
+import './test-app-context-init.js';
import 'polymer-resin/standalone/polymer-resin.js';
import '@polymer/iron-test-helpers/iron-test-helpers.js';
import './test-router.js';
import {SafeTypes} from '../behaviors/safe-types-behavior/safe-types-behavior.js';
-import {appContext} from '../services/app-context.js';
-import {initAppContext} from '../services/app-context-init.js';
import {_testOnly_resetPluginLoader} from '../elements/shared/gr-js-api-interface/gr-plugin-loader.js';
-import {grReportingMock} from '../services/gr-reporting/gr-reporting_mock.js';
-
-// Returns true if tests run under the Karma
-function isKarmaTest() {
- return window.__karma__ !== undefined;
-}
+import {_testOnlyResetRestApi} from '../elements/shared/gr-js-api-interface/gr-plugin-rest-api.js';
+import {_testOnlyResetGrRestApiSharedObjects} from '../elements/shared/gr-rest-api-interface/gr-rest-api-interface.js';
+import {TestKeyboardShortcutBinder} from './test-utils';
+import {flushDebouncers} from '@polymer/polymer/lib/utils/debounce';
+import {_testOnly_getShortcutManagerInstance} from '../behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.js';
+import sinon from 'sinon/pkg/sinon-esm.js';
+window.sinon = sinon;
security.polymer_resin.install({
allowedIdentifierPrefixes: [''],
@@ -49,88 +48,98 @@
safeTypesBridge: SafeTypes.safeTypesBridge,
});
-// Default implementations of 'fixture' and 'stub' methods in
-// web-component-tester are incorrect. Default methods calls mocha teardown
-// method to register cleanup actions. Each call to the teardown method adds
-// additional 'afterEach' hook to a suite.
-// As a result, if a suite's setup(..) method calls fixture(..) or stub(..)
-// method, then additional afterEach hook is registered before each test.
-// In overall, afterEach hook is called testCount^2 instead of testCount.
-// When tests runs with the wct test runner, the runner adds listener for
-// the 'afterEach' and tries to make some UI and log udpates. These updates
-// are quite heavy, and after about 40-50 tests each test waste 0.5-1seconds.
-//
-// Our implementation uses global teardown to clean up everything. mocha calls
-// global teardown after each test. The cleanups array stores all functions
-// which must be called after a test ends.
-//
-// Note, that fixture(...) and stub(..) methods are registered different by
-// WCT. This is why these methods implemented slightly different here.
const cleanups = [];
-if (isKarmaTest() || !window.fixture) {
- // For karma always set our implementation
- // (karma doesn't provide the fixture method)
- window.fixture = function(fixtureId, model) {
- // This method is inspired by WCT method
- cleanups.push(() => document.getElementById(fixtureId).restore());
- return document.getElementById(fixtureId).create(model);
- };
-} else {
- // The following error is important for WCT tests.
- // If window.fixture already installed by WCT at this point, WCT tests
- // performance decreases rapidly.
- // It allows to catch performance problems earlier.
- throw new Error('window.fixture must be set before wct sets it');
-}
-// On the first call to the setup, WCT installs window.fixture
-// and window.stub methods
+// For karma always set our implementation
+// (karma doesn't provide the fixture method)
+window.fixture = function(fixtureId, model) {
+ // This method is inspired by web-component-tester method
+ cleanups.push(() => document.getElementById(fixtureId).restore());
+ return document.getElementById(fixtureId).create(model);
+};
+
setup(() => {
// If the following asserts fails - then window.stub is
// overwritten by some other code.
assert.equal(cleanups.length, 0);
-
- _testOnly_resetPluginLoader();
+ // The following calls is nessecary to avoid influence of previously executed
+ // tests.
+ TestKeyboardShortcutBinder.push();
+ const mgr = _testOnly_getShortcutManagerInstance();
+ assert.equal(mgr.activeHosts.size, 0);
+ assert.equal(mgr.listeners.size, 0);
+ document.getSelection().removeAllRanges();
+ const pl = _testOnly_resetPluginLoader();
+ // For testing, always init with empty plugin list
+ // Since when serve in gr-app, we always retrieve the list
+ // from project config and init loading after that, all
+ // `awaitPluginsLoaded` will rely on that to kick off,
+ // in testing, we want to kick start this earlier.
+ // You still can manually call _testOnly_resetPluginLoader
+ // to reset this behavior if you need to test something specific.
+ pl.loadPlugins([]);
+ _testOnlyResetGrRestApiSharedObjects();
+ _testOnlyResetRestApi();
});
-if (isKarmaTest() || window.stub) {
- // For karma always set our implementation
- // (karma doesn't provide the stub method)
- window.stub = function(tagName, implementation) {
- // This method is inspired by WCT method
- const proto = document.createElement(tagName).constructor.prototype;
- const stubs = Object.keys(implementation)
- .map(key => sinon.stub(proto, key, implementation[key]));
- cleanups.push(() => {
- stubs.forEach(stub => {
- stub.restore();
- });
+// For karma always set our implementation
+// (karma doesn't provide the stub method)
+window.stub = function(tagName, implementation) {
+ // This method is inspired by web-component-tester method
+ const proto = document.createElement(tagName).constructor.prototype;
+ const stubs = Object.keys(implementation)
+ .map(key => sinon.stub(proto, key).callsFake(implementation[key]));
+ cleanups.push(() => {
+ stubs.forEach(stub => {
+ stub.restore();
});
- };
-} else {
- // The following error is important for WCT tests.
- // If window.fixture already installed by WCT at this point, WCT tests
- // performance decreases rapidly.
- // It allows to catch performance problems earlier.
- throw new Error('window.stub must be set after wct sets it');
-}
-
-initAppContext();
-function setMock(serviceName, setupMock) {
- Object.defineProperty(appContext, serviceName, {
- get() {
- return setupMock;
- },
});
+};
+
+// Very simple function to catch unexpected elements in documents body.
+// It can't catch everything, but in most cases it is enough.
+function checkChildAllowed(element) {
+ const allowedTags = ['SCRIPT', 'IRON-A11Y-ANNOUNCER'];
+ if (allowedTags.includes(element.tagName)) {
+ return;
+ }
+ if (element.tagName === 'TEST-FIXTURE') {
+ if (element.children.length == 0 ||
+ (element.children.length == 1 &&
+ element.children[0].tagName === 'TEMPLATE')) {
+ return;
+ }
+ assert.fail(`Test fixture
+ ${element.outerHTML}` +
+ `isn't resotred after the test is finished. Please ensure that ` +
+ `restore() method is called for this test-fixture. Usually the call` +
+ `happens automatically.`);
+ return;
+ }
+ if (element.tagName === 'DIV' && element.id === 'gr-hovercard-container' &&
+ element.childNodes.length === 0) {
+ return;
+ }
+ assert.fail(
+ `The following node remains in document after the test:
+ ${element.tagName}
+ Outer HTML:
+ ${element.outerHTML},
+ Stack trace:
+ ${element.stackTrace}`);
}
-setMock('reportingService', grReportingMock);
+function checkGlobalSpace() {
+ for (const child of document.body.children) {
+ checkChildAllowed(child);
+ }
+}
teardown(() => {
- // WCT incorrectly uses teardown method in the 'fixture' and 'stub'
- // implementations. This leads to slowdown WCT tests after each tests.
- // I.e. more tests in a file - longer it takes.
- // For example, gr-file-list_test.html takes approx 40 second without
- // a fix and 10 seconds with our implementation of fixture and stub.
+ sinon.restore();
cleanups.forEach(cleanup => cleanup());
cleanups.splice(0);
+ TestKeyboardShortcutBinder.pop();
+ checkGlobalSpace();
+ // Clean Polymer debouncer queue, so next tests will not be affected.
+ flushDebouncers();
});
diff --git a/polygerrit-ui/app/test/index.html b/polygerrit-ui/app/test/index.html
deleted file mode 100644
index 63df0be..0000000
--- a/polygerrit-ui/app/test/index.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!-- Copyright (C) 2020 The Android Open Source Project -->
-<!-- -->
-<!-- Licensed under the Apache License, Version 2.0 (the "License"); -->
-<!-- you may not use this file except in compliance with the License. -->
-<!-- You may obtain a copy of the License at -->
-<!-- -->
-<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
-<!-- -->
-<!-- Unless required by applicable law or agreed to in writing, software -->
-<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
-<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
-<!-- See the License for the specific language governing permissions and -->
-<!-- limitations under the License. -->
-
-<!DOCTYPE html>
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<meta charset="utf-8">
-<title>Elements Test Runner</title>
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/node_modules/web-component-tester/browser.js"></script>
-<style>
- /* Prevent horizontal scrolling on page.
- New version of web-component-tester creates very narrow iframe */
- #subsuites {
- width: 1500px !important;
- }
-</style>
-<script type="module">
- import {config, testsPerFileString} from './suite_conf.js';
- import {getSuiteTests} from './tests.js';
- WCT.loadSuites(
- getSuiteTests(testsPerFileString, config.splitIndex, config.splitCount));
-</script>
diff --git a/polygerrit-ui/app/test/mocks/comment-api.js b/polygerrit-ui/app/test/mocks/comment-api.js
index 77c72d4..f2ca48c 100644
--- a/polygerrit-ui/app/test/mocks/comment-api.js
+++ b/polygerrit-ui/app/test/mocks/comment-api.js
@@ -19,11 +19,13 @@
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
+/**
+ * This is an "abstract" class for tests. The descendant must define a template
+ * for this element and a tagName - see createCommentApiMockWithTemplateElement below
+ */
class CommentApiMock extends GestureEventListeners(
LegacyElementMixin(
PolymerElement)) {
- static get is() { return 'comment-api-mock'; }
-
static get properties() {
return {
_changeComments: Object,
@@ -52,4 +54,18 @@
}
}
-customElements.define(CommentApiMock.is, CommentApiMock);
+/**
+ * Creates a new element which is descendant of CommentApiMock with specified
+ * template. Additionally, the method registers a tagName for this element.
+ *
+ * Each tagName must be a unique accross all tests.
+ */
+export function createCommentApiMockWithTemplateElement(tagName, template) {
+ const elementClass = class extends CommentApiMock {
+ static get is() { return tagName; }
+
+ static get template() { return template; }
+ };
+ customElements.define(tagName, elementClass);
+ return elementClass;
+}
diff --git a/polygerrit-ui/app/test/suite_conf.js b/polygerrit-ui/app/test/suite_conf.js
deleted file mode 100644
index 82870fe..0000000
--- a/polygerrit-ui/app/test/suite_conf.js
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * @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.
- */
-
-/**
- * This file is an example of the content.
- * The real file is generated by the wct_test.sh script.
- * Content of this file doesn't affect wct tests.
- * Generated files contains all information to split test files between different tests
- */
-
-export const config = {
- splitIndex: 0, // Index for split (wct_suite creates several sh_test, each split has its own index)
- splitCount: 1, // Defines the number of splits
-};
-
-/**
- * testsPerFileString contains information about number of tests in each file
- * This information is not precise. It is used to split test files between WCT suites more evenly.
- */
-export const testsPerFileString = `
-./elements/change-list/gr-repo-header/gr-repo-header_test.html:1
-./elements/change-list/gr-dashboard-view/gr-dashboard-view_test.html:25
-./elements/gr-app_test.html:4
-./behaviors/gr-admin-nav-behavior/gr-admin-nav-behavior_test.html:13
-./behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior_test.html:19
-`;
diff --git a/polygerrit-ui/app/test/test-app-context-init.js b/polygerrit-ui/app/test/test-app-context-init.js
new file mode 100644
index 0000000..6fffdba
--- /dev/null
+++ b/polygerrit-ui/app/test/test-app-context-init.js
@@ -0,0 +1,32 @@
+/**
+ * @license
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Init app context before any other imports
+import {initAppContext} from '../services/app-context-init.js';
+import {grReportingMock} from '../services/gr-reporting/gr-reporting_mock';
+import {appContext} from '../services/app-context.js';
+
+initAppContext();
+
+function setMock(serviceName, setupMock) {
+ Object.defineProperty(appContext, serviceName, {
+ get() {
+ return setupMock;
+ },
+ });
+}
+setMock('reportingService', grReportingMock);
diff --git a/polygerrit-ui/app/test/test-utils.js b/polygerrit-ui/app/test/test-utils.js
index 77d8e22..aaab295 100644
--- a/polygerrit-ui/app/test/test-utils.js
+++ b/polygerrit-ui/app/test/test-utils.js
@@ -18,6 +18,7 @@
import {_testOnly_resetPluginLoader} from '../elements/shared/gr-js-api-interface/gr-plugin-loader.js';
import {testOnly_resetInternalState} from '../elements/shared/gr-js-api-interface/gr-api-utils.js';
import {_testOnly_resetEndpoints} from '../elements/shared/gr-js-api-interface/gr-plugin-endpoints.js';
+import {KeyboardShortcutBinder, _testOnly_getShortcutManagerInstance} from '../behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.js';
export const mockPromise = () => {
let res;
@@ -29,10 +30,42 @@
};
export const isHidden = el => getComputedStyle(el).display === 'none';
+// Some tests/elements can define its own binding. We want to restore bindings
+// at the end of the test. The TestKeyboardShortcutBinder store bindings in
+// stack, so it is possible to override bindings in nested suites.
+export class TestKeyboardShortcutBinder {
+ static push() {
+ if (!this.stack) {
+ this.stack = [];
+ }
+ const testBinder = new TestKeyboardShortcutBinder();
+ this.stack.push(testBinder);
+ return KeyboardShortcutBinder;
+ }
+
+ static pop() {
+ this.stack.pop()._restoreShortcuts();
+ }
+
+ constructor() {
+ this._originalBinding = new Map(
+ _testOnly_getShortcutManagerInstance().bindings);
+ }
+
+ _restoreShortcuts() {
+ const bindings = _testOnly_getShortcutManagerInstance().bindings;
+ bindings.clear();
+ this._originalBinding.forEach((value, key) => {
+ bindings.set(key, value);
+ });
+ }
+}
+
// Provide reset plugins function to clear installed plugins between tests.
// No gr-app found (running tests)
export const resetPlugins = () => {
testOnly_resetInternalState();
_testOnly_resetEndpoints();
- _testOnly_resetPluginLoader();
+ const pl = _testOnly_resetPluginLoader();
+ pl.loadPlugins([]);
};
diff --git a/polygerrit-ui/app/test/tests.js b/polygerrit-ui/app/test/tests.js
deleted file mode 100644
index 2d795ec..0000000
--- a/polygerrit-ui/app/test/tests.js
+++ /dev/null
@@ -1,335 +0,0 @@
-/**
- * @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.
- */
-
-const testFiles = [];
-const scriptsPath = '../scripts/';
-const elementsPath = '../elements/';
-const behaviorsPath = '../behaviors/';
-const servicesPath = '../services/';
-
-// Elements tests.
-/* eslint-disable max-len */
-const elements = [
- // This seemed to be flaky when it was farther down the list. Keep at the
- // beginning.
- 'gr-app_test.html',
- 'admin/gr-admin-group-list/gr-admin-group-list_test.html',
- 'admin/gr-admin-view/gr-admin-view_test.html',
- 'admin/gr-confirm-delete-item-dialog/gr-confirm-delete-item-dialog_test.html',
- 'admin/gr-create-change-dialog/gr-create-change-dialog_test.html',
- 'admin/gr-create-group-dialog/gr-create-group-dialog_test.html',
- 'admin/gr-create-pointer-dialog/gr-create-pointer-dialog_test.html',
- 'admin/gr-create-repo-dialog/gr-create-repo-dialog_test.html',
- 'admin/gr-group-audit-log/gr-group-audit-log_test.html',
- 'admin/gr-group-members/gr-group-members_test.html',
- 'admin/gr-group/gr-group_test.html',
- 'admin/gr-permission/gr-permission_test.html',
- 'admin/gr-plugin-config-array-editor/gr-plugin-config-array-editor_test.html',
- 'admin/gr-plugin-list/gr-plugin-list_test.html',
- 'admin/gr-repo-access/gr-repo-access_test.html',
- 'admin/gr-repo-commands/gr-repo-commands_test.html',
- 'admin/gr-repo-dashboards/gr-repo-dashboards_test.html',
- 'admin/gr-repo-detail-list/gr-repo-detail-list_test.html',
- 'admin/gr-repo-list/gr-repo-list_test.html',
- 'admin/gr-repo-plugin-config/gr-repo-plugin-config_test.html',
- 'admin/gr-repo/gr-repo_test.html',
- 'admin/gr-rule-editor/gr-rule-editor_test.html',
- 'change-list/gr-change-list-item/gr-change-list-item_test.html',
- 'change-list/gr-change-list-view/gr-change-list-view_test.html',
- 'change-list/gr-change-list/gr-change-list_test.html',
- 'change-list/gr-create-commands-dialog/gr-create-commands-dialog_test.html',
- 'change-list/gr-create-change-help/gr-create-change-help_test.html',
- 'change-list/gr-dashboard-view/gr-dashboard-view_test.html',
- 'change-list/gr-repo-header/gr-repo-header_test.html',
- 'change-list/gr-user-header/gr-user-header_test.html',
- 'change/gr-change-actions/gr-change-actions_test.html',
- 'change/gr-change-metadata/gr-change-metadata-it_test.html',
- 'change/gr-change-metadata/gr-change-metadata_test.html',
- 'change/gr-change-requirements/gr-change-requirements_test.html',
- 'change/gr-comment-list/gr-comment-list_test.html',
- 'change/gr-commit-info/gr-commit-info_test.html',
- 'change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog_test.html',
- 'change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.html',
- 'change/gr-confirm-cherrypick-conflict-dialog/gr-confirm-cherrypick-conflict-dialog_test.html',
- 'change/gr-confirm-move-dialog/gr-confirm-move-dialog_test.html',
- 'change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog_test.html',
- 'change/gr-confirm-revert-dialog/gr-confirm-revert-dialog_test.html',
- 'change/gr-confirm-submit-dialog/gr-confirm-submit-dialog_test.html',
- 'change/gr-download-dialog/gr-download-dialog_test.html',
- 'change/gr-file-list-header/gr-file-list-header_test.html',
- 'change/gr-file-list/gr-file-list_test.html',
- 'change/gr-included-in-dialog/gr-included-in-dialog_test.html',
- 'change/gr-label-score-row/gr-label-score-row_test.html',
- 'change/gr-label-scores/gr-label-scores_test.html',
- 'change/gr-message/gr-message_test.html',
- 'change/gr-messages-list/gr-messages-list_test.html',
- 'change/gr-messages-list/gr-messages-list-experimental_test.html',
- 'change/gr-related-changes-list/gr-related-changes-list_test.html',
- 'change/gr-reply-dialog/gr-reply-dialog-it_test.html',
- 'change/gr-reply-dialog/gr-reply-dialog_test.html',
- 'change/gr-reviewer-list/gr-reviewer-list_test.html',
- 'change/gr-thread-list/gr-thread-list_test.html',
- 'change/gr-upload-help-dialog/gr-upload-help-dialog_test.html',
- 'core/gr-account-dropdown/gr-account-dropdown_test.html',
- 'core/gr-error-dialog/gr-error-dialog_test.html',
- 'core/gr-error-manager/gr-error-manager_test.html',
- 'core/gr-key-binding-display/gr-key-binding-display_test.html',
- 'core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog_test.html',
- 'core/gr-main-header/gr-main-header_test.html',
- 'core/gr-navigation/gr-navigation_test.html',
- 'core/gr-router/gr-router_test.html',
- 'core/gr-search-bar/gr-search-bar_test.html',
- 'core/gr-smart-search/gr-smart-search_test.html',
- 'diff/gr-comment-api/gr-comment-api_test.html',
- 'diff/gr-coverage-layer/gr-coverage-layer_test.html',
- 'diff/gr-diff-builder/gr-diff-builder-element_test.html',
- 'diff/gr-diff-builder/gr-diff-builder-unified_test.html',
- 'diff/gr-diff-cursor/gr-diff-cursor_test.html',
- 'diff/gr-diff-highlight/gr-annotation_test.html',
- 'diff/gr-diff-highlight/gr-diff-highlight_test.html',
- 'diff/gr-diff-host/gr-diff-host_test.html',
- 'diff/gr-diff-mode-selector/gr-diff-mode-selector_test.html',
- 'diff/gr-diff-preferences-dialog/gr-diff-preferences-dialog_test.html',
- 'diff/gr-diff-processor/gr-diff-processor_test.html',
- 'diff/gr-diff-selection/gr-diff-selection_test.html',
- 'diff/gr-diff-view/gr-diff-view_test.html',
- 'diff/gr-diff/gr-diff-group_test.html',
- 'diff/gr-apply-fix-dialog/gr-apply-fix-dialog_test.html',
- 'diff/gr-patch-range-select/gr-patch-range-select_test.html',
- 'diff/gr-ranged-comment-layer/gr-ranged-comment-layer_test.html',
- 'diff/gr-selection-action-box/gr-selection-action-box_test.html',
- 'diff/gr-syntax-layer/gr-syntax-layer_test.html',
- 'documentation/gr-documentation-search/gr-documentation-search_test.html',
- 'edit/gr-default-editor/gr-default-editor_test.html',
- 'edit/gr-edit-controls/gr-edit-controls_test.html',
- 'edit/gr-edit-file-controls/gr-edit-file-controls_test.html',
- 'edit/gr-editor-view/gr-editor-view_test.html',
- 'plugins/gr-admin-api/gr-admin-api_test.html',
- 'plugins/gr-styles-api/gr-styles-api_test.html',
- 'plugins/gr-attribute-helper/gr-attribute-helper_test.html',
- 'plugins/gr-dom-hooks/gr-dom-hooks_test.html',
- 'plugins/gr-endpoint-decorator/gr-endpoint-decorator_test.html',
- 'plugins/gr-event-helper/gr-event-helper_test.html',
- 'plugins/gr-external-style/gr-external-style_test.html',
- 'plugins/gr-plugin-host/gr-plugin-host_test.html',
- 'plugins/gr-popup-interface/gr-plugin-popup_test.html',
- 'plugins/gr-popup-interface/gr-popup-interface_test.html',
- 'plugins/gr-repo-api/gr-repo-api_test.html',
- 'plugins/gr-settings-api/gr-settings-api_test.html',
- 'plugins/gr-theme-api/gr-theme-api_test.html',
- 'settings/gr-account-info/gr-account-info_test.html',
- 'settings/gr-agreements-list/gr-agreements-list_test.html',
- 'settings/gr-change-table-editor/gr-change-table-editor_test.html',
- 'settings/gr-cla-view/gr-cla-view_test.html',
- 'settings/gr-edit-preferences/gr-edit-preferences_test.html',
- 'settings/gr-email-editor/gr-email-editor_test.html',
- 'settings/gr-gpg-editor/gr-gpg-editor_test.html',
- 'settings/gr-group-list/gr-group-list_test.html',
- 'settings/gr-http-password/gr-http-password_test.html',
- 'settings/gr-identities/gr-identities_test.html',
- 'settings/gr-menu-editor/gr-menu-editor_test.html',
- 'settings/gr-registration-dialog/gr-registration-dialog_test.html',
- 'settings/gr-settings-view/gr-settings-view_test.html',
- 'settings/gr-ssh-editor/gr-ssh-editor_test.html',
- 'settings/gr-watched-projects-editor/gr-watched-projects-editor_test.html',
- 'shared/gr-account-entry/gr-account-entry_test.html',
- 'shared/gr-account-label/gr-account-label_test.html',
- 'shared/gr-account-list/gr-account-list_test.html',
- 'shared/gr-account-link/gr-account-link_test.html',
- 'shared/gr-alert/gr-alert_test.html',
- 'shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown_test.html',
- 'shared/gr-avatar/gr-avatar_test.html',
- 'shared/gr-button/gr-button_test.html',
- 'shared/gr-change-star/gr-change-star_test.html',
- 'shared/gr-change-status/gr-change-status_test.html',
- 'shared/gr-comment-thread/gr-comment-thread_test.html',
- 'shared/gr-comment/gr-comment_test.html',
- 'shared/gr-copy-clipboard/gr-copy-clipboard_test.html',
- 'shared/gr-count-string-formatter/gr-count-string-formatter_test.html',
- 'shared/gr-date-formatter/gr-date-formatter_test.html',
- 'shared/gr-dialog/gr-dialog_test.html',
- 'shared/gr-diff-preferences/gr-diff-preferences_test.html',
- 'shared/gr-download-commands/gr-download-commands_test.html',
- 'shared/gr-dropdown/gr-dropdown_test.html',
- 'shared/gr-dropdown-list/gr-dropdown-list_test.html',
- 'shared/gr-editable-content/gr-editable-content_test.html',
- 'shared/gr-editable-label/gr-editable-label_test.html',
- 'shared/gr-formatted-text/gr-formatted-text_test.html',
- 'shared/gr-hovercard/gr-hovercard_test.html',
- 'shared/gr-hovercard-account/gr-hovercard-account_test.html',
- 'shared/gr-js-api-interface/gr-annotation-actions-context_test.html',
- 'shared/gr-js-api-interface/gr-annotation-actions-js-api_test.html',
- 'shared/gr-js-api-interface/gr-change-actions-js-api_test.html',
- 'shared/gr-js-api-interface/gr-change-reply-js-api_test.html',
- 'shared/gr-js-api-interface/gr-api-utils_test.html',
- 'shared/gr-js-api-interface/gr-js-api-interface_test.html',
- 'shared/gr-js-api-interface/gr-gerrit_test.html',
- 'shared/gr-js-api-interface/gr-plugin-action-context_test.html',
- 'shared/gr-js-api-interface/gr-plugin-loader_test.html',
- 'shared/gr-js-api-interface/gr-plugin-endpoints_test.html',
- 'shared/gr-js-api-interface/gr-plugin-rest-api_test.html',
- 'shared/gr-fixed-panel/gr-fixed-panel_test.html',
- 'shared/gr-labeled-autocomplete/gr-labeled-autocomplete_test.html',
- 'shared/gr-label-info/gr-label-info_test.html',
- 'shared/gr-lib-loader/gr-lib-loader_test.html',
- 'shared/gr-limited-text/gr-limited-text_test.html',
- 'shared/gr-linked-chip/gr-linked-chip_test.html',
- 'shared/gr-linked-text/gr-linked-text_test.html',
- 'shared/gr-list-view/gr-list-view_test.html',
- 'shared/gr-overlay/gr-overlay_test.html',
- 'shared/gr-page-nav/gr-page-nav_test.html',
- 'shared/gr-repo-branch-picker/gr-repo-branch-picker_test.html',
- 'shared/gr-rest-api-interface/gr-auth_test.html',
- 'shared/gr-rest-api-interface/gr-etag-decorator_test.html',
- 'shared/gr-rest-api-interface/gr-rest-api-interface_test.html',
- 'shared/gr-rest-api-interface/gr-reviewer-updates-parser_test.html',
- 'shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper_test.html',
- 'shared/gr-select/gr-select_test.html',
- 'shared/gr-shell-command/gr-shell-command_test.html',
- 'shared/gr-storage/gr-storage_test.html',
- 'shared/gr-textarea/gr-textarea_test.html',
- 'shared/gr-tooltip-content/gr-tooltip-content_test.html',
- 'shared/gr-tooltip/gr-tooltip_test.html',
- 'shared/revision-info/revision-info_test.html',
-];
-/* eslint-enable max-len */
-for (let file of elements) {
- file = elementsPath + file;
- testFiles.push(file);
-}
-
-// Behaviors tests.
-/* eslint-disable max-len */
-const behaviors = [
- 'base-url-behavior/base-url-behavior_test.html',
- 'docs-url-behavior/docs-url-behavior_test.html',
- 'dom-util-behavior/dom-util-behavior_test.html',
- 'keyboard-shortcut-behavior/keyboard-shortcut-behavior_test.html',
- 'rest-client-behavior/rest-client-behavior_test.html',
- 'gr-access-behavior/gr-access-behavior_test.html',
- 'gr-admin-nav-behavior/gr-admin-nav-behavior_test.html',
- 'gr-change-table-behavior/gr-change-table-behavior_test.html',
- 'gr-list-view-behavior/gr-list-view-behavior_test.html',
- 'gr-display-name-behavior/gr-display-name-behavior_test.html',
- 'gr-patch-set-behavior/gr-patch-set-behavior_test.html',
- 'gr-path-list-behavior/gr-path-list-behavior_test.html',
- 'gr-tooltip-behavior/gr-tooltip-behavior_test.html',
- 'gr-url-encoding-behavior/gr-url-encoding-behavior_test.html',
- 'safe-types-behavior/safe-types-behavior_test.html',
-];
-/* eslint-enable max-len */
-for (let file of behaviors) {
- // Behaviors do not utilize the DOM, so no shadow DOM test is necessary.
- file = behaviorsPath + file;
- testFiles.push(file);
-}
-
-const scripts = [
- 'gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider_test.html',
- 'gr-group-suggestions-provider/gr-group-suggestions-provider_test.html',
- 'gr-display-name-utils/gr-display-name-utils_test.html',
- 'gr-email-suggestions-provider/gr-email-suggestions-provider_test.html',
-];
-/* eslint-enable max-len */
-for (let file of scripts) {
- file = scriptsPath + file;
- testFiles.push(file);
-}
-
-const services = [
- 'app-context-init_test.html',
- 'flags_test.html',
- 'gr-reporting/gr-reporting_test.html',
- 'gr-reporting/gr-reporting_mock_test.html',
- 'gr-event-interface/gr-event-interface_test.html',
-];
-for (let file of services) {
- file = servicesPath + file;
- testFiles.push(file);
-}
-
-// embed test
-testFiles.push('../embed/gr-diff-app-context-init_test.html');
-
-/**
- * Converts multiline string to a map<file_name, test_count>.
- *
- * @param {number} testsPerFileString - multiline input string in the following format:
- * fileName1:test_count1
- * fileName2:test_count2
- * ...
- * fileName3:test_count3
- * @return Object<string, number> - key is the test file name, value is the number of tests
- */
-function parseTestsPerFileString(testsPerFileString) {
- return testsPerFileString.split('\n').map(s => s.trim().replace('./', '../'))
- .reduce((acc, fileAndCount) => {
- const [file, countStr] = fileAndCount.split(':');
- acc[file] = parseInt(countStr);
- return acc;
- }, {});
-}
-
-const defaultTestsPerFile = [];
-
-function getBucketWithMinTests(buckets) {
- let minBucket = buckets[0];
- for (let i = 1; i < buckets.length; i++) {
- if (buckets[i].count < minBucket.count) {
- minBucket = buckets[i];
- }
- }
- return minBucket;
-}
-
-/**
- * Split testFiles among all buckets. The greedy algorithm is used,
- * because we don't need accurate splitting
- */
-function splitTestsByBuckets(buckets, testsPerFile) {
- for (const testFile of testFiles) {
- const testsInFile = testsPerFile[testFile] ?
- testsPerFile[testFile] : defaultTestsPerFile;
- const minBucket = getBucketWithMinTests(buckets);
- minBucket.count += testsInFile;
- minBucket.items.push(testFile);
- }
-}
-
-/**
- * Returns list of test files for specified splitIndex
- *
- * @param {string} testsPerFileString - information about number of tests in each file
- * (see suite_conf.js for exact format)
- * @param {number} splitIndex - index of split to return (0<=splitIndex<splitCount)
- * @param {number} splitCount - total number of splits
- * @return Array<string> - list of test files
- */
-export function getSuiteTests(testsPerFileString, splitIndex, splitCount) {
- const testsPerFile = parseTestsPerFileString(testsPerFileString);
- const buckets = [];
- for (let i = 0; i < splitCount; i++) {
- buckets.push({count: 0, items: []});
- }
- // TODO(dmfilippov): split tests by buckets only once
- // This doesn't affect overall performance, so we can keep it
- // while we have only small amounts of test files.
- splitTestsByBuckets(buckets, testsPerFile);
- console.log(buckets);
- return buckets[splitIndex].items;
-}
-
diff --git a/polygerrit-ui/app/wct.conf.js b/polygerrit-ui/app/wct.conf.js
deleted file mode 100644
index 1a9300e..0000000
--- a/polygerrit-ui/app/wct.conf.js
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- * @license
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
-For some reason wct tries to install selenium into its node_modules
-directory on first run. If you've installed into /usr/local and
-aren't running wct as root, you're screwed. Turning this option off
-through skipSeleniumInstall seems to still work, so there's that.
-
-Sauce tests are disabled by default in order to run local tests
-only. Run it with (saucelabs.com account required; free for open
-source): ./polygerrit-ui/app/run_test.sh --test_arg=--plugin --test_arg=sauce
-*/
-
-const headless = 'WCT_HEADLESS_MODE' in process.env ?
- process.env['WCT_HEADLESS_MODE'] === '1' : false;
-
-const headlessBrowserOptions = {
- chrome: ['start-maximized', 'headless', 'disable-gpu', 'no-sandbox'],
- firefox: ['-headless'],
-};
-
-const defaultBrowserOptions = {
- chrome: ['start-maximized'],
- firefox: [],
-};
-
-module.exports = {
- suites: ['test'],
- npm: true,
- moduleResolution: 'node',
- wctPackageName: 'wct-browser-legacy',
- plugins: {
- local: {
- skipSeleniumInstall: true,
- browserOptions: headless ? headlessBrowserOptions : defaultBrowserOptions,
- },
- sauce: {
- disabled: true,
- browsers: [
- 'OS X 10.12/chrome',
- 'Windows 10/chrome',
- 'Linux/firefox',
- 'OS X 10.12/safari',
- 'Windows 10/microsoftedge',
- ],
- },
- },
-};
diff --git a/polygerrit-ui/app/wct_test.sh b/polygerrit-ui/app/wct_test.sh
deleted file mode 100755
index 829a507..0000000
--- a/polygerrit-ui/app/wct_test.sh
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/bin/sh
-
-set -ex
-root_dir=$(pwd)
-t=$TEST_TMPDIR
-export JSON_CONFIG=$2
-
-mkdir -p $t/node_modules
-# WCT doesn't implement node module resolution.
-# WCT uses only node_module/ directory from current directory when looking for a module
-# So, it is impossible to make hierarchical node_modules. Instead, we copy
-# all node_modules to one directory.
-cp -R -L ./external/ui_dev_npm/node_modules/* $t/node_modules
-
-# Copy ui_npm, so it will override ui_dev_npm modules (in case of conflicts)
-# Because browser always requests specific exact files (i.e. not a directory),
-# it always receives file from ui_npm. It can broke WCT itself but luckily it works.
-cp -R -L ./external/ui_npm/node_modules/* $t/node_modules
-
-cp -R -L ./polygerrit-ui/app/* $t/
-
-export PATH="$(dirname $NPM):$PATH"
-
-cd $t
-echo "export const config=$JSON_CONFIG;" > ./test/suite_conf.js
-echo "export const testsPerFileString=\`" >> ./test/suite_conf.js
-# Count number of tests in each file.
-# We don't need accurate data, use simplest method
-# TODO(dmfilippov): collect data only once
-# In the current implementation, the same data is collected for each split,
-# It takes less than a second which many times less than the overall wct test time
-grep -rnw '.' --include=\*_test.html -e "test(" -c >> ./test/suite_conf.js
-echo "\`;" >>./test/suite_conf.js
-
-# If wct doesn't receive any parameters, it fails (can't find files)
-# Pass --config-file as a parameter to have some arguments in command line
-$root_dir/$1 --config-file wct.conf.js ${WCT_ARGS}
diff --git a/polygerrit-ui/package.json b/polygerrit-ui/package.json
index 527763b..ea039d5 100644
--- a/polygerrit-ui/package.json
+++ b/polygerrit-ui/package.json
@@ -15,11 +15,7 @@
"karma-mocha-reporter": "^2.2.5",
"lodash": "^4.17.15",
"mocha": "^7.1.1",
- "wct-browser-legacy": "^1.0.2",
- "web-component-tester": "^6.9.2"
- },
- "scripts": {
- "postinstall": "selenium-standalone install"
+ "sinon": "^9.0.2"
},
"license": "Apache-2.0",
"private": true
diff --git a/polygerrit-ui/yarn.lock b/polygerrit-ui/yarn.lock
index 5ad28b6..d73e1d0 100644
--- a/polygerrit-ui/yarn.lock
+++ b/polygerrit-ui/yarn.lock
@@ -18,27 +18,6 @@
invariant "^2.2.4"
semver "^5.5.0"
-"@babel/core@^7.0.0":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.3.tgz#30b0ebb4dd1585de6923a0b4d179e0b9f5d82941"
- integrity sha512-4XFkf8AwyrEG7Ziu3L2L0Cv+WyY47Tcsp70JFmpftbAA1K7YL/sgE9jh9HyNj08Y/U50ItUchpN0w6HxAoX1rA==
- dependencies:
- "@babel/code-frame" "^7.8.3"
- "@babel/generator" "^7.8.3"
- "@babel/helpers" "^7.8.3"
- "@babel/parser" "^7.8.3"
- "@babel/template" "^7.8.3"
- "@babel/traverse" "^7.8.3"
- "@babel/types" "^7.8.3"
- convert-source-map "^1.7.0"
- debug "^4.1.0"
- gensync "^1.0.0-beta.1"
- json5 "^2.1.0"
- lodash "^4.17.13"
- resolve "^1.3.2"
- semver "^5.4.1"
- source-map "^0.5.0"
-
"@babel/core@^7.9.0":
version "7.9.0"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.0.tgz#ac977b538b77e132ff706f3b8a4dbad09c03c56e"
@@ -61,16 +40,6 @@
semver "^5.4.1"
source-map "^0.5.0"
-"@babel/generator@^7.0.0-beta.42", "@babel/generator@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.3.tgz#0e22c005b0a94c1c74eafe19ef78ce53a4d45c03"
- integrity sha512-WjoPk8hRpDRqqzRpvaR8/gDUPkrnOOeuT2m8cNICJtZH6mwaCo3v0OKMI7Y6SM1pBtyijnLtAL0HDi41pf41ug==
- dependencies:
- "@babel/types" "^7.8.3"
- jsesc "^2.5.1"
- lodash "^4.17.13"
- source-map "^0.5.0"
-
"@babel/generator@^7.4.0", "@babel/generator@^7.9.0":
version "7.9.4"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.4.tgz#12441e90c3b3c4159cdecf312075bf1a8ce2dbce"
@@ -81,6 +50,16 @@
lodash "^4.17.13"
source-map "^0.5.0"
+"@babel/generator@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.3.tgz#0e22c005b0a94c1c74eafe19ef78ce53a4d45c03"
+ integrity sha512-WjoPk8hRpDRqqzRpvaR8/gDUPkrnOOeuT2m8cNICJtZH6mwaCo3v0OKMI7Y6SM1pBtyijnLtAL0HDi41pf41ug==
+ dependencies:
+ "@babel/types" "^7.8.3"
+ jsesc "^2.5.1"
+ lodash "^4.17.13"
+ source-map "^0.5.0"
+
"@babel/helper-annotate-as-pure@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz#60bc0bc657f63a0924ff9a4b4a0b24a13cf4deee"
@@ -96,15 +75,6 @@
"@babel/helper-explode-assignable-expression" "^7.8.3"
"@babel/types" "^7.8.3"
-"@babel/helper-call-delegate@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.8.3.tgz#de82619898aa605d409c42be6ffb8d7204579692"
- integrity sha512-6Q05px0Eb+N4/GTyKPPvnkig7Lylw+QzihMpws9iiZQv7ZImf84ZsZpQH7QoWN4n4tm81SnSzPgHw2qtO0Zf3A==
- dependencies:
- "@babel/helper-hoist-variables" "^7.8.3"
- "@babel/traverse" "^7.8.3"
- "@babel/types" "^7.8.3"
-
"@babel/helper-compilation-targets@^7.8.7":
version "7.8.7"
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.7.tgz#dac1eea159c0e4bd46e309b5a1b04a66b53c1dde"
@@ -187,18 +157,6 @@
dependencies:
"@babel/types" "^7.8.3"
-"@babel/helper-module-transforms@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.8.3.tgz#d305e35d02bee720fbc2c3c3623aa0c316c01590"
- integrity sha512-C7NG6B7vfBa/pwCOshpMbOYUmrYQDfCpVL/JCRu0ek8B5p8kue1+BCXpg2vOYs7w5ACB9GTOBYQ5U6NwrMg+3Q==
- dependencies:
- "@babel/helper-module-imports" "^7.8.3"
- "@babel/helper-simple-access" "^7.8.3"
- "@babel/helper-split-export-declaration" "^7.8.3"
- "@babel/template" "^7.8.3"
- "@babel/types" "^7.8.3"
- lodash "^4.17.13"
-
"@babel/helper-module-transforms@^7.9.0":
version "7.9.0"
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz#43b34dfe15961918707d247327431388e9fe96e5"
@@ -292,15 +250,6 @@
"@babel/traverse" "^7.8.3"
"@babel/types" "^7.8.3"
-"@babel/helpers@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.8.3.tgz#382fbb0382ce7c4ce905945ab9641d688336ce85"
- integrity sha512-LmU3q9Pah/XyZU89QvBgGt+BCsTPoQa+73RxAQh8fb8qkDyIfeQnmgs+hvzhTCKTzqOyk7JTkS3MS1S8Mq5yrQ==
- dependencies:
- "@babel/template" "^7.8.3"
- "@babel/traverse" "^7.8.3"
- "@babel/types" "^7.8.3"
-
"@babel/helpers@^7.9.0":
version "7.9.2"
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.9.2.tgz#b42a81a811f1e7313b88cba8adc66b3d9ae6c09f"
@@ -329,14 +278,7 @@
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.3.tgz#790874091d2001c9be6ec426c2eed47bc7679081"
integrity sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==
-"@babel/plugin-external-helpers@^7.0.0":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-external-helpers/-/plugin-external-helpers-7.8.3.tgz#5a94164d9af393b2820a3cdc407e28ebf237de4b"
- integrity sha512-mx0WXDDiIl5DwzMtzWGRSPugXi9BxROS05GQrhLNbEamhBiicgn994ibwkyiBH+6png7bm/yA7AUsvHyCXi4Vw==
- dependencies:
- "@babel/helper-plugin-utils" "^7.8.3"
-
-"@babel/plugin-proposal-async-generator-functions@^7.0.0", "@babel/plugin-proposal-async-generator-functions@^7.8.3":
+"@babel/plugin-proposal-async-generator-functions@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz#bad329c670b382589721b27540c7d288601c6e6f"
integrity sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw==
@@ -377,14 +319,6 @@
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-syntax-numeric-separator" "^7.8.3"
-"@babel/plugin-proposal-object-rest-spread@^7.0.0":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.8.3.tgz#eb5ae366118ddca67bed583b53d7554cad9951bb"
- integrity sha512-8qvuPwU/xxUCt78HocNlv0mXXo0wdh9VT1R04WU8HGOfaOob26pF+9P5/lYjN/q7DHOX1bvX60hnhOvuQUJdbA==
- dependencies:
- "@babel/helper-plugin-utils" "^7.8.3"
- "@babel/plugin-syntax-object-rest-spread" "^7.8.0"
-
"@babel/plugin-proposal-object-rest-spread@^7.9.0":
version "7.9.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.0.tgz#a28993699fc13df165995362693962ba6b061d6f"
@@ -417,7 +351,7 @@
"@babel/helper-create-regexp-features-plugin" "^7.8.8"
"@babel/helper-plugin-utils" "^7.8.3"
-"@babel/plugin-syntax-async-generators@^7.0.0", "@babel/plugin-syntax-async-generators@^7.8.0":
+"@babel/plugin-syntax-async-generators@^7.8.0":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d"
integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==
@@ -431,14 +365,14 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
-"@babel/plugin-syntax-dynamic-import@^7.0.0", "@babel/plugin-syntax-dynamic-import@^7.8.0", "@babel/plugin-syntax-dynamic-import@^7.8.3":
+"@babel/plugin-syntax-dynamic-import@^7.8.0", "@babel/plugin-syntax-dynamic-import@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3"
integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==
dependencies:
"@babel/helper-plugin-utils" "^7.8.0"
-"@babel/plugin-syntax-import-meta@^7.0.0", "@babel/plugin-syntax-import-meta@^7.8.3":
+"@babel/plugin-syntax-import-meta@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.8.3.tgz#230afff79d3ccc215b5944b438e4e266daf3d84d"
integrity sha512-vYiGd4wQ9gx0Lngb7+bPCwQXGK/PR6FeTIJ+TIOlq+OfOKG/kCAOO2+IBac3oMM9qV7/fU76hfcqxUaLKZf1hQ==
@@ -466,7 +400,7 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
-"@babel/plugin-syntax-object-rest-spread@^7.0.0", "@babel/plugin-syntax-object-rest-spread@^7.8.0":
+"@babel/plugin-syntax-object-rest-spread@^7.8.0":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871"
integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==
@@ -494,14 +428,14 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
-"@babel/plugin-transform-arrow-functions@^7.0.0", "@babel/plugin-transform-arrow-functions@^7.8.3":
+"@babel/plugin-transform-arrow-functions@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz#82776c2ed0cd9e1a49956daeb896024c9473b8b6"
integrity sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg==
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
-"@babel/plugin-transform-async-to-generator@^7.0.0", "@babel/plugin-transform-async-to-generator@^7.8.3":
+"@babel/plugin-transform-async-to-generator@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz#4308fad0d9409d71eafb9b1a6ee35f9d64b64086"
integrity sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ==
@@ -510,14 +444,14 @@
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/helper-remap-async-to-generator" "^7.8.3"
-"@babel/plugin-transform-block-scoped-functions@^7.0.0", "@babel/plugin-transform-block-scoped-functions@^7.8.3":
+"@babel/plugin-transform-block-scoped-functions@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz#437eec5b799b5852072084b3ae5ef66e8349e8a3"
integrity sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg==
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
-"@babel/plugin-transform-block-scoping@^7.0.0", "@babel/plugin-transform-block-scoping@^7.8.3":
+"@babel/plugin-transform-block-scoping@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz#97d35dab66857a437c166358b91d09050c868f3a"
integrity sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w==
@@ -525,20 +459,6 @@
"@babel/helper-plugin-utils" "^7.8.3"
lodash "^4.17.13"
-"@babel/plugin-transform-classes@^7.0.0":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.8.3.tgz#46fd7a9d2bb9ea89ce88720477979fe0d71b21b8"
- integrity sha512-SjT0cwFJ+7Rbr1vQsvphAHwUHvSUPmMjMU/0P59G8U2HLFqSa082JO7zkbDNWs9kH/IUqpHI6xWNesGf8haF1w==
- dependencies:
- "@babel/helper-annotate-as-pure" "^7.8.3"
- "@babel/helper-define-map" "^7.8.3"
- "@babel/helper-function-name" "^7.8.3"
- "@babel/helper-optimise-call-expression" "^7.8.3"
- "@babel/helper-plugin-utils" "^7.8.3"
- "@babel/helper-replace-supers" "^7.8.3"
- "@babel/helper-split-export-declaration" "^7.8.3"
- globals "^11.1.0"
-
"@babel/plugin-transform-classes@^7.9.0":
version "7.9.2"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.9.2.tgz#8603fc3cc449e31fdbdbc257f67717536a11af8d"
@@ -553,20 +473,13 @@
"@babel/helper-split-export-declaration" "^7.8.3"
globals "^11.1.0"
-"@babel/plugin-transform-computed-properties@^7.0.0", "@babel/plugin-transform-computed-properties@^7.8.3":
+"@babel/plugin-transform-computed-properties@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz#96d0d28b7f7ce4eb5b120bb2e0e943343c86f81b"
integrity sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA==
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
-"@babel/plugin-transform-destructuring@^7.0.0":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.8.3.tgz#20ddfbd9e4676906b1056ee60af88590cc7aaa0b"
- integrity sha512-H4X646nCkiEcHZUZaRkhE2XVsoz0J/1x3VVujnn96pSoGCtKPA99ZZA+va+gK+92Zycd6OBKCD8tDb/731bhgQ==
- dependencies:
- "@babel/helper-plugin-utils" "^7.8.3"
-
"@babel/plugin-transform-destructuring@^7.8.3":
version "7.8.8"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.8.8.tgz#fadb2bc8e90ccaf5658de6f8d4d22ff6272a2f4b"
@@ -582,14 +495,14 @@
"@babel/helper-create-regexp-features-plugin" "^7.8.3"
"@babel/helper-plugin-utils" "^7.8.3"
-"@babel/plugin-transform-duplicate-keys@^7.0.0", "@babel/plugin-transform-duplicate-keys@^7.8.3":
+"@babel/plugin-transform-duplicate-keys@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.8.3.tgz#8d12df309aa537f272899c565ea1768e286e21f1"
integrity sha512-s8dHiBUbcbSgipS4SMFuWGqCvyge5V2ZeAWzR6INTVC3Ltjig/Vw1G2Gztv0vU/hRG9X8IvKvYdoksnUfgXOEQ==
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
-"@babel/plugin-transform-exponentiation-operator@^7.0.0", "@babel/plugin-transform-exponentiation-operator@^7.8.3":
+"@babel/plugin-transform-exponentiation-operator@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz#581a6d7f56970e06bf51560cd64f5e947b70d7b7"
integrity sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ==
@@ -597,13 +510,6 @@
"@babel/helper-builder-binary-assignment-operator-visitor" "^7.8.3"
"@babel/helper-plugin-utils" "^7.8.3"
-"@babel/plugin-transform-for-of@^7.0.0":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.8.3.tgz#15f17bce2fc95c7d59a24b299e83e81cedc22e18"
- integrity sha512-ZjXznLNTxhpf4Q5q3x1NsngzGA38t9naWH8Gt+0qYZEJAcvPI9waSStSh56u19Ofjr7QmD0wUsQ8hw8s/p1VnA==
- dependencies:
- "@babel/helper-plugin-utils" "^7.8.3"
-
"@babel/plugin-transform-for-of@^7.9.0":
version "7.9.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.9.0.tgz#0f260e27d3e29cd1bb3128da5e76c761aa6c108e"
@@ -611,7 +517,7 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
-"@babel/plugin-transform-function-name@^7.0.0", "@babel/plugin-transform-function-name@^7.8.3":
+"@babel/plugin-transform-function-name@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz#279373cb27322aaad67c2683e776dfc47196ed8b"
integrity sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ==
@@ -619,14 +525,7 @@
"@babel/helper-function-name" "^7.8.3"
"@babel/helper-plugin-utils" "^7.8.3"
-"@babel/plugin-transform-instanceof@^7.0.0":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-instanceof/-/plugin-transform-instanceof-7.8.3.tgz#a44d7d71590da36be7429573300618aefd784c3d"
- integrity sha512-c/jB6Ebe2u17hxo+rce6PDgbkuHyfcJOleqgHYttnvMrCsxVwUnYsMq7GhxXekzUQsv9IImhv6YICKihpen+Ag==
- dependencies:
- "@babel/helper-plugin-utils" "^7.8.3"
-
-"@babel/plugin-transform-literals@^7.0.0", "@babel/plugin-transform-literals@^7.8.3":
+"@babel/plugin-transform-literals@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz#aef239823d91994ec7b68e55193525d76dbd5dc1"
integrity sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A==
@@ -640,15 +539,6 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
-"@babel/plugin-transform-modules-amd@^7.0.0":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.8.3.tgz#65606d44616b50225e76f5578f33c568a0b876a5"
- integrity sha512-MadJiU3rLKclzT5kBH4yxdry96odTUwuqrZM+GllFI/VhxfPz+k9MshJM+MwhfkCdxxclSbSBbUGciBngR+kEQ==
- dependencies:
- "@babel/helper-module-transforms" "^7.8.3"
- "@babel/helper-plugin-utils" "^7.8.3"
- babel-plugin-dynamic-import-node "^2.3.0"
-
"@babel/plugin-transform-modules-amd@^7.9.0":
version "7.9.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.0.tgz#19755ee721912cf5bb04c07d50280af3484efef4"
@@ -700,7 +590,7 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
-"@babel/plugin-transform-object-super@^7.0.0", "@babel/plugin-transform-object-super@^7.8.3":
+"@babel/plugin-transform-object-super@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz#ebb6a1e7a86ffa96858bd6ac0102d65944261725"
integrity sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ==
@@ -708,15 +598,6 @@
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/helper-replace-supers" "^7.8.3"
-"@babel/plugin-transform-parameters@^7.0.0":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.8.3.tgz#7890576a13b17325d8b7d44cb37f21dc3bbdda59"
- integrity sha512-/pqngtGb54JwMBZ6S/D3XYylQDFtGjWrnoCF4gXZOUpFV/ujbxnoNGNvDGu6doFWRPBveE72qTx/RRU44j5I/Q==
- dependencies:
- "@babel/helper-call-delegate" "^7.8.3"
- "@babel/helper-get-function-arity" "^7.8.3"
- "@babel/helper-plugin-utils" "^7.8.3"
-
"@babel/plugin-transform-parameters@^7.8.7":
version "7.9.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.9.3.tgz#3028d0cc20ddc733166c6e9c8534559cee09f54a"
@@ -732,13 +613,6 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
-"@babel/plugin-transform-regenerator@^7.0.0":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.3.tgz#b31031e8059c07495bf23614c97f3d9698bc6ec8"
- integrity sha512-qt/kcur/FxrQrzFR432FGZznkVAjiyFtCOANjkAKwCbt465L6ZCiUQh2oMYGU3Wo8LRFJxNDFwWn106S5wVUNA==
- dependencies:
- regenerator-transform "^0.14.0"
-
"@babel/plugin-transform-regenerator@^7.8.7":
version "7.8.7"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.7.tgz#5e46a0dca2bee1ad8285eb0527e6abc9c37672f8"
@@ -753,21 +627,21 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
-"@babel/plugin-transform-shorthand-properties@^7.0.0", "@babel/plugin-transform-shorthand-properties@^7.8.3":
+"@babel/plugin-transform-shorthand-properties@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz#28545216e023a832d4d3a1185ed492bcfeac08c8"
integrity sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w==
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
-"@babel/plugin-transform-spread@^7.0.0", "@babel/plugin-transform-spread@^7.8.3":
+"@babel/plugin-transform-spread@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz#9c8ffe8170fdfb88b114ecb920b82fb6e95fe5e8"
integrity sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g==
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
-"@babel/plugin-transform-sticky-regex@^7.0.0", "@babel/plugin-transform-sticky-regex@^7.8.3":
+"@babel/plugin-transform-sticky-regex@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz#be7a1290f81dae767475452199e1f76d6175b100"
integrity sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw==
@@ -775,7 +649,7 @@
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/helper-regex" "^7.8.3"
-"@babel/plugin-transform-template-literals@^7.0.0", "@babel/plugin-transform-template-literals@^7.8.3":
+"@babel/plugin-transform-template-literals@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz#7bfa4732b455ea6a43130adc0ba767ec0e402a80"
integrity sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ==
@@ -783,13 +657,6 @@
"@babel/helper-annotate-as-pure" "^7.8.3"
"@babel/helper-plugin-utils" "^7.8.3"
-"@babel/plugin-transform-typeof-symbol@^7.0.0":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.3.tgz#5cffb216fb25c8c64ba6bf5f76ce49d3ab079f4d"
- integrity sha512-3TrkKd4LPqm4jHs6nPtSDI/SV9Cm5PRJkHLUgTcqRQQTMAZ44ZaAdDZJtvWFSaRcvT0a1rTmJ5ZA5tDKjleF3g==
- dependencies:
- "@babel/helper-plugin-utils" "^7.8.3"
-
"@babel/plugin-transform-typeof-symbol@^7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz#ede4062315ce0aaf8a657a920858f1a2f35fc412"
@@ -797,7 +664,7 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
-"@babel/plugin-transform-unicode-regex@^7.0.0", "@babel/plugin-transform-unicode-regex@^7.8.3":
+"@babel/plugin-transform-unicode-regex@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz#0cef36e3ba73e5c57273effb182f46b91a1ecaad"
integrity sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw==
@@ -907,21 +774,6 @@
"@babel/parser" "^7.8.3"
"@babel/types" "^7.8.3"
-"@babel/traverse@^7.0.0", "@babel/traverse@^7.0.0-beta.42", "@babel/traverse@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.3.tgz#a826215b011c9b4f73f3a893afbc05151358bf9a"
- integrity sha512-we+a2lti+eEImHmEXp7bM9cTxGzxPmBiVJlLVD+FuuQMeeO7RaDbutbgeheDkw+Xe3mCfJHnGOWLswT74m2IPg==
- dependencies:
- "@babel/code-frame" "^7.8.3"
- "@babel/generator" "^7.8.3"
- "@babel/helper-function-name" "^7.8.3"
- "@babel/helper-split-export-declaration" "^7.8.3"
- "@babel/parser" "^7.8.3"
- "@babel/types" "^7.8.3"
- debug "^4.1.0"
- globals "^11.1.0"
- lodash "^4.17.13"
-
"@babel/traverse@^7.4.3", "@babel/traverse@^7.8.6", "@babel/traverse@^7.9.0":
version "7.9.0"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.0.tgz#d3882c2830e513f4fe4cec9fe76ea1cc78747892"
@@ -937,14 +789,20 @@
globals "^11.1.0"
lodash "^4.17.13"
-"@babel/types@^7.0.0-beta.42", "@babel/types@^7.8.3":
+"@babel/traverse@^7.8.3":
version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.3.tgz#5a383dffa5416db1b73dedffd311ffd0788fb31c"
- integrity sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.3.tgz#a826215b011c9b4f73f3a893afbc05151358bf9a"
+ integrity sha512-we+a2lti+eEImHmEXp7bM9cTxGzxPmBiVJlLVD+FuuQMeeO7RaDbutbgeheDkw+Xe3mCfJHnGOWLswT74m2IPg==
dependencies:
- esutils "^2.0.2"
+ "@babel/code-frame" "^7.8.3"
+ "@babel/generator" "^7.8.3"
+ "@babel/helper-function-name" "^7.8.3"
+ "@babel/helper-split-export-declaration" "^7.8.3"
+ "@babel/parser" "^7.8.3"
+ "@babel/types" "^7.8.3"
+ debug "^4.1.0"
+ globals "^11.1.0"
lodash "^4.17.13"
- to-fast-properties "^2.0.0"
"@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.8.6", "@babel/types@^7.9.0":
version "7.9.0"
@@ -955,6 +813,15 @@
lodash "^4.17.13"
to-fast-properties "^2.0.0"
+"@babel/types@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.3.tgz#5a383dffa5416db1b73dedffd311ffd0788fb31c"
+ integrity sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==
+ dependencies:
+ esutils "^2.0.2"
+ lodash "^4.17.13"
+ to-fast-properties "^2.0.0"
+
"@open-wc/building-utils@^2.16.1":
version "2.16.1"
resolved "https://registry.yarnpkg.com/@open-wc/building-utils/-/building-utils-2.16.1.tgz#093d74881b996fe9497d628cdf55b6757422d894"
@@ -1002,11 +869,6 @@
portfinder "^1.0.21"
request "^2.88.0"
-"@polymer/esm-amd-loader@^1.0.0":
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/@polymer/esm-amd-loader/-/esm-amd-loader-1.0.4.tgz#4e77f2f59b29b01e0ad02aa83d33716cddc5f9f9"
- integrity sha512-h+hqYkL+tQV/y2ESD5gFXMl5z4cC+XY1jTlBeGSBaTcj3VbB5OBEScbvRXm63NcEbBneQQYbHfBAXAkF9i9wIA==
-
"@polymer/iron-test-helpers@^3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@polymer/iron-test-helpers/-/iron-test-helpers-3.0.1.tgz#ec2b9c6567e2967a191b3d800a04b1167b2d1394"
@@ -1021,21 +883,6 @@
dependencies:
"@webcomponents/shadycss" "^1.9.1"
-"@polymer/sinonjs@^1.14.1":
- version "1.17.1"
- resolved "https://registry.yarnpkg.com/@polymer/sinonjs/-/sinonjs-1.17.1.tgz#e47d3785b7d0e8c29feb97f7e924b0fc597e2e9b"
- integrity sha512-/U8F/cOTrbF2iVVYgINYmvKbtbexs+89Q3v8AaHADRYabTg7aOZGOb0RyWpOI+sUJt04kj63U4FwMhzW5r4wZA==
-
-"@polymer/test-fixture@^0.0.3":
- version "0.0.3"
- resolved "https://registry.yarnpkg.com/@polymer/test-fixture/-/test-fixture-0.0.3.tgz#4443752697d4d9293bbc412ea0b5e4d341f149d9"
- integrity sha1-REN1JpfU2Sk7vEEuoLXk00HxSdk=
-
-"@polymer/test-fixture@^3.0.0-pre.1":
- version "3.0.0-pre.21"
- resolved "https://registry.yarnpkg.com/@polymer/test-fixture/-/test-fixture-3.0.0-pre.21.tgz#85152207cb0bf57caebc191c80bb0fdb6952614e"
- integrity sha512-IxzUe6YzaORzUksafHAXHprV29YncOJgr0+1zNAifl0/f+cb5iAd4IWUrnsnVFHG5UGTLjvis5RgV6vvIZPDrA==
-
"@polymer/test-fixture@^4.0.2":
version "4.0.2"
resolved "https://registry.yarnpkg.com/@polymer/test-fixture/-/test-fixture-4.0.2.tgz#2f4777ecdcfb22ee000db35a05e0edf27c722c19"
@@ -1059,279 +906,52 @@
dependencies:
estree-walker "^1.0.1"
-"@types/babel-generator@^6.25.1":
- version "6.25.3"
- resolved "https://registry.yarnpkg.com/@types/babel-generator/-/babel-generator-6.25.3.tgz#8f06caa12d0595a0538560abe771966d77d29286"
- integrity sha512-pGgnuxVddKcYIc+VJkRDop7gxLhqclNKBdlsm/5Vp8d+37pQkkDK7fef8d9YYImRzw9xcojEPc18pUYnbxmjqA==
+"@sinonjs/commons@^1", "@sinonjs/commons@^1.6.0", "@sinonjs/commons@^1.7.0", "@sinonjs/commons@^1.7.2":
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.0.tgz#c8d68821a854c555bba172f3b06959a0039b236d"
+ integrity sha512-wEj54PfsZ5jGSwMX68G8ZXFawcSglQSXqCftWX3ec8MDUzQdHgcKvw97awHbY0efQEL5iKUOAmmVtoYgmrSG4Q==
dependencies:
- "@types/babel-types" "*"
+ type-detect "4.0.8"
-"@types/babel-traverse@^6.25.2", "@types/babel-traverse@^6.25.3":
- version "6.25.5"
- resolved "https://registry.yarnpkg.com/@types/babel-traverse/-/babel-traverse-6.25.5.tgz#6d293cf7523e48b524faa7b86dc3c488191484e5"
- integrity sha512-WrMbwmu+MWf8FiUMbmVOGkc7bHPzndUafn1CivMaBHthBBoo0VNIcYk1KV71UovYguhsNOwf3UF5oRmkkGOU3w==
+"@sinonjs/fake-timers@^6.0.0", "@sinonjs/fake-timers@^6.0.1":
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz#293674fccb3262ac782c7aadfdeca86b10c75c40"
+ integrity sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==
dependencies:
- "@types/babel-types" "*"
+ "@sinonjs/commons" "^1.7.0"
-"@types/babel-types@*":
- version "7.0.7"
- resolved "https://registry.yarnpkg.com/@types/babel-types/-/babel-types-7.0.7.tgz#667eb1640e8039436028055737d2b9986ee336e3"
- integrity sha512-dBtBbrc+qTHy1WdfHYjBwRln4+LWqASWakLHsWHR2NWHIFkv4W3O070IGoGLEBrJBvct3r0L1BUPuvURi7kYUQ==
-
-"@types/babel-types@^6.25.1":
- version "6.25.2"
- resolved "https://registry.yarnpkg.com/@types/babel-types/-/babel-types-6.25.2.tgz#5c57f45973e4f13742dbc5273dd84cffe7373a9e"
- integrity sha512-+3bMuktcY4a70a0KZc8aPJlEOArPuAKQYHU5ErjkOqGJdx8xuEEVK6nWogqigBOJ8nKPxRpyCUDTCPmZ3bUxGA==
-
-"@types/babylon@^6.16.2":
- version "6.16.5"
- resolved "https://registry.yarnpkg.com/@types/babylon/-/babylon-6.16.5.tgz#1c5641db69eb8cdf378edd25b4be7754beeb48b4"
- integrity sha512-xH2e58elpj1X4ynnKp9qSnWlsRTIs6n3tgLGNfwAGHwePw0mulHQllV34n0T25uYSu1k0hRKkWXF890B1yS47w==
+"@sinonjs/formatio@^5.0.1":
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-5.0.1.tgz#f13e713cb3313b1ab965901b01b0828ea6b77089"
+ integrity sha512-KaiQ5pBf1MpS09MuA0kp6KBQt2JUOQycqVG1NZXvzeaXe5LGFqAKueIS0bw4w0P9r7KuBSVdUk5QjXsUdu2CxQ==
dependencies:
- "@types/babel-types" "*"
+ "@sinonjs/commons" "^1"
+ "@sinonjs/samsam" "^5.0.2"
-"@types/bluebird@*":
- version "3.5.29"
- resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.29.tgz#7cd933c902c4fc83046517a1bef973886d00bdb6"
- integrity sha512-kmVtnxTuUuhCET669irqQmPAez4KFnFVKvpleVRyfC3g+SHD1hIkFZcWLim9BVcwUBLO59o8VZE4yGCmTif8Yw==
-
-"@types/body-parser@*":
- version "1.17.1"
- resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.17.1.tgz#18fcf61768fb5c30ccc508c21d6fd2e8b3bf7897"
- integrity sha512-RoX2EZjMiFMjZh9lmYrwgoP9RTpAjSHiJxdp4oidAQVO02T7HER3xj9UKue5534ULWeqVEkujhWcyvUce+d68w==
+"@sinonjs/samsam@^5.0.2", "@sinonjs/samsam@^5.0.3":
+ version "5.0.3"
+ resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-5.0.3.tgz#86f21bdb3d52480faf0892a480c9906aa5a52938"
+ integrity sha512-QucHkc2uMJ0pFGjJUDP3F9dq5dx8QIaqISl9QgwLOh6P9yv877uONPGXh/OH/0zmM3tW1JjuJltAZV2l7zU+uQ==
dependencies:
- "@types/connect" "*"
- "@types/node" "*"
+ "@sinonjs/commons" "^1.6.0"
+ lodash.get "^4.4.2"
+ type-detect "^4.0.8"
-"@types/chai-subset@^1.3.0":
- version "1.3.3"
- resolved "https://registry.yarnpkg.com/@types/chai-subset/-/chai-subset-1.3.3.tgz#97893814e92abd2c534de422cb377e0e0bdaac94"
- integrity sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==
- dependencies:
- "@types/chai" "*"
+"@sinonjs/text-encoding@^0.7.1":
+ version "0.7.1"
+ resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5"
+ integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==
-"@types/chai@*":
- version "4.2.7"
- resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.7.tgz#1c8c25cbf6e59ffa7d6b9652c78e547d9a41692d"
- integrity sha512-luq8meHGYwvky0O7u0eQZdA7B4Wd9owUCqvbw2m3XCrCU8mplYOujMBbvyS547AxJkC+pGnd0Cm15eNxEUNU8g==
-
-"@types/chalk@^0.4.30":
- version "0.4.31"
- resolved "https://registry.yarnpkg.com/@types/chalk/-/chalk-0.4.31.tgz#a31d74241a6b1edbb973cf36d97a2896834a51f9"
- integrity sha1-ox10JBprHtu5c8822XooloNKUfk=
-
-"@types/clean-css@*":
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/@types/clean-css/-/clean-css-4.2.1.tgz#cb0134241ec5e6ede1b5344bc829668fd9871a8d"
- integrity sha512-A1HQhQ0hkvqqByJMgg+Wiv9p9XdoYEzuwm11SVo1mX2/4PSdhjcrUlilJQoqLscIheC51t1D5g+EFWCXZ2VTQQ==
- dependencies:
- "@types/node" "*"
-
-"@types/clone@^0.1.30":
- version "0.1.30"
- resolved "https://registry.yarnpkg.com/@types/clone/-/clone-0.1.30.tgz#e7365648c1b42136a59c7d5040637b3b5c83b614"
- integrity sha1-5zZWSMG0ITalnH1QQGN7O1yDthQ=
-
-"@types/compression@^0.0.33":
- version "0.0.33"
- resolved "https://registry.yarnpkg.com/@types/compression/-/compression-0.0.33.tgz#95dc733a2339aa846381d7f1377792d2553dc27d"
- integrity sha1-ldxzOiM5qoRjgdfxN3eS0lU9wn0=
- dependencies:
- "@types/express" "*"
-
-"@types/connect@*":
- version "3.4.33"
- resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.33.tgz#31610c901eca573b8713c3330abc6e6b9f588546"
- integrity sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==
- dependencies:
- "@types/node" "*"
-
-"@types/content-type@^1.1.0":
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/@types/content-type/-/content-type-1.1.3.tgz#3688bd77fc12f935548eef102a4e34c512b03a07"
- integrity sha512-pv8VcFrZ3fN93L4rTNIbbUzdkzjEyVMp5mPVjsFfOYTDOZMZiZ8P1dhu+kEv3faYyKzZgLlSvnyQNFg+p/v5ug==
-
-"@types/cssbeautify@^0.3.1":
- version "0.3.1"
- resolved "https://registry.yarnpkg.com/@types/cssbeautify/-/cssbeautify-0.3.1.tgz#8e0bee8f7decb952250da0caebe05e30591c17ef"
- integrity sha1-jgvuj33suVIlDaDK6+BeMFkcF+8=
-
-"@types/doctrine@^0.0.1":
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/@types/doctrine/-/doctrine-0.0.1.tgz#b999f2d9f7b43cabe0a1a2f39bc203bc7dcada9d"
- integrity sha1-uZny2fe0PKvgoaLzm8IDvH3K2p0=
-
-"@types/escape-html@0.0.20":
- version "0.0.20"
- resolved "https://registry.yarnpkg.com/@types/escape-html/-/escape-html-0.0.20.tgz#cae698714dd61ebee5ab3f2aeb9a34ba1011735a"
- integrity sha512-6dhZJLbA7aOwkYB2GDGdIqJ20wmHnkDzaxV9PJXe7O02I2dSFTERzRB6JrX6cWKaS+VqhhY7cQUMCbO5kloFUw==
-
-"@types/estree@*":
- version "0.0.42"
- resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.42.tgz#8d0c1f480339efedb3e46070e22dd63e0430dd11"
- integrity sha512-K1DPVvnBCPxzD+G51/cxVIoc2X8uUVl1zpJeE6iKcgHMj4+tbat5Xu4TjV7v2QSDbIeAfLi2hIk+u2+s0MlpUQ==
-
-"@types/events@*":
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7"
- integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==
-
-"@types/expect@^1.20.4":
- version "1.20.4"
- resolved "https://registry.yarnpkg.com/@types/expect/-/expect-1.20.4.tgz#8288e51737bf7e3ab5d7c77bfa695883745264e5"
- integrity sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==
-
-"@types/express-serve-static-core@*":
- version "4.17.2"
- resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.2.tgz#f6f41fa35d42e79dbf6610eccbb2637e6008a0cf"
- integrity sha512-El9yMpctM6tORDAiBwZVLMcxoTMcqqRO9dVyYcn7ycLWbvR8klrDn8CAOwRfZujZtWD7yS/mshTdz43jMOejbg==
- dependencies:
- "@types/node" "*"
- "@types/range-parser" "*"
-
-"@types/express@*", "@types/express@^4.0.30", "@types/express@^4.0.36":
- version "4.17.2"
- resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.2.tgz#a0fb7a23d8855bac31bc01d5a58cadd9b2173e6c"
- integrity sha512-5mHFNyavtLoJmnusB8OKJ5bshSzw+qkMIBAobLrIM48HJvunFva9mOa6aBwh64lBFyNwBbs0xiEFuj4eU/NjCA==
- dependencies:
- "@types/body-parser" "*"
- "@types/express-serve-static-core" "*"
- "@types/serve-static" "*"
-
-"@types/freeport@^1.0.19":
- version "1.0.21"
- resolved "https://registry.yarnpkg.com/@types/freeport/-/freeport-1.0.21.tgz#73f6543ed67d3ca3fff97b985591598b7092066f"
- integrity sha1-c/ZUPtZ9PKP/+XuYVZFZi3CSBm8=
-
-"@types/glob-stream@*":
- version "6.1.0"
- resolved "https://registry.yarnpkg.com/@types/glob-stream/-/glob-stream-6.1.0.tgz#7ede8a33e59140534f8d8adfb8ac9edfb31897bc"
- integrity sha512-RHv6ZQjcTncXo3thYZrsbAVwoy4vSKosSWhuhuQxLOTv74OJuFQxXkmUuZCr3q9uNBEVCvIzmZL/FeRNbHZGUg==
- dependencies:
- "@types/glob" "*"
- "@types/node" "*"
-
-"@types/glob@*":
- version "7.1.1"
- resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575"
- integrity sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==
- dependencies:
- "@types/events" "*"
- "@types/minimatch" "*"
- "@types/node" "*"
-
-"@types/gulp-if@0.0.33":
- version "0.0.33"
- resolved "https://registry.yarnpkg.com/@types/gulp-if/-/gulp-if-0.0.33.tgz#edece22b7925d9a6db5f9c8c0d7882aa776fb678"
- integrity sha512-J5lzff21X7r1x/4hSzn02GgIUEyjCqYIXZ9GgGBLhbsD3RiBdqwnkFWgF16/0jO5rcVZ52Zp+6MQMQdvIsWuKg==
- dependencies:
- "@types/node" "*"
- "@types/vinyl" "*"
-
-"@types/html-minifier@^3.5.1":
- version "3.5.3"
- resolved "https://registry.yarnpkg.com/@types/html-minifier/-/html-minifier-3.5.3.tgz#5276845138db2cebc54c789e0aaf87621a21e84f"
- integrity sha512-j1P/4PcWVVCPEy5lofcHnQ6BtXz9tHGiFPWzqm7TtGuWZEfCHEP446HlkSNc9fQgNJaJZ6ewPtp2aaFla/Uerg==
- dependencies:
- "@types/clean-css" "*"
- "@types/relateurl" "*"
- "@types/uglify-js" "*"
-
-"@types/is-windows@^0.2.0":
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/@types/is-windows/-/is-windows-0.2.0.tgz#6f24ee48731d31168ea510610d6dd15e5fc9c6ff"
- integrity sha1-byTuSHMdMRaOpRBhDW3RXl/Jxv8=
-
-"@types/launchpad@^0.6.0":
- version "0.6.0"
- resolved "https://registry.yarnpkg.com/@types/launchpad/-/launchpad-0.6.0.tgz#37296109b7f277f6e6c5fd7e0c0706bc918fbb51"
- integrity sha1-NylhCbfyd/bmxf1+DAcGvJGPu1E=
-
-"@types/mime@*", "@types/mime@^2.0.0":
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d"
- integrity sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw==
-
-"@types/minimatch@*", "@types/minimatch@^3.0.1", "@types/minimatch@^3.0.3":
+"@types/minimatch@^3.0.3":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
-"@types/mz@0.0.29":
- version "0.0.29"
- resolved "https://registry.yarnpkg.com/@types/mz/-/mz-0.0.29.tgz#bc24728c649973f1c7851e9033f9ce525668c27b"
- integrity sha1-vCRyjGSZc/HHhR6QM/nOUlZowns=
- dependencies:
- "@types/bluebird" "*"
- "@types/node" "*"
-
-"@types/mz@0.0.31":
- version "0.0.31"
- resolved "https://registry.yarnpkg.com/@types/mz/-/mz-0.0.31.tgz#a4d80c082fefe71e40a7c0f07d1e6555bbbc7b52"
- integrity sha1-pNgMCC/v5x5Ap8DwfR5lVbu8e1I=
- dependencies:
- "@types/node" "*"
-
"@types/node@*":
version "13.1.8"
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.1.8.tgz#1d590429fe8187a02707720ecf38a6fe46ce294b"
integrity sha512-6XzyyNM9EKQW4HKuzbo/CkOIjn/evtCmsU+MUM1xDfJ+3/rNjBttM1NgN7AOQvN6tP1Sl1D1PIKMreTArnxM9A==
-"@types/node@^4.0.30":
- version "4.9.4"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-4.9.4.tgz#75ef91733afaa856b01e12da6ecf48aa9d5e221f"
- integrity sha512-nKoiCZ87x6+fs26bNHjy07AQt6f46nFEitGH0P9JmWbY6tEyum6LLfLf7SIsKFh4DnBWsyUM2gYhaQAt+aA0Sw==
-
-"@types/opn@^3.0.28":
- version "3.0.28"
- resolved "https://registry.yarnpkg.com/@types/opn/-/opn-3.0.28.tgz#097d0d1c9b5749573a5d96df132387bb6d02118a"
- integrity sha1-CX0NHJtXSVc6XZbfEyOHu20CEYo=
- dependencies:
- "@types/node" "*"
-
-"@types/parse5@^2.2.34":
- version "2.2.34"
- resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-2.2.34.tgz#e3870a10e82735a720f62d71dcd183ba78ef3a9d"
- integrity sha1-44cKEOgnNacg9i1x3NGDunjvOp0=
- dependencies:
- "@types/node" "*"
-
-"@types/path-is-inside@^1.0.0":
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/@types/path-is-inside/-/path-is-inside-1.0.0.tgz#02d6ff38975d684bdec96204494baf9f29f0e17f"
- integrity sha512-hfnXRGugz+McgX2jxyy5qz9sB21LRzlGn24zlwN2KEgoPtEvjzNRrLtUkOOebPDPZl3Rq7ywKxYvylVcEZDnEw==
-
-"@types/pem@^1.8.1":
- version "1.9.5"
- resolved "https://registry.yarnpkg.com/@types/pem/-/pem-1.9.5.tgz#cd5548b5e0acb4b41a9e21067e9fcd8c57089c99"
- integrity sha512-C0txxEw8B7DCoD85Ko7SEvzUogNd5VDJ5/YBG8XUcacsOGqxr5Oo4g3OUAfdEDUbhXanwUoVh/ZkMFw77FGPQQ==
- dependencies:
- "@types/node" "*"
-
-"@types/range-parser@*":
- version "1.2.3"
- resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
- integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==
-
-"@types/relateurl@*":
- version "0.2.28"
- resolved "https://registry.yarnpkg.com/@types/relateurl/-/relateurl-0.2.28.tgz#6bda7db8653fa62643f5ee69e9f69c11a392e3a6"
- integrity sha1-a9p9uGU/piZD9e5p6facEaOS46Y=
-
-"@types/resolve@0.0.6":
- version "0.0.6"
- resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.6.tgz#0bd2f236c2e1cebb98b79885df57edd71a8d770e"
- integrity sha512-g+Rg8uMWY76oYTyaL+m7ZcblqF/oj7pE6uEUyACluJx4zcop1Lk14qQiocdEkEVMDFm6DmKpxJhsER+ZuTwG3g==
- dependencies:
- "@types/node" "*"
-
-"@types/resolve@0.0.7":
- version "0.0.7"
- resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.7.tgz#b299c13be8d712b1b502fb14a084252acef84f4d"
- integrity sha512-GPewdjkb0Q76o459qgp6pBLzJj/bD3oveS2kfLhIkZ9U3t3AFKtl5DlFB6lGTw0iZmcmxoGC8lpLW3NNJKrN9A==
- dependencies:
- "@types/node" "*"
-
"@types/resolve@0.0.8":
version "0.0.8"
resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194"
@@ -1339,69 +959,6 @@
dependencies:
"@types/node" "*"
-"@types/serve-static@*", "@types/serve-static@^1.7.31":
- version "1.13.3"
- resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.3.tgz#eb7e1c41c4468272557e897e9171ded5e2ded9d1"
- integrity sha512-oprSwp094zOglVrXdlo/4bAHtKTAxX6VT8FOZlBKrmyLbNvE1zxZyJ6yikMVtHIvwP45+ZQGJn+FdXGKTozq0g==
- dependencies:
- "@types/express-serve-static-core" "*"
- "@types/mime" "*"
-
-"@types/spdy@^3.4.1":
- version "3.4.4"
- resolved "https://registry.yarnpkg.com/@types/spdy/-/spdy-3.4.4.tgz#3282fd4ad8c4603aa49f7017dd520a08a345b2bc"
- integrity sha512-N9LBlbVRRYq6HgYpPkqQc3a9HJ/iEtVZToW6xlTtJiMhmRJ7jJdV7TaZQJw/Ve/1ePUsQiCTDc4JMuzzag94GA==
- dependencies:
- "@types/node" "*"
-
-"@types/ua-parser-js@^0.7.31":
- version "0.7.33"
- resolved "https://registry.yarnpkg.com/@types/ua-parser-js/-/ua-parser-js-0.7.33.tgz#4a92089511574e12928a7cb6b99a01831acd1dd7"
- integrity sha512-ngUKcHnytUodUCL7C6EZ+lVXUjTMQb+9p/e1JjV5tN9TVzS98lHozWEFRPY1QcCdwFeMsmVWfZ3DPPT/udCyIw==
-
-"@types/uglify-js@*":
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.0.4.tgz#96beae23df6f561862a830b4288a49e86baac082"
- integrity sha512-SudIN9TRJ+v8g5pTG8RRCqfqTMNqgWCKKd3vtynhGzkIIjxaicNAMuY5TRadJ6tzDu3Dotf3ngaMILtmOdmWEQ==
- dependencies:
- source-map "^0.6.1"
-
-"@types/uuid@^3.4.3":
- version "3.4.6"
- resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-3.4.6.tgz#d2c4c48eb85a757bf2927f75f939942d521e3016"
- integrity sha512-cCdlC/1kGEZdEglzOieLDYBxHsvEOIg7kp/2FYyVR9Pxakq+Qf/inL3RKQ+PA8gOlI/NnL+fXmQH12nwcGzsHw==
- dependencies:
- "@types/node" "*"
-
-"@types/vinyl-fs@^2.4.8":
- version "2.4.11"
- resolved "https://registry.yarnpkg.com/@types/vinyl-fs/-/vinyl-fs-2.4.11.tgz#b98119b8bb2494141eaf649b09fbfeb311161206"
- integrity sha512-2OzQSfIr9CqqWMGqmcERE6Hnd2KY3eBVtFaulVo3sJghplUcaeMdL9ZjEiljcQQeHjheWY9RlNmumjIAvsBNaA==
- dependencies:
- "@types/glob-stream" "*"
- "@types/node" "*"
- "@types/vinyl" "*"
-
-"@types/vinyl@*", "@types/vinyl@^2.0.0":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@types/vinyl/-/vinyl-2.0.4.tgz#9a7a8071c8d14d3a95d41ebe7135babe4ad5995a"
- integrity sha512-2o6a2ixaVI2EbwBPg1QYLGQoHK56p/8X/sGfKbFC8N6sY9lfjsMf/GprtkQkSya0D4uRiutRZ2BWj7k3JvLsAQ==
- dependencies:
- "@types/expect" "^1.20.4"
- "@types/node" "*"
-
-"@types/whatwg-url@^6.4.0":
- version "6.4.0"
- resolved "https://registry.yarnpkg.com/@types/whatwg-url/-/whatwg-url-6.4.0.tgz#1e59b8c64bc0dbdf66d037cf8449d1c3d5270237"
- integrity sha512-tonhlcbQ2eho09am6RHnHOgvtDfDYINd5rgxD+2YSkKENooVCFsWizJz139MQW/PV8FfClyKrNe9ZbdHrSCxGg==
- dependencies:
- "@types/node" "*"
-
-"@types/which@^1.3.1":
- version "1.3.2"
- resolved "https://registry.yarnpkg.com/@types/which/-/which-1.3.2.tgz#9c246fc0c93ded311c8512df2891fb41f6227fdf"
- integrity sha512-8oDqyLC7eD4HM307boe2QWKyuzdzWBj56xI/imSl2cpL+U3tCMaTAkMJ4ee5JBZ/FsOJlvRGeIShiZDAl1qERA==
-
"@webcomponents/shadycss@^1.9.1":
version "1.9.4"
resolved "https://registry.yarnpkg.com/@webcomponents/shadycss/-/shadycss-1.9.4.tgz#4f9d8ea1526bab084c60b53d4854dc39fdb2bb48"
@@ -1412,16 +969,6 @@
resolved "https://registry.yarnpkg.com/@webcomponents/shadycss/-/shadycss-1.9.6.tgz#a8c5db867e49200a05cf8d5008029c09b7861979"
integrity sha512-5fFjvP0jQJZoXK6YzYeYcIDGJ5oEsdjr1L9VaYLw5yxNd4aRz4srMpwCwldeNG0A6Hvr9igbG7fCsBeiiCXd7A==
-"@webcomponents/webcomponentsjs@^1.0.7":
- version "1.3.3"
- resolved "https://registry.yarnpkg.com/@webcomponents/webcomponentsjs/-/webcomponentsjs-1.3.3.tgz#5bb82a0d3210c836bd4623e13a4a93145cb9dc27"
- integrity sha512-eLH04VBMpuZGzBIhOnUjECcQPEPcmfhWEijW9u1B5I+2PPYdWf3vWUExdDxu4Y3GljRSTCOlWnGtS9tpzmXMyQ==
-
-"@webcomponents/webcomponentsjs@^2.0.0":
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/@webcomponents/webcomponentsjs/-/webcomponentsjs-2.4.1.tgz#7baadec56ed2fd79b94ddfd509132d8c0c295c5c"
- integrity sha512-7jxBb+KoWncKb/JGFyTY40PjV4yRx2zd35ZLuvRP+6WndJDL7X32ZIZ7bN3sSQIl+NzJkCo7chfXJyzn+6WZaQ==
-
"@webcomponents/webcomponentsjs@^2.4.0":
version "2.4.3"
resolved "https://registry.yarnpkg.com/@webcomponents/webcomponentsjs/-/webcomponentsjs-2.4.3.tgz#384f4f6d54563ba465fb4df21fe89e78a76fc530"
@@ -1432,7 +979,7 @@
resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.4.0.tgz#0d5eb58e522a461774af8086414f68e1dda7a6c4"
integrity sha512-3ZFfCRfDzx3GFjO6RAkYx81lPGpUS20ISxux9gLxuKnqafNcFQo59+IoZqpO2WvQlyc287B62HDnDdNYRmlvWA==
-accepts@^1.3.5, accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7:
+accepts@^1.3.5, accepts@~1.3.4:
version "1.3.7"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==
@@ -1445,45 +992,11 @@
resolved "https://registry.yarnpkg.com/accessibility-developer-tools/-/accessibility-developer-tools-2.12.0.tgz#3da0cce9d6ec6373964b84f35db7cfc3df7ab514"
integrity sha1-PaDM6dbsY3OWS4TzXbfPw996tRQ=
-acorn-jsx@^3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b"
- integrity sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=
- dependencies:
- acorn "^3.0.4"
-
-acorn@^3.0.4:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a"
- integrity sha1-ReN/s56No/JbruP/U2niu18iAXo=
-
-acorn@^5.5.0:
- version "5.7.3"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279"
- integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==
-
-acorn@^7.1.0:
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c"
- integrity sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==
-
-adm-zip@~0.4.3:
- version "0.4.13"
- resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.13.tgz#597e2f8cc3672151e1307d3e95cddbc75672314a"
- integrity sha512-fERNJX8sOXfel6qCBCMPvZLzENBEhZTzKqg6vrOW5pvoEaQuJhRU4ndTAh6lHOxn1I6jnz2NHra56ZODM751uw==
-
after@0.8.2:
version "0.8.2"
resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=
-agent-base@^4.3.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
- integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
- dependencies:
- es6-promisify "^5.0.0"
-
ajv@^6.5.5:
version "6.11.0"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.11.0.tgz#c3607cbc8ae392d8a5a536f25b21f8e5f3f87fe9"
@@ -1494,23 +1007,11 @@
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
-ansi-align@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f"
- integrity sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=
- dependencies:
- string-width "^2.0.0"
-
ansi-colors@3.2.3:
version "3.2.3"
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813"
integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==
-ansi-regex@^2.0.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
- integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
-
ansi-regex@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
@@ -1521,11 +1022,6 @@
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
-ansi-styles@^2.2.1:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
- integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=
-
ansi-styles@^3.2.0, ansi-styles@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
@@ -1533,11 +1029,6 @@
dependencies:
color-convert "^1.9.0"
-ansi-styles@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.0.0.tgz#cb102df1c56f5123eab8b67cd7b98027a0279178"
- integrity sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=
-
any-promise@^1.0.0, any-promise@^1.1.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
@@ -1551,40 +1042,6 @@
normalize-path "^3.0.0"
picomatch "^2.0.4"
-append-field@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/append-field/-/append-field-1.0.0.tgz#1e3440e915f0b1203d23748e78edd7b9b5b43e56"
- integrity sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=
-
-archiver-utils@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-2.1.0.tgz#e8a460e94b693c3e3da182a098ca6285ba9249e2"
- integrity sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==
- dependencies:
- glob "^7.1.4"
- graceful-fs "^4.2.0"
- lazystream "^1.0.0"
- lodash.defaults "^4.2.0"
- lodash.difference "^4.5.0"
- lodash.flatten "^4.4.0"
- lodash.isplainobject "^4.0.6"
- lodash.union "^4.6.0"
- normalize-path "^3.0.0"
- readable-stream "^2.0.0"
-
-archiver@^3.0.0:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/archiver/-/archiver-3.1.1.tgz#9db7819d4daf60aec10fe86b16cb9258ced66ea0"
- integrity sha512-5Hxxcig7gw5Jod/8Gq0OneVgLYET+oNHcxgWItq4TbhOzRLKNAFUb9edAftiMKXvXfCB0vbGrJdZDNq0dWMsxg==
- dependencies:
- archiver-utils "^2.1.0"
- async "^2.6.3"
- buffer-crc32 "^0.2.1"
- glob "^7.1.4"
- readable-stream "^3.4.0"
- tar-stream "^2.1.0"
- zip-stream "^2.1.2"
-
argparse@^1.0.7:
version "1.0.10"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
@@ -1592,35 +1049,6 @@
dependencies:
sprintf-js "~1.0.2"
-arr-diff@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf"
- integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=
- dependencies:
- arr-flatten "^1.0.1"
-
-arr-diff@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
- integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=
-
-arr-flatten@^1.0.1, arr-flatten@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1"
- integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==
-
-arr-union@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4"
- integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=
-
-array-back@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/array-back/-/array-back-2.0.0.tgz#6877471d51ecc9c9bfa6136fb6c7d5fe69748022"
- integrity sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==
- dependencies:
- typical "^2.6.1"
-
array-back@^3.0.1:
version "3.1.0"
resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0"
@@ -1631,26 +1059,6 @@
resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.1.tgz#9b80312935a52062e1a233a9c7abeb5481b30e90"
integrity sha512-Z/JnaVEXv+A9xabHzN43FiiiWEE7gPCRXMrVmRm00tWbjZRul1iHm7ECzlyNq1p4a4ATXz+G9FJ3GqGOkOV3fg==
-array-find-index@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
- integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=
-
-array-flatten@1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
- integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=
-
-array-unique@^0.2.1:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53"
- integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=
-
-array-unique@^0.3.2:
- version "0.3.2"
- resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
- integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=
-
arraybuffer.slice@~0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675"
@@ -1673,48 +1081,28 @@
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
-assertion-error@^1.0.1, assertion-error@^1.1.0:
+assertion-error@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b"
integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==
-assign-symbols@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
- integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=
-
async-limiter@~1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==
-async@^1.5.2:
- version "1.5.2"
- resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
- integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=
-
-async@^2.0.0, async@^2.0.1, async@^2.1.2, async@^2.4.1, async@^2.6.1, async@^2.6.2, async@^2.6.3:
+async@^2.6.2:
version "2.6.3"
resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==
dependencies:
lodash "^4.17.14"
-async@~0.2.9:
- version "0.2.10"
- resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1"
- integrity sha1-trvgsGdLnXGXCMo43owjfLUmw9E=
-
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
-atob@^2.1.2:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
- integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
-
aws-sign2@~0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
@@ -1725,71 +1113,6 @@
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e"
integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==
-babel-code-frame@^6.26.0:
- version "6.26.0"
- resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
- integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=
- dependencies:
- chalk "^1.1.3"
- esutils "^2.0.2"
- js-tokens "^3.0.2"
-
-babel-generator@^6.26.1:
- version "6.26.1"
- resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90"
- integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==
- dependencies:
- babel-messages "^6.23.0"
- babel-runtime "^6.26.0"
- babel-types "^6.26.0"
- detect-indent "^4.0.0"
- jsesc "^1.3.0"
- lodash "^4.17.4"
- source-map "^0.5.7"
- trim-right "^1.0.1"
-
-babel-helper-evaluate-path@^0.5.0:
- version "0.5.0"
- resolved "https://registry.yarnpkg.com/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.5.0.tgz#a62fa9c4e64ff7ea5cea9353174ef023a900a67c"
- integrity sha512-mUh0UhS607bGh5wUMAQfOpt2JX2ThXMtppHRdRU1kL7ZLRWIXxoV2UIV1r2cAeeNeU1M5SB5/RSUgUxrK8yOkA==
-
-babel-helper-flip-expressions@^0.4.3:
- version "0.4.3"
- resolved "https://registry.yarnpkg.com/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.4.3.tgz#3696736a128ac18bc25254b5f40a22ceb3c1d3fd"
- integrity sha1-NpZzahKKwYvCUlS19AoizrPB0/0=
-
-babel-helper-is-nodes-equiv@^0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz#34e9b300b1479ddd98ec77ea0bbe9342dfe39684"
- integrity sha1-NOmzALFHnd2Y7HfqC76TQt/jloQ=
-
-babel-helper-is-void-0@^0.4.3:
- version "0.4.3"
- resolved "https://registry.yarnpkg.com/babel-helper-is-void-0/-/babel-helper-is-void-0-0.4.3.tgz#7d9c01b4561e7b95dbda0f6eee48f5b60e67313e"
- integrity sha1-fZwBtFYee5Xb2g9u7kj1tg5nMT4=
-
-babel-helper-mark-eval-scopes@^0.4.3:
- version "0.4.3"
- resolved "https://registry.yarnpkg.com/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.4.3.tgz#d244a3bef9844872603ffb46e22ce8acdf551562"
- integrity sha1-0kSjvvmESHJgP/tG4izorN9VFWI=
-
-babel-helper-remove-or-void@^0.4.3:
- version "0.4.3"
- resolved "https://registry.yarnpkg.com/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.4.3.tgz#a4f03b40077a0ffe88e45d07010dee241ff5ae60"
- integrity sha1-pPA7QAd6D/6I5F0HAQ3uJB/1rmA=
-
-babel-helper-to-multiple-sequence-expressions@^0.5.0:
- version "0.5.0"
- resolved "https://registry.yarnpkg.com/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.5.0.tgz#a3f924e3561882d42fcf48907aa98f7979a4588d"
- integrity sha512-m2CvfDW4+1qfDdsrtf4dwOslQC3yhbgyBFptncp4wvtdrDHqueW7slsYv4gArie056phvQFhT2nRcGS4bnm6mA==
-
-babel-messages@^6.23.0:
- version "6.23.0"
- resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e"
- integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=
- dependencies:
- babel-runtime "^6.22.0"
-
babel-plugin-dynamic-import-node@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f"
@@ -1807,213 +1130,6 @@
istanbul-lib-instrument "^3.3.0"
test-exclude "^5.2.3"
-babel-plugin-minify-builtins@^0.5.0:
- version "0.5.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.5.0.tgz#31eb82ed1a0d0efdc31312f93b6e4741ce82c36b"
- integrity sha512-wpqbN7Ov5hsNwGdzuzvFcjgRlzbIeVv1gMIlICbPj0xkexnfoIDe7q+AZHMkQmAE/F9R5jkrB6TLfTegImlXag==
-
-babel-plugin-minify-constant-folding@^0.5.0:
- version "0.5.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-minify-constant-folding/-/babel-plugin-minify-constant-folding-0.5.0.tgz#f84bc8dbf6a561e5e350ff95ae216b0ad5515b6e"
- integrity sha512-Vj97CTn/lE9hR1D+jKUeHfNy+m1baNiJ1wJvoGyOBUx7F7kJqDZxr9nCHjO/Ad+irbR3HzR6jABpSSA29QsrXQ==
- dependencies:
- babel-helper-evaluate-path "^0.5.0"
-
-babel-plugin-minify-dead-code-elimination@^0.5.1:
- version "0.5.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.5.1.tgz#1a0c68e44be30de4976ca69ffc535e08be13683f"
- integrity sha512-x8OJOZIrRmQBcSqxBcLbMIK8uPmTvNWPXH2bh5MDCW1latEqYiRMuUkPImKcfpo59pTUB2FT7HfcgtG8ZlR5Qg==
- dependencies:
- babel-helper-evaluate-path "^0.5.0"
- babel-helper-mark-eval-scopes "^0.4.3"
- babel-helper-remove-or-void "^0.4.3"
- lodash "^4.17.11"
-
-babel-plugin-minify-flip-comparisons@^0.4.3:
- version "0.4.3"
- resolved "https://registry.yarnpkg.com/babel-plugin-minify-flip-comparisons/-/babel-plugin-minify-flip-comparisons-0.4.3.tgz#00ca870cb8f13b45c038b3c1ebc0f227293c965a"
- integrity sha1-AMqHDLjxO0XAOLPB68DyJyk8llo=
- dependencies:
- babel-helper-is-void-0 "^0.4.3"
-
-babel-plugin-minify-guarded-expressions@^0.4.3, babel-plugin-minify-guarded-expressions@^0.4.4:
- version "0.4.4"
- resolved "https://registry.yarnpkg.com/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.4.4.tgz#818960f64cc08aee9d6c75bec6da974c4d621135"
- integrity sha512-RMv0tM72YuPPfLT9QLr3ix9nwUIq+sHT6z8Iu3sLbqldzC1Dls8DPCywzUIzkTx9Zh1hWX4q/m9BPoPed9GOfA==
- dependencies:
- babel-helper-evaluate-path "^0.5.0"
- babel-helper-flip-expressions "^0.4.3"
-
-babel-plugin-minify-infinity@^0.4.3:
- version "0.4.3"
- resolved "https://registry.yarnpkg.com/babel-plugin-minify-infinity/-/babel-plugin-minify-infinity-0.4.3.tgz#dfb876a1b08a06576384ef3f92e653ba607b39ca"
- integrity sha1-37h2obCKBldjhO8/kuZTumB7Oco=
-
-babel-plugin-minify-mangle-names@^0.5.0:
- version "0.5.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-minify-mangle-names/-/babel-plugin-minify-mangle-names-0.5.0.tgz#bcddb507c91d2c99e138bd6b17a19c3c271e3fd3"
- integrity sha512-3jdNv6hCAw6fsX1p2wBGPfWuK69sfOjfd3zjUXkbq8McbohWy23tpXfy5RnToYWggvqzuMOwlId1PhyHOfgnGw==
- dependencies:
- babel-helper-mark-eval-scopes "^0.4.3"
-
-babel-plugin-minify-numeric-literals@^0.4.3:
- version "0.4.3"
- resolved "https://registry.yarnpkg.com/babel-plugin-minify-numeric-literals/-/babel-plugin-minify-numeric-literals-0.4.3.tgz#8e4fd561c79f7801286ff60e8c5fd9deee93c0bc"
- integrity sha1-jk/VYcefeAEob/YOjF/Z3u6TwLw=
-
-babel-plugin-minify-replace@^0.5.0:
- version "0.5.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-minify-replace/-/babel-plugin-minify-replace-0.5.0.tgz#d3e2c9946c9096c070efc96761ce288ec5c3f71c"
- integrity sha512-aXZiaqWDNUbyNNNpWs/8NyST+oU7QTpK7J9zFEFSA0eOmtUNMU3fczlTTTlnCxHmq/jYNFEmkkSG3DDBtW3Y4Q==
-
-babel-plugin-minify-simplify@^0.5.1:
- version "0.5.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-minify-simplify/-/babel-plugin-minify-simplify-0.5.1.tgz#f21613c8b95af3450a2ca71502fdbd91793c8d6a"
- integrity sha512-OSYDSnoCxP2cYDMk9gxNAed6uJDiDz65zgL6h8d3tm8qXIagWGMLWhqysT6DY3Vs7Fgq7YUDcjOomhVUb+xX6A==
- dependencies:
- babel-helper-evaluate-path "^0.5.0"
- babel-helper-flip-expressions "^0.4.3"
- babel-helper-is-nodes-equiv "^0.0.1"
- babel-helper-to-multiple-sequence-expressions "^0.5.0"
-
-babel-plugin-minify-type-constructors@^0.4.3:
- version "0.4.3"
- resolved "https://registry.yarnpkg.com/babel-plugin-minify-type-constructors/-/babel-plugin-minify-type-constructors-0.4.3.tgz#1bc6f15b87f7ab1085d42b330b717657a2156500"
- integrity sha1-G8bxW4f3qxCF1CszC3F2V6IVZQA=
- dependencies:
- babel-helper-is-void-0 "^0.4.3"
-
-babel-plugin-transform-inline-consecutive-adds@^0.4.3:
- version "0.4.3"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.4.3.tgz#323d47a3ea63a83a7ac3c811ae8e6941faf2b0d1"
- integrity sha1-Mj1Ho+pjqDp6w8gRro5pQfrysNE=
-
-babel-plugin-transform-member-expression-literals@^6.9.4:
- version "6.9.4"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-member-expression-literals/-/babel-plugin-transform-member-expression-literals-6.9.4.tgz#37039c9a0c3313a39495faac2ff3a6b5b9d038bf"
- integrity sha1-NwOcmgwzE6OUlfqsL/OmtbnQOL8=
-
-babel-plugin-transform-merge-sibling-variables@^6.9.4:
- version "6.9.4"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-merge-sibling-variables/-/babel-plugin-transform-merge-sibling-variables-6.9.4.tgz#85b422fc3377b449c9d1cde44087203532401dae"
- integrity sha1-hbQi/DN3tEnJ0c3kQIcgNTJAHa4=
-
-babel-plugin-transform-minify-booleans@^6.9.4:
- version "6.9.4"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.9.4.tgz#acbb3e56a3555dd23928e4b582d285162dd2b198"
- integrity sha1-rLs+VqNVXdI5KOS1gtKFFi3SsZg=
-
-babel-plugin-transform-property-literals@^6.9.4:
- version "6.9.4"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.9.4.tgz#98c1d21e255736573f93ece54459f6ce24985d39"
- integrity sha1-mMHSHiVXNlc/k+zlRFn2ziSYXTk=
- dependencies:
- esutils "^2.0.2"
-
-babel-plugin-transform-regexp-constructors@^0.4.3:
- version "0.4.3"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-regexp-constructors/-/babel-plugin-transform-regexp-constructors-0.4.3.tgz#58b7775b63afcf33328fae9a5f88fbd4fb0b4965"
- integrity sha1-WLd3W2OvzzMyj66aX4j71PsLSWU=
-
-babel-plugin-transform-remove-console@^6.9.4:
- version "6.9.4"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.9.4.tgz#b980360c067384e24b357a588d807d3c83527780"
- integrity sha1-uYA2DAZzhOJLNXpYjYB9PINSd4A=
-
-babel-plugin-transform-remove-debugger@^6.9.4:
- version "6.9.4"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-remove-debugger/-/babel-plugin-transform-remove-debugger-6.9.4.tgz#42b727631c97978e1eb2d199a7aec84a18339ef2"
- integrity sha1-QrcnYxyXl44estGZp67IShgznvI=
-
-babel-plugin-transform-remove-undefined@^0.5.0:
- version "0.5.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-remove-undefined/-/babel-plugin-transform-remove-undefined-0.5.0.tgz#80208b31225766c630c97fa2d288952056ea22dd"
- integrity sha512-+M7fJYFaEE/M9CXa0/IRkDbiV3wRELzA1kKQFCJ4ifhrzLKn/9VCCgj9OFmYWwBd8IB48YdgPkHYtbYq+4vtHQ==
- dependencies:
- babel-helper-evaluate-path "^0.5.0"
-
-babel-plugin-transform-simplify-comparison-operators@^6.9.4:
- version "6.9.4"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-simplify-comparison-operators/-/babel-plugin-transform-simplify-comparison-operators-6.9.4.tgz#f62afe096cab0e1f68a2d753fdf283888471ceb9"
- integrity sha1-9ir+CWyrDh9ootdT/fKDiIRxzrk=
-
-babel-plugin-transform-undefined-to-void@^6.9.4:
- version "6.9.4"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.9.4.tgz#be241ca81404030678b748717322b89d0c8fe280"
- integrity sha1-viQcqBQEAwZ4t0hxcyK4nQyP4oA=
-
-babel-preset-minify@^0.5.0:
- version "0.5.1"
- resolved "https://registry.yarnpkg.com/babel-preset-minify/-/babel-preset-minify-0.5.1.tgz#25f5d0bce36ec818be80338d0e594106e21eaa9f"
- integrity sha512-1IajDumYOAPYImkHbrKeiN5AKKP9iOmRoO2IPbIuVp0j2iuCcj0n7P260z38siKMZZ+85d3mJZdtW8IgOv+Tzg==
- dependencies:
- babel-plugin-minify-builtins "^0.5.0"
- babel-plugin-minify-constant-folding "^0.5.0"
- babel-plugin-minify-dead-code-elimination "^0.5.1"
- babel-plugin-minify-flip-comparisons "^0.4.3"
- babel-plugin-minify-guarded-expressions "^0.4.4"
- babel-plugin-minify-infinity "^0.4.3"
- babel-plugin-minify-mangle-names "^0.5.0"
- babel-plugin-minify-numeric-literals "^0.4.3"
- babel-plugin-minify-replace "^0.5.0"
- babel-plugin-minify-simplify "^0.5.1"
- babel-plugin-minify-type-constructors "^0.4.3"
- babel-plugin-transform-inline-consecutive-adds "^0.4.3"
- babel-plugin-transform-member-expression-literals "^6.9.4"
- babel-plugin-transform-merge-sibling-variables "^6.9.4"
- babel-plugin-transform-minify-booleans "^6.9.4"
- babel-plugin-transform-property-literals "^6.9.4"
- babel-plugin-transform-regexp-constructors "^0.4.3"
- babel-plugin-transform-remove-console "^6.9.4"
- babel-plugin-transform-remove-debugger "^6.9.4"
- babel-plugin-transform-remove-undefined "^0.5.0"
- babel-plugin-transform-simplify-comparison-operators "^6.9.4"
- babel-plugin-transform-undefined-to-void "^6.9.4"
- lodash "^4.17.11"
-
-babel-runtime@^6.22.0, babel-runtime@^6.26.0:
- version "6.26.0"
- resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
- integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4=
- dependencies:
- core-js "^2.4.0"
- regenerator-runtime "^0.11.0"
-
-babel-traverse@^6.26.0:
- version "6.26.0"
- resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee"
- integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=
- dependencies:
- babel-code-frame "^6.26.0"
- babel-messages "^6.23.0"
- babel-runtime "^6.26.0"
- babel-types "^6.26.0"
- babylon "^6.18.0"
- debug "^2.6.8"
- globals "^9.18.0"
- invariant "^2.2.2"
- lodash "^4.17.4"
-
-babel-types@^6.26.0:
- version "6.26.0"
- resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497"
- integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=
- dependencies:
- babel-runtime "^6.26.0"
- esutils "^2.0.2"
- lodash "^4.17.4"
- to-fast-properties "^1.0.3"
-
-babylon@^6.18.0:
- version "6.18.0"
- resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
- integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==
-
-babylon@^7.0.0-beta.42:
- version "7.0.0-beta.47"
- resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.47.tgz#6d1fa44f0abec41ab7c780481e62fd9aafbdea80"
- integrity sha512-+rq2cr4GDhtToEzKFD6KZZMDBXhjFAr9JjPw9pAppZACeEWqNM294j+NdBzkSHYXwzzBmVjZ3nEVJlOhbR2gOQ==
-
backo2@1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
@@ -2029,39 +1145,11 @@
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8"
integrity sha1-c5JncZI7Whl0etZmqlzUv5xunOg=
-base64-js@1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.0.tgz#a39992d723584811982be5e290bb6a53d86700f1"
- integrity sha1-o5mS1yNYSBGYK+XikLtqU9hnAPE=
-
-base64-js@^1.0.2:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1"
- integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==
-
base64id@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6"
integrity sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=
-base64id@2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6"
- integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==
-
-base@^0.11.1:
- version "0.11.2"
- resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f"
- integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==
- dependencies:
- cache-base "^1.0.1"
- class-utils "^0.3.5"
- component-emitter "^1.2.1"
- define-property "^1.0.0"
- isobject "^3.0.1"
- mixin-deep "^1.2.0"
- pascalcase "^0.1.1"
-
bcrypt-pbkdf@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
@@ -2081,21 +1169,6 @@
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c"
integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==
-bl@^2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/bl/-/bl-2.2.0.tgz#e1a574cdf528e4053019bb800b041c0ac88da493"
- integrity sha512-wbgvOpqopSr7uq6fJrLH8EsvYMJf9gzfo2jCsL2eTy75qXPukA4pCgHamOQkZtY5vmfVtjB+P3LNlMHW5CEZXA==
- dependencies:
- readable-stream "^2.3.5"
- safe-buffer "^5.1.1"
-
-bl@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/bl/-/bl-3.0.0.tgz#3611ec00579fd18561754360b21e9f784500ff88"
- integrity sha512-EUAyP5UHU5hxF8BPT0LKW8gjYLhq1DQIcneOX/pL/m2Alo+OYDQAJlHq+yseMP50Os2nHXOSic6Ss3vSQeyf4A==
- dependencies:
- readable-stream "^3.0.1"
-
blob@0.0.5:
version "0.0.5"
resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.5.tgz#d680eeef25f8cd91ad533f5b01eed48e64caf683"
@@ -2106,7 +1179,7 @@
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
-body-parser@1.19.0, body-parser@^1.16.1, body-parser@^1.17.2:
+body-parser@^1.16.1:
version "1.19.0"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==
@@ -2122,30 +1195,6 @@
raw-body "2.4.0"
type-is "~1.6.17"
-bower-config@^1.4.0, bower-config@^1.4.1:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/bower-config/-/bower-config-1.4.1.tgz#85fd9df367c2b8dbbd0caa4c5f2bad40cd84c2cc"
- integrity sha1-hf2d82fCuNu9DKpMXyutQM2Ewsw=
- dependencies:
- graceful-fs "^4.1.3"
- mout "^1.0.0"
- optimist "^0.6.1"
- osenv "^0.1.3"
- untildify "^2.1.0"
-
-boxen@^1.2.1:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b"
- integrity sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==
- dependencies:
- ansi-align "^2.0.0"
- camelcase "^4.0.0"
- chalk "^2.0.1"
- cli-boxes "^1.0.0"
- string-width "^2.0.0"
- term-size "^1.2.0"
- widest-line "^2.0.0"
-
brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
@@ -2154,31 +1203,6 @@
balanced-match "^1.0.0"
concat-map "0.0.1"
-braces@^1.8.2:
- version "1.8.5"
- resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7"
- integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=
- dependencies:
- expand-range "^1.8.1"
- preserve "^0.2.0"
- repeat-element "^1.1.2"
-
-braces@^2.3.1:
- version "2.3.2"
- resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729"
- integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==
- dependencies:
- arr-flatten "^1.1.0"
- array-unique "^0.3.2"
- extend-shallow "^2.0.1"
- fill-range "^4.0.0"
- isobject "^3.0.1"
- repeat-element "^1.1.2"
- snapdragon "^0.8.1"
- snapdragon-node "^2.0.1"
- split-string "^3.0.2"
- to-regex "^3.0.1"
-
braces@^3.0.2, braces@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
@@ -2186,19 +1210,6 @@
dependencies:
fill-range "^7.0.1"
-browser-capabilities@^1.0.0:
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/browser-capabilities/-/browser-capabilities-1.1.4.tgz#a6bd657a07a134532ad66c722b8949904478b973"
- integrity sha512-BezMQhbQklxjRQpZZQ8tnbzEo6AldUwMh8/PeWt5/CTBSwByQRXZEAK2fbnEahQ4poeeaI0suAYRq25A1YGOmw==
- dependencies:
- "@types/ua-parser-js" "^0.7.31"
- ua-parser-js "^0.7.15"
-
-browser-stdout@1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f"
- integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8=
-
browser-stdout@1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
@@ -2223,13 +1234,6 @@
node-releases "^1.1.53"
pkg-up "^2.0.0"
-browserstack@^1.2.0:
- version "1.5.3"
- resolved "https://registry.yarnpkg.com/browserstack/-/browserstack-1.5.3.tgz#93ab48799a12ef99dbd074dd595410ddb196a7ac"
- integrity sha512-AO+mECXsW4QcqC9bxwM29O7qWa7bJT94uBFzeb5brylIQwawuEziwq20dPYbins95GlWzOawgyDNdjYAo32EKg==
- dependencies:
- https-proxy-agent "^2.2.1"
-
buffer-alloc-unsafe@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
@@ -2243,11 +1247,6 @@
buffer-alloc-unsafe "^1.1.0"
buffer-fill "^1.0.0"
-buffer-crc32@^0.2.1, buffer-crc32@^0.2.13, buffer-crc32@~0.2.3:
- version "0.2.13"
- resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
- integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
-
buffer-fill@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c"
@@ -2258,52 +1257,16 @@
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
-buffer@^5.1.0:
- version "5.4.3"
- resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.4.3.tgz#3fbc9c69eb713d323e3fc1a895eee0710c072115"
- integrity sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A==
- dependencies:
- base64-js "^1.0.2"
- ieee754 "^1.1.4"
-
builtin-modules@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.1.0.tgz#aad97c15131eb76b65b50ef208e7584cd76a7484"
integrity sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==
-busboy@^0.2.11:
- version "0.2.14"
- resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.2.14.tgz#6c2a622efcf47c57bbbe1e2a9c37ad36c7925453"
- integrity sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=
- dependencies:
- dicer "0.2.5"
- readable-stream "1.1.x"
-
-bytes@3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
- integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=
-
bytes@3.1.0, bytes@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
-cache-base@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2"
- integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==
- dependencies:
- collection-visit "^1.0.0"
- component-emitter "^1.2.1"
- get-value "^2.0.6"
- has-value "^1.0.0"
- isobject "^3.0.1"
- set-value "^2.0.0"
- to-object-path "^0.3.0"
- union-value "^1.0.0"
- unset-value "^1.0.0"
-
cache-content-type@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/cache-content-type/-/cache-content-type-1.0.1.tgz#035cde2b08ee2129f4a8315ea8f00a00dba1453c"
@@ -2317,7 +1280,7 @@
resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20"
integrity sha1-KAOY5dZkvXQDi28JBRU+borxvCA=
-camel-case@3.0.x, camel-case@^3.0.0:
+camel-case@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73"
integrity sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=
@@ -2325,36 +1288,11 @@
no-case "^2.2.0"
upper-case "^1.1.1"
-camelcase-keys@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7"
- integrity sha1-MIvur/3ygRkFHvodkyITyRuPkuc=
- dependencies:
- camelcase "^2.0.0"
- map-obj "^1.0.0"
-
-camelcase@^2.0.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
- integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=
-
-camelcase@^4.0.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
- integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=
-
camelcase@^5.0.0, camelcase@^5.3.1:
version "5.3.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
-cancel-token@^0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/cancel-token/-/cancel-token-0.1.1.tgz#c18197674bb1c84c1d6933ebf15d8d5a5ce79b4f"
- integrity sha1-wYGXZ0uxyEwdaTPr8V2NWlznm08=
- dependencies:
- "@types/node" "^4.0.30"
-
caniuse-api@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0"
@@ -2370,25 +1308,11 @@
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001038.tgz#44da3cbca2ab6cb6aa83d1be5d324e17f141caff"
integrity sha512-zii9quPo96XfOiRD4TrfYGs+QsGZpb2cGiMAzPjtf/hpFgB6zCPZgJb7I1+EATeMw/o+lG8FyRAnI+CWStHcaQ==
-capture-stack-trace@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz#a6c0bbe1f38f3aa0b92238ecb6ff42c344d4135d"
- integrity sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==
-
caseless@~0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
-chai@^3.5.0:
- version "3.5.0"
- resolved "https://registry.yarnpkg.com/chai/-/chai-3.5.0.tgz#4d02637b067fe958bdbfdd3a40ec56fef7373247"
- integrity sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=
- dependencies:
- assertion-error "^1.0.1"
- deep-eql "^0.1.3"
- type-detect "^1.0.0"
-
chai@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5"
@@ -2401,18 +1325,7 @@
pathval "^1.1.0"
type-detect "^4.0.5"
-chalk@^1.1.1, chalk@^1.1.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
- integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=
- dependencies:
- ansi-styles "^2.2.1"
- escape-string-regexp "^1.0.2"
- has-ansi "^2.0.0"
- strip-ansi "^3.0.0"
- supports-color "^2.0.0"
-
-chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2:
+chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
@@ -2421,20 +1334,6 @@
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
-chalk@~0.4.0:
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.4.0.tgz#5199a3ddcd0c1efe23bc08c1b027b06176e0c64f"
- integrity sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=
- dependencies:
- ansi-styles "~1.0.0"
- has-color "~0.1.0"
- strip-ansi "~0.1.0"
-
-charenc@~0.0.1:
- version "0.0.2"
- resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
- integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=
-
check-error@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82"
@@ -2470,28 +1369,6 @@
optionalDependencies:
fsevents "~2.1.2"
-ci-info@^1.5.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497"
- integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==
-
-class-utils@^0.3.5:
- version "0.3.6"
- resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463"
- integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==
- dependencies:
- arr-union "^3.1.0"
- define-property "^0.2.5"
- isobject "^3.0.0"
- static-extend "^0.1.1"
-
-clean-css@4.2.x:
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.1.tgz#2d411ef76b8569b6d0c84068dabe85b0aa5e5c17"
- integrity sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==
- dependencies:
- source-map "~0.6.0"
-
clean-css@^4.2.1:
version "4.2.3"
resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78"
@@ -2499,16 +1376,6 @@
dependencies:
source-map "~0.6.0"
-cleankill@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/cleankill/-/cleankill-2.0.0.tgz#59830dfc8b411d53dc72ad09d45a78ea33161a91"
- integrity sha1-WYMN/ItBHVPccq0J1Fp46jMWGpE=
-
-cli-boxes@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143"
- integrity sha1-T6kXw+WclKAEzWH47lCdplFocUM=
-
cliui@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5"
@@ -2518,17 +1385,7 @@
strip-ansi "^5.2.0"
wrap-ansi "^5.1.0"
-clone-stats@^0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1"
- integrity sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=
-
-clone@^1.0.0:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
- integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4=
-
-clone@^2.0.0, clone@^2.1.0, clone@^2.1.2:
+clone@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f"
integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=
@@ -2538,15 +1395,7 @@
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=
-collection-visit@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0"
- integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=
- dependencies:
- map-visit "^1.0.0"
- object-visit "^1.0.0"
-
-color-convert@^1.9.0, color-convert@^1.9.1:
+color-convert@^1.9.0:
version "1.9.3"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
@@ -2558,45 +1407,11 @@
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
-color-name@^1.0.0:
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
- integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
-
-color-string@^1.5.2:
- version "1.5.3"
- resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc"
- integrity sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==
- dependencies:
- color-name "^1.0.0"
- simple-swizzle "^0.2.2"
-
-color@3.0.x:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/color/-/color-3.0.0.tgz#d920b4328d534a3ac8295d68f7bd4ba6c427be9a"
- integrity sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==
- dependencies:
- color-convert "^1.9.1"
- color-string "^1.5.2"
-
-colornames@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/colornames/-/colornames-1.1.1.tgz#f8889030685c7c4ff9e2a559f5077eb76a816f96"
- integrity sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y=
-
-colors@^1.1.0, colors@^1.2.1:
+colors@^1.1.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
-colorspace@1.1.x:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.2.tgz#e0128950d082b86a2168580796a0aa5d6c68d8c5"
- integrity sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==
- dependencies:
- color "3.0.x"
- text-hex "1.0.x"
-
combined-stream@^1.0.6, combined-stream@~1.0.6:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
@@ -2614,16 +1429,6 @@
lodash.camelcase "^4.3.0"
typical "^4.0.0"
-command-line-usage@^5.0.5:
- version "5.0.5"
- resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-5.0.5.tgz#5f25933ffe6dedd983c635d38a21d7e623fda357"
- integrity sha512-d8NrGylA5oCXSbGoKz05FkehDAzSmIm4K03S5VDh4d5lZAtTWfc3D1RuETtuQCn8129nYfJfDdF7P/lwcz1BlA==
- dependencies:
- array-back "^2.0.0"
- chalk "^2.4.1"
- table-layout "^0.4.3"
- typical "^2.6.1"
-
command-line-usage@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-6.1.0.tgz#f28376a3da3361ff3d36cfd31c3c22c9a64c7cb6"
@@ -2634,28 +1439,11 @@
table-layout "^1.0.0"
typical "^5.2.0"
-commander@2.17.x:
- version "2.17.1"
- resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
- integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==
-
-commander@2.9.0:
- version "2.9.0"
- resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
- integrity sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=
- dependencies:
- graceful-readlink ">= 1.0.0"
-
commander@^2.19.0, commander@^2.20.0, commander@~2.20.3:
version "2.20.3"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
-commander@~2.19.0:
- version "2.19.0"
- resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
- integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
-
component-bind@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1"
@@ -2666,73 +1454,23 @@
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6"
integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=
-component-emitter@^1.2.1:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
- integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
-
component-inherit@0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143"
integrity sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=
-compress-commons@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-2.1.1.tgz#9410d9a534cf8435e3fbbb7c6ce48de2dc2f0610"
- integrity sha512-eVw6n7CnEMFzc3duyFVrQEuY1BlHR3rYsSztyG32ibGMW722i3C6IizEGMFmfMU+A+fALvBIwxN3czffTcdA+Q==
- dependencies:
- buffer-crc32 "^0.2.13"
- crc32-stream "^3.0.1"
- normalize-path "^3.0.0"
- readable-stream "^2.3.6"
-
-compressible@^2.0.0, compressible@~2.0.16:
+compressible@^2.0.0:
version "2.0.18"
resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba"
integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==
dependencies:
mime-db ">= 1.43.0 < 2"
-compression@^1.6.2:
- version "1.7.4"
- resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f"
- integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==
- dependencies:
- accepts "~1.3.5"
- bytes "3.0.0"
- compressible "~2.0.16"
- debug "2.6.9"
- on-headers "~1.0.2"
- safe-buffer "5.1.2"
- vary "~1.1.2"
-
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
-concat-stream@^1.5.2:
- version "1.6.2"
- resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
- integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
- dependencies:
- buffer-from "^1.0.0"
- inherits "^2.0.3"
- readable-stream "^2.2.2"
- typedarray "^0.0.6"
-
-configstore@^3.0.0:
- version "3.1.2"
- resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.2.tgz#c6f25defaeef26df12dd33414b001fe81a543f8f"
- integrity sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==
- dependencies:
- dot-prop "^4.1.0"
- graceful-fs "^4.1.2"
- make-dir "^1.0.0"
- unique-string "^1.0.0"
- write-file-atomic "^2.0.0"
- xdg-basedir "^3.0.0"
-
connect@^3.6.0:
version "3.7.0"
resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8"
@@ -2743,40 +1481,30 @@
parseurl "~1.3.3"
utils-merge "1.0.1"
-content-disposition@0.5.3, content-disposition@~0.5.2:
+content-disposition@~0.5.2:
version "0.5.3"
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd"
integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==
dependencies:
safe-buffer "5.1.2"
-content-type@^1.0.2, content-type@^1.0.4, content-type@~1.0.4:
+content-type@^1.0.4, content-type@~1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
-convert-source-map@^1.1.1, convert-source-map@^1.7.0:
+convert-source-map@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==
dependencies:
safe-buffer "~5.1.1"
-cookie-signature@1.0.6:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
- integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
-
cookie@0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=
-cookie@0.4.0:
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba"
- integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==
-
cookies@~0.8.0:
version "0.8.0"
resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.8.0.tgz#1293ce4b391740a8406e3c9870e828c4b54f3f90"
@@ -2785,11 +1513,6 @@
depd "~2.0.0"
keygrip "~1.1.0"
-copy-descriptor@^0.1.0:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
- integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=
-
core-js-bundle@^3.6.0:
version "3.6.4"
resolved "https://registry.yarnpkg.com/core-js-bundle/-/core-js-bundle-3.6.4.tgz#d4e098323c035f4a1b61f00db0b8def04c243920"
@@ -2803,99 +1526,11 @@
browserslist "^4.8.3"
semver "7.0.0"
-core-js@^2.4.0:
- version "2.6.11"
- resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c"
- integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==
-
-core-util-is@1.0.2, core-util-is@~1.0.0:
+core-util-is@1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
-cors@^2.8.4:
- version "2.8.5"
- resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29"
- integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==
- dependencies:
- object-assign "^4"
- vary "^1"
-
-crc32-stream@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-3.0.1.tgz#cae6eeed003b0e44d739d279de5ae63b171b4e85"
- integrity sha512-mctvpXlbzsvK+6z8kJwSJ5crm7yBwrQMTybJzMw1O4lLGJqjlDCXY2Zw7KheiA6XBEcBmfLx1D88mjRGVJtY9w==
- dependencies:
- crc "^3.4.4"
- readable-stream "^3.4.0"
-
-crc@^3.4.4:
- version "3.8.0"
- resolved "https://registry.yarnpkg.com/crc/-/crc-3.8.0.tgz#ad60269c2c856f8c299e2c4cc0de4556914056c6"
- integrity sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==
- dependencies:
- buffer "^5.1.0"
-
-create-error-class@^3.0.0:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6"
- integrity sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=
- dependencies:
- capture-stack-trace "^1.0.0"
-
-cross-spawn@^5.0.1:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
- integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=
- dependencies:
- lru-cache "^4.0.1"
- shebang-command "^1.2.0"
- which "^1.2.9"
-
-cross-spawn@^6.0.5:
- version "6.0.5"
- resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
- integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
- dependencies:
- nice-try "^1.0.4"
- path-key "^2.0.1"
- semver "^5.5.0"
- shebang-command "^1.2.0"
- which "^1.2.9"
-
-crypt@~0.0.1:
- version "0.0.2"
- resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
- integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=
-
-crypto-random-string@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e"
- integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=
-
-css-slam@^2.1.2:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/css-slam/-/css-slam-2.1.2.tgz#3d35b1922cb3e0002a45c89ab189492508c493e5"
- integrity sha512-cObrY+mhFEmepWpua6EpMrgRNTQ0eeym+kvR0lukI6hDEzK7F8himEDS4cJ9+fPHCoArTzVrrR0d+oAUbTR1NA==
- dependencies:
- command-line-args "^5.0.2"
- command-line-usage "^5.0.5"
- dom5 "^3.0.0"
- parse5 "^4.0.0"
- shady-css-parser "^0.1.0"
-
-cssbeautify@^0.3.1:
- version "0.3.1"
- resolved "https://registry.yarnpkg.com/cssbeautify/-/cssbeautify-0.3.1.tgz#12dd1f734035c2e6faca67dcbdcef74e42811397"
- integrity sha1-Et0fc0A1wub6ymfcvc73TkKBE5c=
-
-currently-unhandled@^0.4.1:
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
- integrity sha1-mI3zP+qxke95mmE2nddsF635V+o=
- dependencies:
- array-find-index "^1.0.1"
-
custom-event@~1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425"
@@ -2918,14 +1553,7 @@
resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.0.tgz#44a540abc0ea9943018dc0eaa95cce87f65cd131"
integrity sha512-mYtLl1xfZLi1m4RtQYlZgJUNQjl4ZxVnHzIR8nLLgi4q1YT8o/WM+MK/f8yfcc9s5Ir5zRaPZyZU6xs1Syoocg==
-debug@2.6.8:
- version "2.6.8"
- resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
- integrity sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=
- dependencies:
- ms "2.0.0"
-
-debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8:
+debug@2.6.9:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
@@ -2939,7 +1567,7 @@
dependencies:
ms "^2.1.1"
-debug@^4.1.0, debug@^4.1.1, debug@~4.1.0:
+debug@^4.1.0, debug@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
@@ -2953,23 +1581,11 @@
dependencies:
ms "2.0.0"
-decamelize@^1.1.2, decamelize@^1.2.0:
+decamelize@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
-decode-uri-component@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
- integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
-
-deep-eql@^0.1.3:
- version "0.1.3"
- resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-0.1.3.tgz#ef558acab8de25206cd713906d74e56930eb69f2"
- integrity sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=
- dependencies:
- type-detect "0.1.1"
-
deep-eql@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df"
@@ -2982,7 +1598,7 @@
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=
-deep-extend@^0.6.0, deep-extend@~0.6.0:
+deep-extend@~0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
@@ -2999,28 +1615,6 @@
dependencies:
object-keys "^1.0.12"
-define-property@^0.2.5:
- version "0.2.5"
- resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116"
- integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=
- dependencies:
- is-descriptor "^0.1.0"
-
-define-property@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6"
- integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY=
- dependencies:
- is-descriptor "^1.0.0"
-
-define-property@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d"
- integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==
- dependencies:
- is-descriptor "^1.0.2"
- isobject "^3.0.1"
-
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
@@ -3041,66 +1635,25 @@
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
-destroy@^1.0.4, destroy@~1.0.4:
+destroy@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
-detect-file@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7"
- integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=
-
-detect-indent@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208"
- integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg=
- dependencies:
- repeating "^2.0.0"
-
-detect-node@^2.0.3:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c"
- integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==
-
di@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c"
integrity sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=
-diagnostics@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/diagnostics/-/diagnostics-1.1.1.tgz#cab6ac33df70c9d9a727490ae43ac995a769b22a"
- integrity sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==
- dependencies:
- colorspace "1.1.x"
- enabled "1.0.x"
- kuler "1.0.x"
-
-dicer@0.2.5:
- version "0.2.5"
- resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.2.5.tgz#5996c086bb33218c812c090bddc09cd12facb70f"
- integrity sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=
- dependencies:
- readable-stream "1.1.x"
- streamsearch "0.1.2"
-
-diff@3.2.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9"
- integrity sha1-yc45Okt8vQsFinJck98pkCeGj/k=
-
-diff@3.5.0, diff@^3.1.0:
+diff@3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
-doctrine@^2.0.2:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
- integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==
- dependencies:
- esutils "^2.0.2"
+diff@^4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
+ integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
dom-serialize@^2.2.0:
version "2.2.1"
@@ -3112,51 +1665,6 @@
extend "^3.0.0"
void-elements "^2.0.0"
-dom-urls@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/dom-urls/-/dom-urls-1.1.0.tgz#001ddf81628cd1e706125c7176f53ccec55d918e"
- integrity sha1-AB3fgWKM0ecGElxxdvU8zsVdkY4=
- dependencies:
- urijs "^1.16.1"
-
-dom5@^3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/dom5/-/dom5-3.0.1.tgz#cdfc7331f376e284bf379e6ea054afc136702944"
- integrity sha512-JPFiouQIr16VQ4dX6i0+Hpbg3H2bMKPmZ+WZgBOSSvOPx9QHwwY8sPzeM2baUtViESYto6wC2nuZOMC/6gulcA==
- dependencies:
- "@types/parse5" "^2.2.34"
- clone "^2.1.0"
- parse5 "^4.0.0"
-
-dot-prop@^4.1.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57"
- integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==
- dependencies:
- is-obj "^1.0.0"
-
-duplexer2@^0.1.2:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1"
- integrity sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=
- dependencies:
- readable-stream "^2.0.2"
-
-duplexer3@^0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
- integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=
-
-duplexify@^3.2.0, duplexify@^3.5.0:
- version "3.7.1"
- resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309"
- integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==
- dependencies:
- end-of-stream "^1.0.0"
- inherits "^2.0.1"
- readable-stream "^2.0.0"
- stream-shift "^1.0.0"
-
dynamic-import-polyfill@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/dynamic-import-polyfill/-/dynamic-import-polyfill-0.1.1.tgz#e1f9eb1876ee242bd56572f8ed4df768e143083f"
@@ -3180,29 +1688,17 @@
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.392.tgz#280ab4f7a3ae47419cfabb15dbfc1567be7f1111"
integrity sha512-/hsgeVdReDsyTBE0aU9FRdh1wnNPrX3xlz3t61F+CJPOT+Umfi9DXHsCX85TEgWZQqlow0Rw44/4/jbU2Sqgkg==
-emitter-component@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/emitter-component/-/emitter-component-1.1.1.tgz#065e2dbed6959bf470679edabeaf7981d1003ab6"
- integrity sha1-Bl4tvtaVm/RwZ57avq95gdEAOrY=
-
emoji-regex@^7.0.1:
version "7.0.3"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
-enabled@1.0.x:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/enabled/-/enabled-1.0.2.tgz#965f6513d2c2d1c5f4652b64a2e3396467fc2f93"
- integrity sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=
- dependencies:
- env-variable "0.0.x"
-
encodeurl@^1.0.2, encodeurl@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
-end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1:
+end-of-stream@^1.1.0:
version "1.4.4"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
@@ -3226,23 +1722,6 @@
xmlhttprequest-ssl "~1.5.4"
yeast "0.1.2"
-engine.io-client@~3.4.0:
- version "3.4.0"
- resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.4.0.tgz#82a642b42862a9b3f7a188f41776b2deab643700"
- integrity sha512-a4J5QO2k99CM2a0b12IznnyQndoEvtA4UAldhGzKqnHf42I3Qs2W5SPnDvatZRcMaNZs4IevVicBPayxYt6FwA==
- dependencies:
- component-emitter "1.2.1"
- component-inherit "0.0.3"
- debug "~4.1.0"
- engine.io-parser "~2.2.0"
- has-cors "1.1.0"
- indexof "0.0.1"
- parseqs "0.0.5"
- parseuri "0.0.5"
- ws "~6.1.0"
- xmlhttprequest-ssl "~1.5.4"
- yeast "0.1.2"
-
engine.io-parser@~2.1.0, engine.io-parser@~2.1.1:
version "2.1.3"
resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.1.3.tgz#757ab970fbf2dfb32c7b74b033216d5739ef79a6"
@@ -3254,17 +1733,6 @@
blob "0.0.5"
has-binary2 "~1.0.2"
-engine.io-parser@~2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.2.0.tgz#312c4894f57d52a02b420868da7b5c1c84af80ed"
- integrity sha512-6I3qD9iUxotsC5HEMuuGsKA0cXerGz+4uGcXQEkfBidgKf0amsjrrtwcbwK/nzpZBxclXlV7gGl9dgWvu4LF6w==
- dependencies:
- after "0.8.2"
- arraybuffer.slice "~0.0.7"
- base64-arraybuffer "0.1.5"
- blob "0.0.5"
- has-binary2 "~1.0.2"
-
engine.io@~3.2.0:
version "3.2.1"
resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.2.1.tgz#b60281c35484a70ee0351ea0ebff83ec8c9522a2"
@@ -3277,29 +1745,12 @@
engine.io-parser "~2.1.0"
ws "~3.3.1"
-engine.io@~3.4.0:
- version "3.4.0"
- resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.4.0.tgz#3a962cc4535928c252759a00f98519cb46c53ff3"
- integrity sha512-XCyYVWzcHnK5cMz7G4VTu2W7zJS7SM1QkcelghyIk/FmobWBtXE7fwhBusEKvCSqc3bMh8fNFMlUkCKTFRxH2w==
- dependencies:
- accepts "~1.3.4"
- base64id "2.0.0"
- cookie "0.3.1"
- debug "~4.1.0"
- engine.io-parser "~2.2.0"
- ws "^7.1.2"
-
ent@~2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d"
integrity sha1-6WQhkyWiHQX0RGai9obtbOX13R0=
-env-variable@0.0.x:
- version "0.0.5"
- resolved "https://registry.yarnpkg.com/env-variable/-/env-variable-0.0.5.tgz#913dd830bef11e96a039c038d4130604eba37f88"
- integrity sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA==
-
-error-ex@^1.2.0, error-ex@^1.3.1:
+error-ex@^1.3.1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
@@ -3398,41 +1849,16 @@
is-date-object "^1.0.1"
is-symbol "^1.0.2"
-es6-promise@^4.0.3, es6-promise@^4.0.5:
- version "4.2.8"
- resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
- integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
-
-es6-promisify@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
- integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=
- dependencies:
- es6-promise "^4.0.3"
-
-es6-promisify@^6.0.0:
- version "6.0.2"
- resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-6.0.2.tgz#525c23725b8510f5f1f2feb5a1fbad93a93e29b4"
- integrity sha512-eO6vFm0JvqGzjWIQA6QVKjxpmELfhWbDUWHm1rPfIbn55mhKPiAa5xpLmQWJrNa629ZIeQ8ZvMAi13kvrjK6Mg==
-
escape-html@^1.0.3, escape-html@~1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
-escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.4, escape-string-regexp@^1.0.5:
+escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
-espree@^3.5.2:
- version "3.5.4"
- resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7"
- integrity sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==
- dependencies:
- acorn "^5.5.0"
- acorn-jsx "^3.0.0"
-
esprima@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
@@ -3448,7 +1874,7 @@
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
-etag@^1.3.0, etag@~1.8.1:
+etag@^1.3.0:
version "1.8.1"
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
@@ -3458,130 +1884,11 @@
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.0.tgz#d65176163887ee59f386d64c82610b696a4a74eb"
integrity sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==
-execa@^0.7.0:
- version "0.7.0"
- resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777"
- integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=
- dependencies:
- cross-spawn "^5.0.1"
- get-stream "^3.0.0"
- is-stream "^1.1.0"
- npm-run-path "^2.0.0"
- p-finally "^1.0.0"
- signal-exit "^3.0.0"
- strip-eof "^1.0.0"
-
-expand-brackets@^0.1.4:
- version "0.1.5"
- resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
- integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=
- dependencies:
- is-posix-bracket "^0.1.0"
-
-expand-brackets@^2.1.4:
- version "2.1.4"
- resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622"
- integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI=
- dependencies:
- debug "^2.3.3"
- define-property "^0.2.5"
- extend-shallow "^2.0.1"
- posix-character-classes "^0.1.0"
- regex-not "^1.0.0"
- snapdragon "^0.8.1"
- to-regex "^3.0.1"
-
-expand-range@^1.8.1:
- version "1.8.2"
- resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337"
- integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=
- dependencies:
- fill-range "^2.1.0"
-
-expand-tilde@^2.0.0, expand-tilde@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502"
- integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=
- dependencies:
- homedir-polyfill "^1.0.1"
-
-express@^4.15.3, express@^4.8.5:
- version "4.17.1"
- resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
- integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==
- dependencies:
- accepts "~1.3.7"
- array-flatten "1.1.1"
- body-parser "1.19.0"
- content-disposition "0.5.3"
- content-type "~1.0.4"
- cookie "0.4.0"
- cookie-signature "1.0.6"
- debug "2.6.9"
- depd "~1.1.2"
- encodeurl "~1.0.2"
- escape-html "~1.0.3"
- etag "~1.8.1"
- finalhandler "~1.1.2"
- fresh "0.5.2"
- merge-descriptors "1.0.1"
- methods "~1.1.2"
- on-finished "~2.3.0"
- parseurl "~1.3.3"
- path-to-regexp "0.1.7"
- proxy-addr "~2.0.5"
- qs "6.7.0"
- range-parser "~1.2.1"
- safe-buffer "5.1.2"
- send "0.17.1"
- serve-static "1.14.1"
- setprototypeof "1.1.1"
- statuses "~1.5.0"
- type-is "~1.6.18"
- utils-merge "1.0.1"
- vary "~1.1.2"
-
-extend-shallow@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f"
- integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=
- dependencies:
- is-extendable "^0.1.0"
-
-extend-shallow@^3.0.0, extend-shallow@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8"
- integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=
- dependencies:
- assign-symbols "^1.0.0"
- is-extendable "^1.0.1"
-
extend@^3.0.0, extend@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
-extglob@^0.3.1:
- version "0.3.2"
- resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1"
- integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=
- dependencies:
- is-extglob "^1.0.0"
-
-extglob@^2.0.4:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543"
- integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==
- dependencies:
- array-unique "^0.3.2"
- define-property "^1.0.0"
- expand-brackets "^2.1.4"
- extend-shallow "^2.0.1"
- fragment-cache "^0.2.1"
- regex-not "^1.0.0"
- snapdragon "^0.8.1"
- to-regex "^3.0.1"
-
extsprintf@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
@@ -3602,49 +1909,6 @@
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
-fast-safe-stringify@^2.0.4:
- version "2.0.7"
- resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743"
- integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==
-
-fd-slicer@~1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
- integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=
- dependencies:
- pend "~1.2.0"
-
-fecha@^2.3.3:
- version "2.3.3"
- resolved "https://registry.yarnpkg.com/fecha/-/fecha-2.3.3.tgz#948e74157df1a32fd1b12c3a3c3cdcb6ec9d96cd"
- integrity sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==
-
-filename-regex@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
- integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=
-
-fill-range@^2.1.0:
- version "2.2.4"
- resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565"
- integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==
- dependencies:
- is-number "^2.1.0"
- isobject "^2.0.0"
- randomatic "^3.0.0"
- repeat-element "^1.1.2"
- repeat-string "^1.5.2"
-
-fill-range@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7"
- integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=
- dependencies:
- extend-shallow "^2.0.1"
- is-number "^3.0.0"
- repeat-string "^1.6.1"
- to-regex-range "^2.1.0"
-
fill-range@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
@@ -3652,7 +1916,7 @@
dependencies:
to-regex-range "^5.0.1"
-finalhandler@1.1.2, finalhandler@~1.1.2:
+finalhandler@1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d"
integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==
@@ -3665,13 +1929,6 @@
statuses "~1.5.0"
unpipe "~1.0.0"
-find-port@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/find-port/-/find-port-1.0.1.tgz#db084a6cbf99564d99869ae79fbdecf66e8a185c"
- integrity sha1-2whKbL+ZVk2Zhprnn73s9m6KGFw=
- dependencies:
- async "~0.2.9"
-
find-replace@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38"
@@ -3686,14 +1943,6 @@
dependencies:
locate-path "^3.0.0"
-find-up@^1.0.0:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
- integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=
- dependencies:
- path-exists "^2.0.0"
- pinkie-promise "^2.0.0"
-
find-up@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
@@ -3701,21 +1950,6 @@
dependencies:
locate-path "^2.0.0"
-findup-sync@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc"
- integrity sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=
- dependencies:
- detect-file "^1.0.0"
- is-glob "^3.1.0"
- micromatch "^3.0.4"
- resolve-dir "^1.0.1"
-
-first-chunk-stream@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz#59bfb50cd905f60d7c394cd3d9acaab4e6ad934e"
- integrity sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=
-
flat@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2"
@@ -3735,28 +1969,11 @@
dependencies:
debug "^3.0.0"
-for-in@^1.0.1, for-in@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
- integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=
-
-for-own@^0.1.4:
- version "0.1.5"
- resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce"
- integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=
- dependencies:
- for-in "^1.0.1"
-
forever-agent@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
-fork-stream@^0.0.4:
- version "0.0.4"
- resolved "https://registry.yarnpkg.com/fork-stream/-/fork-stream-0.0.4.tgz#db849fce77f6708a5f8f386ae533a0907b54ae70"
- integrity sha1-24Sfznf2cIpfjzhq5TOgkHtUrnA=
-
form-data@~2.3.2:
version "2.3.3"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
@@ -3766,47 +1983,11 @@
combined-stream "^1.0.6"
mime-types "^2.1.12"
-formatio@1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.1.1.tgz#5ed3ccd636551097383465d996199100e86161e9"
- integrity sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=
- dependencies:
- samsam "~1.1"
-
-formatio@1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.2.0.tgz#f3b2167d9068c4698a8d51f4f760a39a54d818eb"
- integrity sha1-87IWfZBoxGmKjVH092CjmlTYGOs=
- dependencies:
- samsam "1.x"
-
-forwarded@~0.1.2:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
- integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=
-
-fragment-cache@^0.2.1:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19"
- integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=
- dependencies:
- map-cache "^0.2.2"
-
-freeport@^1.0.4:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/freeport/-/freeport-1.0.5.tgz#255e8ab84170c33ba85d990e821ae5f4a1a9bc5d"
- integrity sha1-JV6KuEFwwzuoXZkOghrl9KGpvF0=
-
-fresh@0.5.2, fresh@~0.5.2:
+fresh@~0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
-fs-constants@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
- integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
-
fs-extra@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9"
@@ -3846,16 +2027,6 @@
resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41"
integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=
-get-stdin@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
- integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=
-
-get-stream@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
- integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=
-
get-stream@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9"
@@ -3863,11 +2034,6 @@
dependencies:
pump "^3.0.0"
-get-value@^2.0.3, get-value@^2.0.6:
- version "2.0.6"
- resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
- integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=
-
getpass@^0.1.1:
version "0.1.7"
resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
@@ -3875,29 +2041,6 @@
dependencies:
assert-plus "^1.0.0"
-glob-base@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4"
- integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=
- dependencies:
- glob-parent "^2.0.0"
- is-glob "^2.0.0"
-
-glob-parent@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28"
- integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=
- dependencies:
- is-glob "^2.0.0"
-
-glob-parent@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae"
- integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=
- dependencies:
- is-glob "^3.1.0"
- path-dirname "^1.0.0"
-
glob-parent@~5.1.0:
version "5.1.1"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229"
@@ -3905,32 +2048,6 @@
dependencies:
is-glob "^4.0.1"
-glob-stream@^5.3.2:
- version "5.3.5"
- resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-5.3.5.tgz#a55665a9a8ccdc41915a87c701e32d4e016fad22"
- integrity sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=
- dependencies:
- extend "^3.0.0"
- glob "^5.0.3"
- glob-parent "^3.0.0"
- micromatch "^2.3.7"
- ordered-read-streams "^0.3.0"
- through2 "^0.6.0"
- to-absolute-glob "^0.1.1"
- unique-stream "^2.0.2"
-
-glob@7.1.1:
- version "7.1.1"
- resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
- integrity sha1-gFIR3wT6rxxjo2ADBs31reULLsg=
- dependencies:
- fs.realpath "^1.0.0"
- inflight "^1.0.4"
- inherits "2"
- minimatch "^3.0.2"
- once "^1.3.0"
- path-is-absolute "^1.0.0"
-
glob@7.1.3:
version "7.1.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1"
@@ -3943,18 +2060,7 @@
once "^1.3.0"
path-is-absolute "^1.0.0"
-glob@^5.0.3:
- version "5.0.15"
- resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1"
- integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=
- dependencies:
- inflight "^1.0.4"
- inherits "2"
- minimatch "2 || 3"
- once "^1.3.0"
- path-is-absolute "^1.0.0"
-
-glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4:
+glob@^7.1.1, glob@^7.1.3:
version "7.1.6"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
@@ -3966,118 +2072,27 @@
once "^1.3.0"
path-is-absolute "^1.0.0"
-global-dirs@^0.1.0:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445"
- integrity sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=
- dependencies:
- ini "^1.3.4"
-
-global-modules@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea"
- integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==
- dependencies:
- global-prefix "^1.0.1"
- is-windows "^1.0.1"
- resolve-dir "^1.0.0"
-
-global-prefix@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe"
- integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=
- dependencies:
- expand-tilde "^2.0.2"
- homedir-polyfill "^1.0.1"
- ini "^1.3.4"
- is-windows "^1.0.1"
- which "^1.2.14"
-
globals@^11.1.0:
version "11.12.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
-globals@^9.18.0:
- version "9.18.0"
- resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
- integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==
-
-got@^6.7.1:
- version "6.7.1"
- resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0"
- integrity sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=
- dependencies:
- create-error-class "^3.0.0"
- duplexer3 "^0.1.4"
- get-stream "^3.0.0"
- is-redirect "^1.0.0"
- is-retry-allowed "^1.0.0"
- is-stream "^1.0.0"
- lowercase-keys "^1.0.0"
- safe-buffer "^5.0.1"
- timed-out "^4.0.0"
- unzip-response "^2.0.1"
- url-parse-lax "^1.0.0"
-
-graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.2.0:
+graceful-fs@^4.1.2, graceful-fs@^4.1.6:
version "4.2.3"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423"
integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==
-"graceful-readlink@>= 1.0.0":
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
- integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=
-
growl@1.10.5:
version "1.10.5"
resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e"
integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==
-growl@1.9.2:
- version "1.9.2"
- resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f"
- integrity sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=
-
-gulp-if@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/gulp-if/-/gulp-if-2.0.2.tgz#a497b7e7573005041caa2bc8b7dda3c80444d629"
- integrity sha1-pJe351cwBQQcqivIt92jyARE1ik=
- dependencies:
- gulp-match "^1.0.3"
- ternary-stream "^2.0.1"
- through2 "^2.0.1"
-
-gulp-match@^1.0.3:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/gulp-match/-/gulp-match-1.1.0.tgz#552b7080fc006ee752c90563f9fec9d61aafdf4f"
- integrity sha512-DlyVxa1Gj24DitY2OjEsS+X6tDpretuxD6wTfhXE/Rw2hweqc1f6D/XtsJmoiCwLWfXgR87W9ozEityPCVzGtQ==
- dependencies:
- minimatch "^3.0.3"
-
-gulp-sourcemaps@1.6.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz#b86ff349d801ceb56e1d9e7dc7bbcb4b7dee600c"
- integrity sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=
- dependencies:
- convert-source-map "^1.1.1"
- graceful-fs "^4.1.2"
- strip-bom "^2.0.0"
- through2 "^2.0.0"
- vinyl "^1.0.0"
-
-handle-thing@^1.2.5:
- version "1.2.5"
- resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-1.2.5.tgz#fd7aad726bf1a5fd16dfc29b2f7a6601d27139c4"
- integrity sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=
-
har-schema@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
-har-validator@~5.1.0, har-validator@~5.1.3:
+har-validator@~5.1.3:
version "5.1.3"
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080"
integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==
@@ -4085,13 +2100,6 @@
ajv "^6.5.5"
har-schema "^2.0.0"
-has-ansi@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
- integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=
- dependencies:
- ansi-regex "^2.0.0"
-
has-binary2@~1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/has-binary2/-/has-binary2-1.0.3.tgz#7776ac627f3ea77250cfc332dab7ddf5e4f5d11d"
@@ -4099,62 +2107,26 @@
dependencies:
isarray "2.0.1"
-has-color@~0.1.0:
- version "0.1.7"
- resolved "https://registry.yarnpkg.com/has-color/-/has-color-0.1.7.tgz#67144a5260c34fc3cca677d041daf52fe7b78b2f"
- integrity sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=
-
has-cors@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39"
integrity sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=
-has-flag@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
- integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=
-
has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
+has-flag@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
+ integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
+
has-symbols@^1.0.0, has-symbols@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==
-has-value@^0.3.1:
- version "0.3.1"
- resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f"
- integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=
- dependencies:
- get-value "^2.0.3"
- has-values "^0.1.4"
- isobject "^2.0.0"
-
-has-value@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177"
- integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=
- dependencies:
- get-value "^2.0.6"
- has-values "^1.0.0"
- isobject "^3.0.0"
-
-has-values@^0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771"
- integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E=
-
-has-values@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f"
- integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=
- dependencies:
- is-number "^3.0.0"
- kind-of "^4.0.0"
-
has@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
@@ -4162,51 +2134,16 @@
dependencies:
function-bind "^1.1.1"
-he@1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
- integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0=
-
-he@1.2.0, he@1.2.x, he@^1.2.0:
+he@1.2.0, he@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
-homedir-polyfill@^1.0.1:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8"
- integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==
- dependencies:
- parse-passwd "^1.0.0"
-
hosted-git-info@^2.1.4:
version "2.8.5"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.5.tgz#759cfcf2c4d156ade59b0b2dfabddc42a6b9c70c"
integrity sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==
-hpack.js@^2.1.6:
- version "2.1.6"
- resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2"
- integrity sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=
- dependencies:
- inherits "^2.0.1"
- obuf "^1.0.0"
- readable-stream "^2.0.1"
- wbuf "^1.1.0"
-
-html-minifier@^3.5.10:
- version "3.5.21"
- resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.21.tgz#d0040e054730e354db008463593194015212d20c"
- integrity sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==
- dependencies:
- camel-case "3.0.x"
- clean-css "4.2.x"
- commander "2.17.x"
- he "1.2.x"
- param-case "2.1.x"
- relateurl "0.2.x"
- uglify-js "3.4.x"
-
html-minifier@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-4.0.0.tgz#cca9aad8bce1175e02e17a8c33e46d8988889f56"
@@ -4228,11 +2165,6 @@
deep-equal "~1.0.1"
http-errors "~1.7.2"
-http-deceiver@^1.2.7:
- version "1.2.7"
- resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87"
- integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=
-
http-errors@1.7.2:
version "1.7.2"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f"
@@ -4265,17 +2197,7 @@
setprototypeof "1.1.0"
statuses ">= 1.4.0 < 2"
-http-proxy-middleware@^0.17.2:
- version "0.17.4"
- resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.17.4.tgz#642e8848851d66f09d4f124912846dbaeb41b833"
- integrity sha1-ZC6ISIUdZvCdTxJJEoRtuutBuDM=
- dependencies:
- http-proxy "^1.16.2"
- is-glob "^3.1.0"
- lodash "^4.17.2"
- micromatch "^2.3.11"
-
-http-proxy@^1.13.0, http-proxy@^1.16.2:
+http-proxy@^1.13.0:
version "1.18.0"
resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.0.tgz#dbe55f63e75a347db7f3d99974f2692a314a6a3a"
integrity sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==
@@ -4293,22 +2215,6 @@
jsprim "^1.2.2"
sshpk "^1.7.0"
-https-proxy-agent@^2.2.1:
- version "2.2.4"
- resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
- integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
- dependencies:
- agent-base "^4.3.0"
- debug "^3.1.0"
-
-https-proxy-agent@^3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz#b8c286433e87602311b01c8ea34413d856a4af81"
- integrity sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==
- dependencies:
- agent-base "^4.3.0"
- debug "^3.1.0"
-
iconv-lite@0.4.24:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
@@ -4316,33 +2222,6 @@
dependencies:
safer-buffer ">= 2.1.2 < 3"
-ieee754@^1.1.4:
- version "1.1.13"
- resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84"
- integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==
-
-import-lazy@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"
- integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=
-
-imurmurhash@^0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
- integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
-
-indent-string@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80"
- integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=
- dependencies:
- repeating "^2.0.0"
-
-indent@0.0.2:
- version "0.0.2"
- resolved "https://registry.yarnpkg.com/indent/-/indent-0.0.2.tgz#8c79f080190559b687034b84c7aefa97d5a911d9"
- integrity sha1-jHnwgBkFWbaHA0uEx676l9WpEdk=
-
indexof@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d"
@@ -4356,7 +2235,7 @@
once "^1.3.0"
wrappy "1"
-inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3:
+inherits@2, inherits@2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
@@ -4366,11 +2245,6 @@
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
-ini@^1.3.4, ini@~1.3.0:
- version "1.3.5"
- resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
- integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
-
intersection-observer@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/intersection-observer/-/intersection-observer-0.7.0.tgz#ee16bee978db53516ead2f0a8154b09b400bbdc9"
@@ -4383,40 +2257,11 @@
dependencies:
loose-envify "^1.0.0"
-ipaddr.js@1.9.0:
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.0.tgz#37df74e430a0e47550fe54a2defe30d8acd95f65"
- integrity sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==
-
-is-accessor-descriptor@^0.1.6:
- version "0.1.6"
- resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6"
- integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=
- dependencies:
- kind-of "^3.0.2"
-
-is-accessor-descriptor@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656"
- integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==
- dependencies:
- kind-of "^6.0.0"
-
-is-arguments@^1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3"
- integrity sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==
-
is-arrayish@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
-is-arrayish@^0.3.1:
- version "0.3.2"
- resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
- integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
-
is-binary-path@~2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
@@ -4424,11 +2269,6 @@
dependencies:
binary-extensions "^2.0.0"
-is-buffer@^1.1.5, is-buffer@~1.1.1:
- version "1.1.6"
- resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
- integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
-
is-buffer@~2.0.3:
version "2.0.4"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623"
@@ -4439,91 +2279,16 @@
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab"
integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==
-is-ci@^1.0.10:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c"
- integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==
- dependencies:
- ci-info "^1.5.0"
-
-is-data-descriptor@^0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56"
- integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=
- dependencies:
- kind-of "^3.0.2"
-
-is-data-descriptor@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7"
- integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==
- dependencies:
- kind-of "^6.0.0"
-
is-date-object@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e"
integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==
-is-descriptor@^0.1.0:
- version "0.1.6"
- resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca"
- integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==
- dependencies:
- is-accessor-descriptor "^0.1.6"
- is-data-descriptor "^0.1.4"
- kind-of "^5.0.0"
-
-is-descriptor@^1.0.0, is-descriptor@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec"
- integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==
- dependencies:
- is-accessor-descriptor "^1.0.0"
- is-data-descriptor "^1.0.0"
- kind-of "^6.0.2"
-
-is-dotfile@^1.0.0:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1"
- integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=
-
-is-equal-shallow@^0.1.3:
- version "0.1.3"
- resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534"
- integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=
- dependencies:
- is-primitive "^2.0.0"
-
-is-extendable@^0.1.0, is-extendable@^0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89"
- integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=
-
-is-extendable@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4"
- integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==
- dependencies:
- is-plain-object "^2.0.4"
-
-is-extglob@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0"
- integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=
-
-is-extglob@^2.1.0, is-extglob@^2.1.1:
+is-extglob@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
-is-finite@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa"
- integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=
- dependencies:
- number-is-nan "^1.0.0"
-
is-fullwidth-code-point@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
@@ -4534,20 +2299,6 @@
resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.7.tgz#d2132e529bb0000a7f80794d4bdf5cd5e5813522"
integrity sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==
-is-glob@^2.0.0, is-glob@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863"
- integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=
- dependencies:
- is-extglob "^1.0.0"
-
-is-glob@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a"
- integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=
- dependencies:
- is-extglob "^2.1.0"
-
is-glob@^4.0.1, is-glob@~4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
@@ -4555,82 +2306,16 @@
dependencies:
is-extglob "^2.1.1"
-is-installed-globally@^0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80"
- integrity sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=
- dependencies:
- global-dirs "^0.1.0"
- is-path-inside "^1.0.0"
-
is-module@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591"
integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=
-is-npm@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4"
- integrity sha1-8vtjpl5JBbQGyGBydloaTceTufQ=
-
-is-number@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f"
- integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=
- dependencies:
- kind-of "^3.0.2"
-
-is-number@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
- integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=
- dependencies:
- kind-of "^3.0.2"
-
-is-number@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff"
- integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==
-
is-number@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
-is-obj@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
- integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8=
-
-is-path-inside@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036"
- integrity sha1-jvW33lBDej/cprToZe96pVy0gDY=
- dependencies:
- path-is-inside "^1.0.1"
-
-is-plain-object@^2.0.3, is-plain-object@^2.0.4:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
- integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==
- dependencies:
- isobject "^3.0.1"
-
-is-posix-bracket@^0.1.0:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4"
- integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=
-
-is-primitive@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575"
- integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU=
-
-is-redirect@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24"
- integrity sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=
-
is-regex@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae"
@@ -4638,16 +2323,6 @@
dependencies:
has "^1.0.3"
-is-retry-allowed@^1.0.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4"
- integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==
-
-is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
- integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
-
is-stream@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3"
@@ -4665,21 +2340,6 @@
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
-is-utf8@^0.2.0:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
- integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=
-
-is-valid-glob@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-0.3.0.tgz#d4b55c69f51886f9b65c70d6c2622d37e29f48fe"
- integrity sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=
-
-is-windows@^1.0.1, is-windows@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
- integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==
-
is-wsl@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d"
@@ -4690,11 +2350,6 @@
resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
-isarray@1.0.0, isarray@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
- integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
-
isarray@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e"
@@ -4717,18 +2372,6 @@
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
-isobject@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89"
- integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=
- dependencies:
- isarray "1.0.0"
-
-isobject@^3.0.0, isobject@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
- integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
-
isstream@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
@@ -4757,11 +2400,6 @@
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
-js-tokens@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
- integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls=
-
js-yaml@3.13.1:
version "3.13.1"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
@@ -4775,11 +2413,6 @@
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
-jsesc@^1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
- integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s=
-
jsesc@^2.5.1:
version "2.5.2"
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
@@ -4805,28 +2438,11 @@
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
-json-stable-stringify-without-jsonify@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
- integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=
-
json-stringify-safe@~5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
-json3@3.3.2:
- version "3.3.2"
- resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1"
- integrity sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=
-
-json5@^2.1.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.1.tgz#81b6cb04e9ba496f1c7005d07b4368a2638f90b6"
- integrity sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==
- dependencies:
- minimist "^1.2.0"
-
json5@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.2.tgz#43ef1f0af9835dd624751a6b7fa48874fb2d608e"
@@ -4841,11 +2457,6 @@
optionalDependencies:
graceful-fs "^4.1.6"
-jsonschema@^1.1.0, jsonschema@^1.1.1:
- version "1.2.5"
- resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.2.5.tgz#bab69d97fa28946aec0a56a9cc266d23fe80ae61"
- integrity sha512-kVTF+08x25PQ0CjuVc0gRM9EUPb0Fe9Ln/utFOgcdxEIOHuU7ooBk/UPTd7t1M91pP35m0MU1T8M5P7vP1bRRw==
-
jsprim@^1.2.2:
version "1.4.1"
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
@@ -4856,6 +2467,11 @@
json-schema "0.2.3"
verror "1.10.0"
+just-extend@^4.0.2:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-4.1.0.tgz#7278a4027d889601640ee0ce0e5a00b992467da4"
+ integrity sha512-ApcjaOdVTJ7y4r08xI5wIqpvwS48Q0PBG4DJROcEkH1f8MdAiNFyFxz3xoL0LWAVwjrwPYZdVHHxhRHcx/uGLA==
+
karma-chrome-launcher@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-3.1.0.tgz#805a586799a4d05f4e54f72a204979f3f3066738"
@@ -4918,30 +2534,6 @@
dependencies:
tsscmp "1.0.6"
-kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
- version "3.2.2"
- resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
- integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=
- dependencies:
- is-buffer "^1.1.5"
-
-kind-of@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57"
- integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc=
- dependencies:
- is-buffer "^1.1.5"
-
-kind-of@^5.0.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d"
- integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==
-
-kind-of@^6.0.0, kind-of@^6.0.2:
- version "6.0.3"
- resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
- integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
-
koa-compose@^3.0.0:
version "3.2.1"
resolved "https://registry.yarnpkg.com/koa-compose/-/koa-compose-3.2.1.tgz#a85ccb40b7d986d8e5a345b3a1ace8eabcf54de7"
@@ -5033,41 +2625,6 @@
type-is "^1.6.16"
vary "^1.1.2"
-kuler@1.0.x:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/kuler/-/kuler-1.0.1.tgz#ef7c784f36c9fb6e16dd3150d152677b2b0228a6"
- integrity sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==
- dependencies:
- colornames "^1.1.1"
-
-latest-version@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15"
- integrity sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=
- dependencies:
- package-json "^4.0.0"
-
-launchpad@^0.7.0:
- version "0.7.5"
- resolved "https://registry.yarnpkg.com/launchpad/-/launchpad-0.7.5.tgz#a16950c937572f10ef01c9be945a96f7aef8e427"
- integrity sha512-gsYFgT8XKL3X2XZHPPPrgwM0JqeQwGpSWnzg7EYadBY3MirbQrTVq6L4fm6l7UE2T+7gnfuhiGkKr/xxuU/fdw==
- dependencies:
- async "^2.0.1"
- browserstack "^1.2.0"
- debug "^2.2.0"
- mkdirp "^0.5.1"
- plist "^2.0.1"
- q "^1.4.1"
- rimraf "^3.0.0"
- underscore "^1.8.3"
-
-lazystream@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4"
- integrity sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=
- dependencies:
- readable-stream "^2.0.5"
-
leven@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
@@ -5080,17 +2637,6 @@
dependencies:
leven "^3.1.0"
-load-json-file@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
- integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=
- dependencies:
- graceful-fs "^4.1.2"
- parse-json "^2.2.0"
- pify "^2.0.0"
- pinkie-promise "^2.0.0"
- strip-bom "^2.0.0"
-
load-json-file@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b"
@@ -5117,143 +2663,32 @@
p-locate "^3.0.0"
path-exists "^3.0.0"
-lodash._baseassign@^3.0.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e"
- integrity sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=
- dependencies:
- lodash._basecopy "^3.0.0"
- lodash.keys "^3.0.0"
-
-lodash._basecopy@^3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36"
- integrity sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=
-
-lodash._basecreate@^3.0.0:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821"
- integrity sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=
-
-lodash._getnative@^3.0.0:
- version "3.9.1"
- resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
- integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=
-
-lodash._isiterateecall@^3.0.0:
- version "3.0.9"
- resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c"
- integrity sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=
-
-lodash._reinterpolate@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
- integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=
-
lodash.camelcase@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY=
-lodash.create@3.1.1:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7"
- integrity sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=
- dependencies:
- lodash._baseassign "^3.0.0"
- lodash._basecreate "^3.0.0"
- lodash._isiterateecall "^3.0.0"
-
-lodash.defaults@^4.2.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
- integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=
-
-lodash.difference@^4.5.0:
- version "4.5.0"
- resolved "https://registry.yarnpkg.com/lodash.difference/-/lodash.difference-4.5.0.tgz#9ccb4e505d486b91651345772885a2df27fd017c"
- integrity sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=
-
-lodash.flatten@^4.4.0:
- version "4.4.0"
- resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f"
- integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=
-
-lodash.isarguments@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a"
- integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=
-
-lodash.isarray@^3.0.0:
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55"
- integrity sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=
-
-lodash.isequal@^4.0.0:
- version "4.5.0"
- resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
- integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
-
-lodash.isplainobject@^4.0.6:
- version "4.0.6"
- resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
- integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=
-
-lodash.keys@^3.0.0:
- version "3.1.2"
- resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a"
- integrity sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=
- dependencies:
- lodash._getnative "^3.0.0"
- lodash.isarguments "^3.0.0"
- lodash.isarray "^3.0.0"
+lodash.get@^4.4.2:
+ version "4.4.2"
+ resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
+ integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=
lodash.memoize@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=
-lodash.padend@^4.6.1:
- version "4.6.1"
- resolved "https://registry.yarnpkg.com/lodash.padend/-/lodash.padend-4.6.1.tgz#53ccba047d06e158d311f45da625f4e49e6f166e"
- integrity sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=
-
lodash.sortby@^4.7.0:
version "4.7.0"
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=
-lodash.template@^4.4.0:
- version "4.5.0"
- resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab"
- integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==
- dependencies:
- lodash._reinterpolate "^3.0.0"
- lodash.templatesettings "^4.0.0"
-
-lodash.templatesettings@^4.0.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33"
- integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==
- dependencies:
- lodash._reinterpolate "^3.0.0"
-
-lodash.union@^4.6.0:
- version "4.6.0"
- resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88"
- integrity sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=
-
lodash.uniq@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
-lodash@^3.0.0, lodash@^3.10.1:
- version "3.10.1"
- resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
- integrity sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=
-
-lodash@^4.0.0, lodash@^4.16.6, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.2, lodash@^4.17.4:
+lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15:
version "4.17.15"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
@@ -5283,38 +2718,6 @@
rfdc "^1.1.4"
streamroller "^1.0.6"
-logform@^1.9.1:
- version "1.10.0"
- resolved "https://registry.yarnpkg.com/logform/-/logform-1.10.0.tgz#c9d5598714c92b546e23f4e78147c40f1e02012e"
- integrity sha512-em5ojIhU18fIMOw/333mD+ZLE2fis0EzXl1ZwHx4iQzmpQi6odNiY/t+ITNr33JZhT9/KEaH+UPIipr6a9EjWg==
- dependencies:
- colors "^1.2.1"
- fast-safe-stringify "^2.0.4"
- fecha "^2.3.3"
- ms "^2.1.1"
- triple-beam "^1.2.0"
-
-logform@^2.1.1:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/logform/-/logform-2.1.2.tgz#957155ebeb67a13164069825ce67ddb5bb2dd360"
- integrity sha512-+lZh4OpERDBLqjiwDLpAWNQu6KMjnlXH2ByZwCuSqVPJletw0kTWJf5CgSNAUKn1KUkv3m2cUz/LK8zyEy7wzQ==
- dependencies:
- colors "^1.2.1"
- fast-safe-stringify "^2.0.4"
- fecha "^2.3.3"
- ms "^2.1.1"
- triple-beam "^1.3.0"
-
-lolex@1.3.2:
- version "1.3.2"
- resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.3.2.tgz#7c3da62ffcb30f0f5a80a2566ca24e45d8a01f31"
- integrity sha1-fD2mL/yzDw9agKJWbKJORdigHzE=
-
-lolex@^1.6.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.6.0.tgz#3a9a0283452a47d7439e72731b9e07d7386e49f6"
- integrity sha1-OpoCg0UqR9dDnnJzG54H1zhuSfY=
-
loose-envify@^1.0.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
@@ -5322,25 +2725,12 @@
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
-loud-rejection@^1.0.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f"
- integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=
- dependencies:
- currently-unhandled "^0.4.1"
- signal-exit "^3.0.0"
-
lower-case@^1.1.1:
version "1.1.4"
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw=
-lowercase-keys@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
- integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==
-
-lru-cache@4.1.x, lru-cache@^4.0.1, lru-cache@^4.0.2:
+lru-cache@4.1.x:
version "4.1.5"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==
@@ -5355,134 +2745,11 @@
dependencies:
yallist "^3.0.2"
-magic-string@^0.22.4:
- version "0.22.5"
- resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.5.tgz#8e9cf5afddf44385c1da5bc2a6a0dbd10b03657e"
- integrity sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w==
- dependencies:
- vlq "^0.2.2"
-
-make-dir@^1.0.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
- integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==
- dependencies:
- pify "^3.0.0"
-
-map-cache@^0.2.2:
- version "0.2.2"
- resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
- integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=
-
-map-obj@^1.0.0, map-obj@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
- integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=
-
-map-visit@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f"
- integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=
- dependencies:
- object-visit "^1.0.0"
-
-matcher@^1.1.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/matcher/-/matcher-1.1.1.tgz#51d8301e138f840982b338b116bb0c09af62c1c2"
- integrity sha512-+BmqxWIubKTRKNWx/ahnCkk3mG8m7OturVlqq6HiojGJTd5hVYbgZm6WzcYPCoB+KBT4Vd6R7WSRG2OADNaCjg==
- dependencies:
- escape-string-regexp "^1.0.4"
-
-math-random@^1.0.1:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c"
- integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==
-
-md5@^2.2.1:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9"
- integrity sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=
- dependencies:
- charenc "~0.0.1"
- crypt "~0.0.1"
- is-buffer "~1.1.1"
-
media-typer@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
-meow@^3.7.0:
- version "3.7.0"
- resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
- integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=
- dependencies:
- camelcase-keys "^2.0.0"
- decamelize "^1.1.2"
- loud-rejection "^1.0.0"
- map-obj "^1.0.1"
- minimist "^1.1.3"
- normalize-package-data "^2.3.4"
- object-assign "^4.0.1"
- read-pkg-up "^1.0.1"
- redent "^1.0.0"
- trim-newlines "^1.0.0"
-
-merge-descriptors@1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
- integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=
-
-merge-stream@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1"
- integrity sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=
- dependencies:
- readable-stream "^2.0.1"
-
-methods@~1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
- integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
-
-micromatch@^2.3.11, micromatch@^2.3.7:
- version "2.3.11"
- resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565"
- integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=
- dependencies:
- arr-diff "^2.0.0"
- array-unique "^0.2.1"
- braces "^1.8.2"
- expand-brackets "^0.1.4"
- extglob "^0.3.1"
- filename-regex "^2.0.0"
- is-extglob "^1.0.0"
- is-glob "^2.0.1"
- kind-of "^3.0.2"
- normalize-path "^2.0.1"
- object.omit "^2.0.0"
- parse-glob "^3.0.4"
- regex-cache "^0.4.2"
-
-micromatch@^3.0.4:
- version "3.1.10"
- resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
- integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==
- dependencies:
- arr-diff "^4.0.0"
- array-unique "^0.3.2"
- braces "^2.3.1"
- define-property "^2.0.2"
- extend-shallow "^3.0.2"
- extglob "^2.0.4"
- fragment-cache "^0.2.1"
- kind-of "^6.0.2"
- nanomatch "^1.2.9"
- object.pick "^1.3.0"
- regex-not "^1.0.0"
- snapdragon "^0.8.1"
- to-regex "^3.0.2"
-
mime-db@1.43.0, "mime-db@>= 1.43.0 < 2":
version "1.43.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58"
@@ -5495,34 +2762,12 @@
dependencies:
mime-db "1.43.0"
-mime@1.4.1:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
- integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==
-
-mime@1.6.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
- integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
-
mime@^2.3.1:
version "2.4.4"
resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5"
integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==
-minimalistic-assert@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
- integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==
-
-minimatch-all@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/minimatch-all/-/minimatch-all-1.1.0.tgz#40c496a27a2e128d19bf758e76bb01a0c7145787"
- integrity sha1-QMSWonouEo0Zv3WOdrsBoMcUV4c=
- dependencies:
- minimatch "^3.0.2"
-
-"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4:
+minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
@@ -5534,11 +2779,6 @@
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
-minimist@^1.1.3, minimist@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
- integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
-
minimist@^1.2.3, minimist@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
@@ -5549,21 +2789,6 @@
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=
-mixin-deep@^1.2.0:
- version "1.3.2"
- resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566"
- integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==
- dependencies:
- for-in "^1.0.2"
- is-extendable "^1.0.1"
-
-mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1:
- version "0.5.1"
- resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
- integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
- dependencies:
- minimist "0.0.8"
-
mkdirp@0.5.3:
version "0.5.3"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.3.tgz#5a514b7179259287952881e94410ec5465659f8c"
@@ -5571,23 +2796,12 @@
dependencies:
minimist "^1.2.5"
-mocha@^3.4.2:
- version "3.5.3"
- resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.5.3.tgz#1e0480fe36d2da5858d1eb6acc38418b26eaa20d"
- integrity sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==
+mkdirp@^0.5.1:
+ version "0.5.1"
+ resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
+ integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
dependencies:
- browser-stdout "1.3.0"
- commander "2.9.0"
- debug "2.6.8"
- diff "3.2.0"
- escape-string-regexp "1.0.5"
- glob "7.1.1"
- growl "1.9.2"
- he "1.1.1"
- json3 "3.3.2"
- lodash.create "3.1.1"
- mkdirp "0.5.1"
- supports-color "3.1.2"
+ minimist "0.0.8"
mocha@^7.1.1:
version "7.1.1"
@@ -5619,11 +2833,6 @@
yargs-parser "13.1.2"
yargs-unparser "1.6.0"
-mout@^1.0.0:
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/mout/-/mout-1.2.2.tgz#c9b718a499806a0632cede178e80f436259e777d"
- integrity sha512-w0OUxFEla6z3d7sVpMZGBCpQvYh8PHS1wZ6Wu9GNKHMpAHWJ0if0LsQZh3DlOqw55HlhJEOMLpFnwtxp99Y5GA==
-
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
@@ -5639,29 +2848,7 @@
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
-multer@^1.3.0:
- version "1.4.2"
- resolved "https://registry.yarnpkg.com/multer/-/multer-1.4.2.tgz#2f1f4d12dbaeeba74cb37e623f234bf4d3d2057a"
- integrity sha512-xY8pX7V+ybyUpbYMxtjM9KAiD9ixtg5/JkeKUTD6xilfDv0vzzOFcCp4Ljb1UU3tSOM3VTZtKo63OmzOrGi3Cg==
- dependencies:
- append-field "^1.0.0"
- busboy "^0.2.11"
- concat-stream "^1.5.2"
- mkdirp "^0.5.1"
- object-assign "^4.1.1"
- on-finished "^2.3.0"
- type-is "^1.6.4"
- xtend "^4.0.0"
-
-multipipe@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-1.0.2.tgz#cc13efd833c9cda99f224f868461b8e1a3fd939d"
- integrity sha1-zBPv2DPJzamfIk+GhGG44aP9k50=
- dependencies:
- duplexer2 "^0.1.2"
- object-assign "^4.1.0"
-
-mz@^2.1.0, mz@^2.4.0, mz@^2.6.0, mz@^2.7.0:
+mz@^2.1.0, mz@^2.7.0:
version "2.7.0"
resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32"
integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==
@@ -5670,37 +2857,21 @@
object-assign "^4.0.1"
thenify-all "^1.0.0"
-nanomatch@^1.2.9:
- version "1.2.13"
- resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
- integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==
- dependencies:
- arr-diff "^4.0.0"
- array-unique "^0.3.2"
- define-property "^2.0.2"
- extend-shallow "^3.0.2"
- fragment-cache "^0.2.1"
- is-windows "^1.0.2"
- kind-of "^6.0.2"
- object.pick "^1.3.0"
- regex-not "^1.0.0"
- snapdragon "^0.8.1"
- to-regex "^3.0.1"
-
-native-promise-only@^0.8.1:
- version "0.8.1"
- resolved "https://registry.yarnpkg.com/native-promise-only/-/native-promise-only-0.8.1.tgz#20a318c30cb45f71fe7adfbf7b21c99c1472ef11"
- integrity sha1-IKMYwwy0X3H+et+/eyHJnBRy7xE=
-
negotiator@0.6.2:
version "0.6.2"
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
-nice-try@^1.0.4:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
- integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
+nise@^4.0.1:
+ version "4.0.4"
+ resolved "https://registry.yarnpkg.com/nise/-/nise-4.0.4.tgz#d73dea3e5731e6561992b8f570be9e363c4512dd"
+ integrity sha512-bTTRUNlemx6deJa+ZyoCUTRvH3liK5+N6VQZ4NIw90AgDXY6iPnsqplNFf6STcj+ePk0H/xqxnP75Lr0J0Fq3A==
+ dependencies:
+ "@sinonjs/commons" "^1.7.0"
+ "@sinonjs/fake-timers" "^6.0.0"
+ "@sinonjs/text-encoding" "^0.7.1"
+ just-extend "^4.0.2"
+ path-to-regexp "^1.7.0"
no-case@^2.2.0:
version "2.3.2"
@@ -5727,15 +2898,7 @@
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.53.tgz#2d821bfa499ed7c5dffc5e2f28c88e78a08ee3f4"
integrity sha512-wp8zyQVwef2hpZ/dJH7SfSrIPD6YoJz6BDQDpGEkcA0s3LpAQoxBIYmfIq6QAhC1DhwsyCgTaTTcONwX8qzCuQ==
-nomnom@^1.8.1:
- version "1.8.1"
- resolved "https://registry.yarnpkg.com/nomnom/-/nomnom-1.8.1.tgz#2151f722472ba79e50a76fc125bb8c8f2e4dc2a7"
- integrity sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=
- dependencies:
- chalk "~0.4.0"
- underscore "~1.6.0"
-
-normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
+normalize-package-data@^2.3.2:
version "2.5.0"
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==
@@ -5745,36 +2908,17 @@
semver "2 || 3 || 4 || 5"
validate-npm-package-license "^3.0.1"
-normalize-path@^2.0.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
- integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=
- dependencies:
- remove-trailing-separator "^1.0.1"
-
normalize-path@^3.0.0, normalize-path@~3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
-npm-run-path@^2.0.0:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
- integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=
- dependencies:
- path-key "^2.0.0"
-
-number-is-nan@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
- integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
-
oauth-sign@~0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
-object-assign@^4, object-assign@^4.0.0, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
+object-assign@^4.0.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
@@ -5784,15 +2928,6 @@
resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291"
integrity sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=
-object-copy@^0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c"
- integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw=
- dependencies:
- copy-descriptor "^0.1.0"
- define-property "^0.2.5"
- kind-of "^3.0.3"
-
object-inspect@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67"
@@ -5803,13 +2938,6 @@
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
-object-visit@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb"
- integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=
- dependencies:
- isobject "^3.0.0"
-
object.assign@4.1.0, object.assign@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da"
@@ -5820,16 +2948,6 @@
has-symbols "^1.0.0"
object-keys "^1.0.11"
-object.entries@^1.1.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.1.tgz#ee1cf04153de02bb093fec33683900f57ce5399b"
- integrity sha512-ilqR7BgdyZetJutmDPfXCDffGa0/Yzl2ivVNpbx/g4UeWrCdRnFDUBrKJGLhGieRHDATnyZXWBeCb29k9CJysQ==
- dependencies:
- define-properties "^1.1.3"
- es-abstract "^1.17.0-next.1"
- function-bind "^1.1.1"
- has "^1.0.3"
-
object.getownpropertydescriptors@^2.0.3:
version "2.1.0"
resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649"
@@ -5838,26 +2956,6 @@
define-properties "^1.1.3"
es-abstract "^1.17.0-next.1"
-object.omit@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa"
- integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=
- dependencies:
- for-own "^0.1.4"
- is-extendable "^0.1.1"
-
-object.pick@^1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747"
- integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=
- dependencies:
- isobject "^3.0.1"
-
-obuf@^1.0.0, obuf@^1.1.1:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e"
- integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==
-
on-finished@^2.3.0, on-finished@~2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
@@ -5865,11 +2963,6 @@
dependencies:
ee-first "1.1.1"
-on-headers@~1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f"
- integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==
-
once@^1.3.0, once@^1.3.1, once@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
@@ -5877,23 +2970,11 @@
dependencies:
wrappy "1"
-one-time@0.0.4:
- version "0.0.4"
- resolved "https://registry.yarnpkg.com/one-time/-/one-time-0.0.4.tgz#f8cdf77884826fe4dff93e3a9cc37b1e4480742e"
- integrity sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=
-
only@~0.0.2:
version "0.0.2"
resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4"
integrity sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q=
-opn@^3.0.2:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/opn/-/opn-3.0.3.tgz#b6d99e7399f78d65c3baaffef1fb288e9b85243a"
- integrity sha1-ttmec5n3jWXDuq/+8fsojpuFJDo=
- dependencies:
- object-assign "^4.0.1"
-
opn@^5.4.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc"
@@ -5909,37 +2990,11 @@
minimist "~0.0.1"
wordwrap "~0.0.2"
-ordered-read-streams@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz#7137e69b3298bb342247a1bbee3881c80e2fd78b"
- integrity sha1-cTfmmzKYuzQiR6G77jiByA4v14s=
- dependencies:
- is-stream "^1.0.1"
- readable-stream "^2.0.1"
-
-os-homedir@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
- integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M=
-
-os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2:
+os-tmpdir@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
-osenv@^0.1.3:
- version "0.1.5"
- resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
- integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==
- dependencies:
- os-homedir "^1.0.0"
- os-tmpdir "^1.0.0"
-
-p-finally@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
- integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=
-
p-limit@^1.1.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8"
@@ -5978,40 +3033,13 @@
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
-package-json@^4.0.0:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed"
- integrity sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=
- dependencies:
- got "^6.7.1"
- registry-auth-token "^3.0.1"
- registry-url "^3.0.3"
- semver "^5.1.0"
-
-param-case@2.1.x, param-case@^2.1.1:
+param-case@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247"
integrity sha1-35T9jPZTHs915r75oIWPvHK+Ikc=
dependencies:
no-case "^2.2.0"
-parse-glob@^3.0.4:
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c"
- integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw=
- dependencies:
- glob-base "^0.3.0"
- is-dotfile "^1.0.0"
- is-extglob "^1.0.0"
- is-glob "^2.0.0"
-
-parse-json@^2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
- integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=
- dependencies:
- error-ex "^1.2.0"
-
parse-json@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0"
@@ -6020,16 +3048,6 @@
error-ex "^1.3.1"
json-parse-better-errors "^1.0.1"
-parse-passwd@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
- integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=
-
-parse5@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608"
- integrity sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==
-
parse5@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178"
@@ -6054,23 +3072,6 @@
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
-pascalcase@^0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
- integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=
-
-path-dirname@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0"
- integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=
-
-path-exists@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
- integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=
- dependencies:
- pinkie-promise "^2.0.0"
-
path-exists@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
@@ -6081,42 +3082,23 @@
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
-path-is-inside@^1.0.1, path-is-inside@^1.0.2:
+path-is-inside@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=
-path-key@^2.0.0, path-key@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
- integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
-
path-parse@^1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
-path-to-regexp@0.1.7:
- version "0.1.7"
- resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
- integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
-
-path-to-regexp@^1.0.1, path-to-regexp@^1.7.0:
+path-to-regexp@^1.7.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a"
integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==
dependencies:
isarray "0.0.1"
-path-type@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
- integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=
- dependencies:
- graceful-fs "^4.1.2"
- pify "^2.0.0"
- pinkie-promise "^2.0.0"
-
path-type@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
@@ -6129,21 +3111,6 @@
resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0"
integrity sha1-uULm1L3mUwBe9rcTYd74cn0GReA=
-pem@^1.8.3:
- version "1.14.3"
- resolved "https://registry.yarnpkg.com/pem/-/pem-1.14.3.tgz#347e5a5c194a5f7612b88083e45042fcc4fb4901"
- integrity sha512-Q+AMVMD3fzeVvZs5PHeI+pVt0hgZY2fjhkliBW43qyONLgCXPVk1ryim43F9eupHlNGLJNT5T/NNrzhUdiC5Zg==
- dependencies:
- es6-promisify "^6.0.0"
- md5 "^2.2.1"
- os-tmpdir "^1.0.1"
- which "^1.3.1"
-
-pend@~1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
- integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA=
-
performance-now@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
@@ -6154,28 +3121,11 @@
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad"
integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==
-pify@^2.0.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
- integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
-
pify@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=
-pinkie-promise@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
- integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o=
- dependencies:
- pinkie "^2.0.0"
-
-pinkie@^2.0.0:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
- integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
-
pkg-up@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f"
@@ -6183,24 +3133,6 @@
dependencies:
find-up "^2.1.0"
-plist@^2.0.1:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/plist/-/plist-2.1.0.tgz#57ccdb7a0821df21831217a3cad54e3e146a1025"
- integrity sha1-V8zbeggh3yGDEhejytVOPhRqECU=
- dependencies:
- base64-js "1.2.0"
- xmlbuilder "8.2.2"
- xmldom "0.1.x"
-
-plylog@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/plylog/-/plylog-1.1.0.tgz#f6f354e2ae0b01f6db4ed111f4b3855da9c37417"
- integrity sha512-/QnY5aSVaP54va6hruzNtAj02HpsLlAt7V5EndMrtq6ZUTZJKUja43rgiUtGXqm95yrSJjbZoPW0yQQQwLpoJA==
- dependencies:
- logform "^1.9.1"
- winston "^3.0.0"
- winston-transport "^4.2.0"
-
polyfills-loader@^1.5.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/polyfills-loader/-/polyfills-loader-1.5.2.tgz#2fe63063da0d74aa69b611bd189d64ee443358c7"
@@ -6223,195 +3155,6 @@
terser "^4.6.4"
whatwg-fetch "^3.0.0"
-polymer-analyzer@^3.1.3, polymer-analyzer@^3.2.2:
- version "3.2.4"
- resolved "https://registry.yarnpkg.com/polymer-analyzer/-/polymer-analyzer-3.2.4.tgz#7d76356620a2328e8bc9e30e47069f9729260ca1"
- integrity sha512-JmxUhMajTuC18tLXbTtu2+aN2x9bTX+4MvCD4IZKJ0rtAL8jWi1iRLfogpHJB4Ig9Dc8EEEuEYipLuzPFl3vqA==
- dependencies:
- "@babel/generator" "^7.0.0-beta.42"
- "@babel/traverse" "^7.0.0-beta.42"
- "@babel/types" "^7.0.0-beta.42"
- "@types/babel-generator" "^6.25.1"
- "@types/babel-traverse" "^6.25.2"
- "@types/babel-types" "^6.25.1"
- "@types/babylon" "^6.16.2"
- "@types/chai-subset" "^1.3.0"
- "@types/chalk" "^0.4.30"
- "@types/clone" "^0.1.30"
- "@types/cssbeautify" "^0.3.1"
- "@types/doctrine" "^0.0.1"
- "@types/is-windows" "^0.2.0"
- "@types/minimatch" "^3.0.1"
- "@types/parse5" "^2.2.34"
- "@types/path-is-inside" "^1.0.0"
- "@types/resolve" "0.0.6"
- "@types/whatwg-url" "^6.4.0"
- babylon "^7.0.0-beta.42"
- cancel-token "^0.1.1"
- chalk "^1.1.3"
- clone "^2.0.0"
- cssbeautify "^0.3.1"
- doctrine "^2.0.2"
- dom5 "^3.0.0"
- indent "0.0.2"
- is-windows "^1.0.2"
- jsonschema "^1.1.0"
- minimatch "^3.0.4"
- parse5 "^4.0.0"
- path-is-inside "^1.0.2"
- resolve "^1.5.0"
- shady-css-parser "^0.1.0"
- stable "^0.1.6"
- strip-indent "^2.0.0"
- vscode-uri "=1.0.6"
- whatwg-url "^6.4.0"
-
-polymer-build@^3.1.0:
- version "3.1.4"
- resolved "https://registry.yarnpkg.com/polymer-build/-/polymer-build-3.1.4.tgz#ab539f1a13d803518b13b73ffd09198431d98142"
- integrity sha512-OhTOPG5Y/tK2HqGZ5XA/CVDh+TuOaDv7wTZWXDCg6hxeMgNKuljDMn2coyGU5NLM0pLbS+gwFAc2ZJ5cWHCHNg==
- dependencies:
- "@babel/core" "^7.0.0"
- "@babel/plugin-external-helpers" "^7.0.0"
- "@babel/plugin-proposal-async-generator-functions" "^7.0.0"
- "@babel/plugin-proposal-object-rest-spread" "^7.0.0"
- "@babel/plugin-syntax-async-generators" "^7.0.0"
- "@babel/plugin-syntax-dynamic-import" "^7.0.0"
- "@babel/plugin-syntax-import-meta" "^7.0.0"
- "@babel/plugin-syntax-object-rest-spread" "^7.0.0"
- "@babel/plugin-transform-arrow-functions" "^7.0.0"
- "@babel/plugin-transform-async-to-generator" "^7.0.0"
- "@babel/plugin-transform-block-scoped-functions" "^7.0.0"
- "@babel/plugin-transform-block-scoping" "^7.0.0"
- "@babel/plugin-transform-classes" "^7.0.0"
- "@babel/plugin-transform-computed-properties" "^7.0.0"
- "@babel/plugin-transform-destructuring" "^7.0.0"
- "@babel/plugin-transform-duplicate-keys" "^7.0.0"
- "@babel/plugin-transform-exponentiation-operator" "^7.0.0"
- "@babel/plugin-transform-for-of" "^7.0.0"
- "@babel/plugin-transform-function-name" "^7.0.0"
- "@babel/plugin-transform-instanceof" "^7.0.0"
- "@babel/plugin-transform-literals" "^7.0.0"
- "@babel/plugin-transform-modules-amd" "^7.0.0"
- "@babel/plugin-transform-object-super" "^7.0.0"
- "@babel/plugin-transform-parameters" "^7.0.0"
- "@babel/plugin-transform-regenerator" "^7.0.0"
- "@babel/plugin-transform-shorthand-properties" "^7.0.0"
- "@babel/plugin-transform-spread" "^7.0.0"
- "@babel/plugin-transform-sticky-regex" "^7.0.0"
- "@babel/plugin-transform-template-literals" "^7.0.0"
- "@babel/plugin-transform-typeof-symbol" "^7.0.0"
- "@babel/plugin-transform-unicode-regex" "^7.0.0"
- "@babel/traverse" "^7.0.0"
- "@polymer/esm-amd-loader" "^1.0.0"
- "@types/babel-types" "^6.25.1"
- "@types/babylon" "^6.16.2"
- "@types/gulp-if" "0.0.33"
- "@types/html-minifier" "^3.5.1"
- "@types/is-windows" "^0.2.0"
- "@types/mz" "0.0.31"
- "@types/parse5" "^2.2.34"
- "@types/resolve" "0.0.7"
- "@types/uuid" "^3.4.3"
- "@types/vinyl" "^2.0.0"
- "@types/vinyl-fs" "^2.4.8"
- babel-plugin-minify-guarded-expressions "^0.4.3"
- babel-preset-minify "^0.5.0"
- babylon "^7.0.0-beta.42"
- css-slam "^2.1.2"
- dom5 "^3.0.0"
- gulp-if "^2.0.2"
- html-minifier "^3.5.10"
- matcher "^1.1.0"
- multipipe "^1.0.2"
- mz "^2.6.0"
- parse5 "^4.0.0"
- plylog "^1.0.0"
- polymer-analyzer "^3.1.3"
- polymer-bundler "^4.0.9"
- polymer-project-config "^4.0.3"
- regenerator-runtime "^0.11.1"
- stream "0.0.2"
- sw-precache "^5.1.1"
- uuid "^3.2.1"
- vinyl "^1.2.0"
- vinyl-fs "^2.4.4"
-
-polymer-bundler@^4.0.9:
- version "4.0.10"
- resolved "https://registry.yarnpkg.com/polymer-bundler/-/polymer-bundler-4.0.10.tgz#abc8d33977652f031068d034c8104841e80d4cbb"
- integrity sha512-nwlN3LQlQDqbZ2sUH3394C/dHZUDHq8tpdS5HARvPDb0Q9IXWD+znOR1cr7wSjF0EZN4LiUH5hWyUoV4QSjhpQ==
- dependencies:
- "@types/babel-generator" "^6.25.1"
- "@types/babel-traverse" "^6.25.3"
- babel-generator "^6.26.1"
- babel-traverse "^6.26.0"
- babel-types "^6.26.0"
- clone "^2.1.0"
- command-line-args "^5.0.2"
- command-line-usage "^5.0.5"
- dom5 "^3.0.0"
- espree "^3.5.2"
- magic-string "^0.22.4"
- mkdirp "^0.5.1"
- parse5 "^4.0.0"
- polymer-analyzer "^3.2.2"
- rollup "^1.3.0"
- source-map "^0.5.6"
- vscode-uri "=1.0.6"
-
-polymer-project-config@^4.0.0, polymer-project-config@^4.0.3:
- version "4.0.3"
- resolved "https://registry.yarnpkg.com/polymer-project-config/-/polymer-project-config-4.0.3.tgz#ef0c1a676ce4809907986c8e910745660de8024f"
- integrity sha512-Drr+Imq+znhBC8XSt9pMlmPixoGnIOmleV5SD6mto1zOGC5oCDbSNsQL2v89DWOk+9aSUO79vnWwOmEPDSvYfw==
- dependencies:
- "@types/parse5" "^2.2.34"
- browser-capabilities "^1.0.0"
- jsonschema "^1.1.1"
- minimatch-all "^1.1.0"
- plylog "^1.0.0"
- winston "^3.0.0"
-
-polyserve@^0.27.13:
- version "0.27.15"
- resolved "https://registry.yarnpkg.com/polyserve/-/polyserve-0.27.15.tgz#261fa5a0873c8d95fd7068598f44c9dac20cf9c4"
- integrity sha512-AaFgANt+tUUVgHLw+BnaVYcn649JiwL1ru0TOZUKj1gGGn/Bq2S16gxql+1muGpRaAsgFu13Zu7k5XkwatwwSg==
- dependencies:
- "@types/compression" "^0.0.33"
- "@types/content-type" "^1.1.0"
- "@types/escape-html" "0.0.20"
- "@types/express" "^4.0.36"
- "@types/mime" "^2.0.0"
- "@types/mz" "0.0.29"
- "@types/opn" "^3.0.28"
- "@types/parse5" "^2.2.34"
- "@types/pem" "^1.8.1"
- "@types/resolve" "0.0.6"
- "@types/serve-static" "^1.7.31"
- "@types/spdy" "^3.4.1"
- bower-config "^1.4.1"
- browser-capabilities "^1.0.0"
- command-line-args "^5.0.2"
- command-line-usage "^5.0.5"
- compression "^1.6.2"
- content-type "^1.0.2"
- cors "^2.8.4"
- escape-html "^1.0.3"
- express "^4.8.5"
- find-port "^1.0.1"
- http-proxy-middleware "^0.17.2"
- lru-cache "^4.0.2"
- mime "^2.3.1"
- mz "^2.4.0"
- opn "^3.0.2"
- pem "^1.8.3"
- polymer-build "^3.1.0"
- polymer-project-config "^4.0.0"
- requirejs "^2.3.4"
- resolve "^1.5.0"
- send "^0.16.2"
- spdy "^3.3.3"
-
portfinder@^1.0.21:
version "1.0.25"
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.25.tgz#254fd337ffba869f4b9d37edc298059cb4d35eca"
@@ -6421,59 +3164,16 @@
debug "^3.1.1"
mkdirp "^0.5.1"
-posix-character-classes@^0.1.0:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
- integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=
-
-prepend-http@^1.0.1:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
- integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=
-
-preserve@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
- integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=
-
-pretty-bytes@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-4.0.2.tgz#b2bf82e7350d65c6c33aa95aaa5a4f6327f61cd9"
- integrity sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk=
-
-private@^0.1.6, private@^0.1.8:
+private@^0.1.8:
version "0.1.8"
resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==
-process-nextick-args@~2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
- integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
-
-progress@2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
- integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
-
-proxy-addr@~2.0.5:
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.5.tgz#34cbd64a2d81f4b1fd21e76f9f06c8a45299ee34"
- integrity sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==
- dependencies:
- forwarded "~0.1.2"
- ipaddr.js "1.9.0"
-
pseudomap@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
-psl@^1.1.24:
- version "1.7.0"
- resolved "https://registry.yarnpkg.com/psl/-/psl-1.7.0.tgz#f1c4c47a8ef97167dea5d6bbf4816d736e884a3c"
- integrity sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==
-
psl@^1.1.28:
version "1.8.0"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
@@ -6487,21 +3187,11 @@
end-of-stream "^1.1.0"
once "^1.3.1"
-punycode@^1.4.1:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
- integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
-
punycode@^2.1.0, punycode@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
-q@^1.4.1, q@^1.5.1:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
- integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=
-
qjobs@^1.1.4:
version "1.2.0"
resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071"
@@ -6517,16 +3207,7 @@
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
-randomatic@^3.0.0:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed"
- integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==
- dependencies:
- is-number "^4.0.0"
- kind-of "^6.0.0"
- math-random "^1.0.1"
-
-range-parser@^1.2.0, range-parser@~1.2.0, range-parser@~1.2.1:
+range-parser@^1.2.0:
version "1.2.1"
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
@@ -6541,24 +3222,6 @@
iconv-lite "0.4.24"
unpipe "1.0.0"
-rc@^1.0.1, rc@^1.1.6:
- version "1.2.8"
- resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
- integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
- dependencies:
- deep-extend "^0.6.0"
- ini "~1.3.0"
- minimist "^1.2.0"
- strip-json-comments "~2.0.1"
-
-read-pkg-up@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
- integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=
- dependencies:
- find-up "^1.0.0"
- read-pkg "^1.0.0"
-
read-pkg-up@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-4.0.0.tgz#1b221c6088ba7799601c808f91161c66e58f8978"
@@ -6567,15 +3230,6 @@
find-up "^3.0.0"
read-pkg "^3.0.0"
-read-pkg@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
- integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=
- dependencies:
- load-json-file "^1.0.0"
- normalize-package-data "^2.3.2"
- path-type "^1.0.0"
-
read-pkg@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389"
@@ -6585,48 +3239,6 @@
normalize-package-data "^2.3.2"
path-type "^3.0.0"
-readable-stream@1.1.x:
- version "1.1.14"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
- integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk=
- dependencies:
- core-util-is "~1.0.0"
- inherits "~2.0.1"
- isarray "0.0.1"
- string_decoder "~0.10.x"
-
-"readable-stream@>=1.0.33-1 <1.1.0-0":
- version "1.0.34"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c"
- integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=
- dependencies:
- core-util-is "~1.0.0"
- inherits "~2.0.1"
- isarray "0.0.1"
- string_decoder "~0.10.x"
-
-readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6:
- version "2.3.7"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
- integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
- dependencies:
- core-util-is "~1.0.0"
- inherits "~2.0.3"
- isarray "~1.0.0"
- process-nextick-args "~2.0.0"
- safe-buffer "~5.1.1"
- string_decoder "~1.1.1"
- util-deprecate "~1.0.1"
-
-readable-stream@^3.0.1, readable-stream@^3.1.1, readable-stream@^3.4.0:
- version "3.5.0"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.5.0.tgz#465d70e6d1087f6162d079cd0b5db7fbebfd1606"
- integrity sha512-gSz026xs2LfxBPudDuI41V1lka8cxg64E66SGe78zJlsUofOg/yqwezdIcdfwik6B4h8LFmWPA9ef9X3FiNFLA==
- dependencies:
- inherits "^2.0.3"
- string_decoder "^1.1.1"
- util-deprecate "^1.0.1"
-
readdirp@~3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.2.0.tgz#c30c33352b12c96dfb4b895421a49fd5a9593839"
@@ -6641,19 +3253,6 @@
dependencies:
picomatch "^2.0.7"
-redent@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
- integrity sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=
- dependencies:
- indent-string "^2.1.0"
- strip-indent "^1.0.1"
-
-reduce-flatten@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-1.0.1.tgz#258c78efd153ddf93cb561237f61184f3696e327"
- integrity sha1-JYx479FT3fk8tWEjf2EYTzaW4yc=
-
reduce-flatten@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27"
@@ -6678,23 +3277,11 @@
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11"
integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==
-regenerator-runtime@^0.11.0, regenerator-runtime@^0.11.1:
- version "0.11.1"
- resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
- integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
-
regenerator-runtime@^0.13.3, regenerator-runtime@^0.13.4:
version "0.13.5"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697"
integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==
-regenerator-transform@^0.14.0:
- version "0.14.1"
- resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb"
- integrity sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==
- dependencies:
- private "^0.1.6"
-
regenerator-transform@^0.14.2:
version "0.14.4"
resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.4.tgz#5266857896518d1616a78a0479337a30ea974cc7"
@@ -6703,21 +3290,6 @@
"@babel/runtime" "^7.8.4"
private "^0.1.8"
-regex-cache@^0.4.2:
- version "0.4.4"
- resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd"
- integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==
- dependencies:
- is-equal-shallow "^0.1.3"
-
-regex-not@^1.0.0, regex-not@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c"
- integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==
- dependencies:
- extend-shallow "^3.0.2"
- safe-regex "^1.1.0"
-
regexpu-core@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.6.0.tgz#2037c18b327cfce8a6fea2a4ec441f2432afb8b6"
@@ -6742,21 +3314,6 @@
unicode-match-property-ecmascript "^1.0.4"
unicode-match-property-value-ecmascript "^1.2.0"
-registry-auth-token@^3.0.1:
- version "3.4.0"
- resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.4.0.tgz#d7446815433f5d5ed6431cd5dca21048f66b397e"
- integrity sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==
- dependencies:
- rc "^1.1.6"
- safe-buffer "^5.0.1"
-
-registry-url@^3.0.3:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942"
- integrity sha1-PU74cPc93h138M+aOBQyRE4XSUI=
- dependencies:
- rc "^1.0.1"
-
regjsgen@^0.5.0, regjsgen@^0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.1.tgz#48f0bf1a5ea205196929c0d9798b42d1ed98443c"
@@ -6776,64 +3333,11 @@
dependencies:
jsesc "~0.5.0"
-relateurl@0.2.x, relateurl@^0.2.7:
+relateurl@^0.2.7:
version "0.2.7"
resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9"
integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=
-remove-trailing-separator@^1.0.1:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
- integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8=
-
-repeat-element@^1.1.2:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce"
- integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==
-
-repeat-string@^1.5.2, repeat-string@^1.6.1:
- version "1.6.1"
- resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
- integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc=
-
-repeating@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
- integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=
- dependencies:
- is-finite "^1.0.0"
-
-replace-ext@0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924"
- integrity sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=
-
-request@2.88.0, request@^2.85.0:
- version "2.88.0"
- resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef"
- integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==
- dependencies:
- aws-sign2 "~0.7.0"
- aws4 "^1.8.0"
- caseless "~0.12.0"
- combined-stream "~1.0.6"
- extend "~3.0.2"
- forever-agent "~0.6.1"
- form-data "~2.3.2"
- har-validator "~5.1.0"
- http-signature "~1.2.0"
- is-typedarray "~1.0.0"
- isstream "~0.1.2"
- json-stringify-safe "~5.0.1"
- mime-types "~2.1.19"
- oauth-sign "~0.9.0"
- performance-now "^2.1.0"
- qs "~6.5.2"
- safe-buffer "^5.1.2"
- tough-cookie "~2.4.3"
- tunnel-agent "^0.6.0"
- uuid "^3.3.2"
-
request@^2.88.0:
version "2.88.2"
resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
@@ -6870,11 +3374,6 @@
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
-requirejs@^2.3.4:
- version "2.3.6"
- resolved "https://registry.yarnpkg.com/requirejs/-/requirejs-2.3.6.tgz#e5093d9601c2829251258c0b9445d4d19fa9e7c9"
- integrity sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==
-
requires-port@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
@@ -6885,14 +3384,6 @@
resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
-resolve-dir@^1.0.0, resolve-dir@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43"
- integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=
- dependencies:
- expand-tilde "^2.0.0"
- global-modules "^1.0.0"
-
resolve-path@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/resolve-path/-/resolve-path-1.4.0.tgz#c4bda9f5efb2fce65247873ab36bb4d834fe16f7"
@@ -6901,12 +3392,7 @@
http-errors "~1.6.2"
path-is-absolute "1.0.1"
-resolve-url@^0.2.1:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
- integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
-
-resolve@^1.10.0, resolve@^1.3.2, resolve@^1.5.0:
+resolve@^1.10.0, resolve@^1.3.2:
version "1.15.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.0.tgz#1b7ca96073ebb52e741ffd799f6b39ea462c67f5"
integrity sha512-+hTmAldEGE80U2wJJDC1lebb5jWqvTYAfm3YZ1ckk1gBr0MnCqUKlwK1e+anaFljIl+F5tR5IoZcm4ZDA1zMQw==
@@ -6920,17 +3406,12 @@
dependencies:
path-parse "^1.0.6"
-ret@~0.1.10:
- version "0.1.15"
- resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
- integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==
-
rfdc@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.4.tgz#ba72cc1367a0ccd9cf81a870b3b58bd3ad07f8c2"
integrity sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==
-rimraf@^2.5.4, rimraf@^2.6.0:
+rimraf@^2.6.0:
version "2.7.1"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
@@ -6944,102 +3425,22 @@
dependencies:
glob "^7.1.3"
-rimraf@~2.6.2:
- version "2.6.3"
- resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
- integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==
- dependencies:
- glob "^7.1.3"
-
-rollup@^1.3.0:
- version "1.29.1"
- resolved "https://registry.yarnpkg.com/rollup/-/rollup-1.29.1.tgz#8715d0a4ca439be3079f8095989ec8aa60f637bc"
- integrity sha512-dGQ+b9d1FOX/gluiggTAVnTvzQZUEkCi/TwZcax7ujugVRHs0nkYJlV9U4hsifGEMojnO+jvEML2CJQ6qXgbHA==
- dependencies:
- "@types/estree" "*"
- "@types/node" "*"
- acorn "^7.1.0"
-
safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
-safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0:
+safe-buffer@^5.0.1, safe-buffer@^5.1.2:
version "5.2.0"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519"
integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==
-safe-regex@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e"
- integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4=
- dependencies:
- ret "~0.1.10"
-
"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
-samsam@1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.2.tgz#bec11fdc83a9fda063401210e40176c3024d1567"
- integrity sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=
-
-samsam@1.x, samsam@^1.1.3:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.3.0.tgz#8d1d9350e25622da30de3e44ba692b5221ab7c50"
- integrity sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==
-
-samsam@~1.1:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.3.tgz#9f5087419b4d091f232571e7fa52e90b0f552621"
- integrity sha1-n1CHQZtNCR8jJXHn+lLpCw9VJiE=
-
-sauce-connect-launcher@^1.0.0:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/sauce-connect-launcher/-/sauce-connect-launcher-1.3.1.tgz#31137f57b0f7176e1c0525b7fb09c6da746647cf"
- integrity sha512-vIf9qDol3q2FlYzrKt0dr3kvec6LSjX2WS+/mVnAJIhqh1evSkPKCR2AzcJrnSmx9Xt9PtV0tLY7jYh0wsQi8A==
- dependencies:
- adm-zip "~0.4.3"
- async "^2.1.2"
- https-proxy-agent "^3.0.0"
- lodash "^4.16.6"
- rimraf "^2.5.4"
-
-select-hose@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
- integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=
-
-selenium-standalone@^6.7.0:
- version "6.17.0"
- resolved "https://registry.yarnpkg.com/selenium-standalone/-/selenium-standalone-6.17.0.tgz#0f24b691836205ee9bc3d7a6f207ebcb28170cd9"
- integrity sha512-5PSnDHwMiq+OCiAGlhwQ8BM9xuwFfvBOZ7Tfbw+ifkTnOy0PWbZmI1B9gPGuyGHpbQ/3J3CzIK7BYwrQ7EjtWQ==
- dependencies:
- async "^2.6.2"
- commander "^2.19.0"
- cross-spawn "^6.0.5"
- debug "^4.1.1"
- lodash "^4.17.11"
- minimist "^1.2.0"
- mkdirp "^0.5.1"
- progress "2.0.3"
- request "2.88.0"
- tar-stream "2.0.0"
- urijs "^1.19.1"
- which "^1.3.1"
- yauzl "^2.10.0"
-
-semver-diff@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36"
- integrity sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=
- dependencies:
- semver "^5.0.3"
-
-"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.7.0:
+"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.7.0:
version "5.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
@@ -7054,79 +3455,11 @@
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
-send@0.17.1:
- version "0.17.1"
- resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8"
- integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==
- dependencies:
- debug "2.6.9"
- depd "~1.1.2"
- destroy "~1.0.4"
- encodeurl "~1.0.2"
- escape-html "~1.0.3"
- etag "~1.8.1"
- fresh "0.5.2"
- http-errors "~1.7.2"
- mime "1.6.0"
- ms "2.1.1"
- on-finished "~2.3.0"
- range-parser "~1.2.1"
- statuses "~1.5.0"
-
-send@^0.16.1, send@^0.16.2:
- version "0.16.2"
- resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1"
- integrity sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==
- dependencies:
- debug "2.6.9"
- depd "~1.1.2"
- destroy "~1.0.4"
- encodeurl "~1.0.2"
- escape-html "~1.0.3"
- etag "~1.8.1"
- fresh "0.5.2"
- http-errors "~1.6.2"
- mime "1.4.1"
- ms "2.0.0"
- on-finished "~2.3.0"
- range-parser "~1.2.0"
- statuses "~1.4.0"
-
-serve-static@1.14.1:
- version "1.14.1"
- resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9"
- integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==
- dependencies:
- encodeurl "~1.0.2"
- escape-html "~1.0.3"
- parseurl "~1.3.3"
- send "0.17.1"
-
-server-destroy@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/server-destroy/-/server-destroy-1.0.1.tgz#f13bf928e42b9c3e79383e61cc3998b5d14e6cdd"
- integrity sha1-8Tv5KOQrnD55OD5hzDmYtdFObN0=
-
-serviceworker-cache-polyfill@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/serviceworker-cache-polyfill/-/serviceworker-cache-polyfill-4.0.0.tgz#de19ee73bef21ab3c0740a37b33db62464babdeb"
- integrity sha1-3hnuc77yGrPAdAo3sz22JGS6ves=
-
set-blocking@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
-set-value@^2.0.0, set-value@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b"
- integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==
- dependencies:
- extend-shallow "^2.0.1"
- is-extendable "^0.1.1"
- is-plain-object "^2.0.3"
- split-string "^3.0.1"
-
setprototypeof@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
@@ -7137,98 +3470,23 @@
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
-shady-css-parser@^0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/shady-css-parser/-/shady-css-parser-0.1.0.tgz#534dc79c8ca5884c5ed92a4e5a13d6d863bca428"
- integrity sha512-irfJUUkEuDlNHKZNAp2r7zOyMlmbfVJ+kWSfjlCYYUx/7dJnANLCyTzQZsuxy5NJkvtNwSxY5Gj8MOlqXUQPyA==
-
shady-css-scoped-element@^0.0.2:
version "0.0.2"
resolved "https://registry.yarnpkg.com/shady-css-scoped-element/-/shady-css-scoped-element-0.0.2.tgz#c538fcfe2317e979cd02dfec533898b95b4ea8fe"
integrity sha512-Dqfl70x6JiwYDujd33ZTbtCK0t52E7+H2swdWQNSTzfsolSa6LJHnTpN4T9OpJJEq4bxuzHRLFO9RBcy/UfrMQ==
-shebang-command@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
- integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=
+sinon@^9.0.2:
+ version "9.0.2"
+ resolved "https://registry.yarnpkg.com/sinon/-/sinon-9.0.2.tgz#b9017e24633f4b1c98dfb6e784a5f0509f5fd85d"
+ integrity sha512-0uF8Q/QHkizNUmbK3LRFqx5cpTttEVXudywY9Uwzy8bTfZUhljZ7ARzSxnRHWYWtVTeh4Cw+tTb3iU21FQVO9A==
dependencies:
- shebang-regex "^1.0.0"
-
-shebang-regex@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
- integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
-
-signal-exit@^3.0.0, signal-exit@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
- integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
-
-simple-swizzle@^0.2.2:
- version "0.2.2"
- resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a"
- integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=
- dependencies:
- is-arrayish "^0.3.1"
-
-sinon-chai@^2.10.0:
- version "2.14.0"
- resolved "https://registry.yarnpkg.com/sinon-chai/-/sinon-chai-2.14.0.tgz#da7dd4cc83cd6a260b67cca0f7a9fdae26a1205d"
- integrity sha512-9stIF1utB0ywNHNT7RgiXbdmen8QDCRsrTjw+G9TgKt1Yexjiv8TOWZ6WHsTPz57Yky3DIswZvEqX8fpuHNDtQ==
-
-sinon@^1.17.1:
- version "1.17.7"
- resolved "https://registry.yarnpkg.com/sinon/-/sinon-1.17.7.tgz#4542a4f49ba0c45c05eb2e9dd9d203e2b8efe0bf"
- integrity sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=
- dependencies:
- formatio "1.1.1"
- lolex "1.3.2"
- samsam "1.1.2"
- util ">=0.10.3 <1"
-
-sinon@^2.3.5:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/sinon/-/sinon-2.4.1.tgz#021fd64b54cb77d9d2fb0d43cdedfae7629c3a36"
- integrity sha512-vFTrO9Wt0ECffDYIPSP/E5bBugt0UjcBQOfQUMh66xzkyPEnhl/vM2LRZi2ajuTdkH07sA6DzrM6KvdvGIH8xw==
- dependencies:
- diff "^3.1.0"
- formatio "1.2.0"
- lolex "^1.6.0"
- native-promise-only "^0.8.1"
- path-to-regexp "^1.7.0"
- samsam "^1.1.3"
- text-encoding "0.6.4"
- type-detect "^4.0.0"
-
-snapdragon-node@^2.0.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b"
- integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==
- dependencies:
- define-property "^1.0.0"
- isobject "^3.0.0"
- snapdragon-util "^3.0.1"
-
-snapdragon-util@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2"
- integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==
- dependencies:
- kind-of "^3.2.0"
-
-snapdragon@^0.8.1:
- version "0.8.2"
- resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d"
- integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==
- dependencies:
- base "^0.11.1"
- debug "^2.2.0"
- define-property "^0.2.5"
- extend-shallow "^2.0.1"
- map-cache "^0.2.2"
- source-map "^0.5.6"
- source-map-resolve "^0.5.0"
- use "^3.1.0"
+ "@sinonjs/commons" "^1.7.2"
+ "@sinonjs/fake-timers" "^6.0.1"
+ "@sinonjs/formatio" "^5.0.1"
+ "@sinonjs/samsam" "^5.0.3"
+ diff "^4.0.2"
+ nise "^4.0.1"
+ supports-color "^7.1.0"
socket.io-adapter@~1.1.0:
version "1.1.2"
@@ -7255,26 +3513,6 @@
socket.io-parser "~3.2.0"
to-array "0.1.4"
-socket.io-client@2.3.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.3.0.tgz#14d5ba2e00b9bcd145ae443ab96b3f86cbcc1bb4"
- integrity sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA==
- dependencies:
- backo2 "1.0.2"
- base64-arraybuffer "0.1.5"
- component-bind "1.0.0"
- component-emitter "1.2.1"
- debug "~4.1.0"
- engine.io-client "~3.4.0"
- has-binary2 "~1.0.2"
- has-cors "1.1.0"
- indexof "0.0.1"
- object-component "0.0.3"
- parseqs "0.0.5"
- parseuri "0.0.5"
- socket.io-parser "~3.3.0"
- to-array "0.1.4"
-
socket.io-parser@~3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.2.0.tgz#e7c6228b6aa1f814e6148aea325b51aa9499e077"
@@ -7284,24 +3522,6 @@
debug "~3.1.0"
isarray "2.0.1"
-socket.io-parser@~3.3.0:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.3.0.tgz#2b52a96a509fdf31440ba40fed6094c7d4f1262f"
- integrity sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==
- dependencies:
- component-emitter "1.2.1"
- debug "~3.1.0"
- isarray "2.0.1"
-
-socket.io-parser@~3.4.0:
- version "3.4.0"
- resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.4.0.tgz#370bb4a151df2f77ce3345ff55a7072cc6e9565a"
- integrity sha512-/G/VOI+3DBp0+DJKW4KesGnQkQPFmUCbA/oO2QGT6CWxU7hLGWqU3tyuzeSK/dqcyeHsQg1vTe9jiZI8GU9SCQ==
- dependencies:
- component-emitter "1.2.1"
- debug "~4.1.0"
- isarray "2.0.1"
-
socket.io@2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.1.1.tgz#a069c5feabee3e6b214a75b40ce0652e1cfb9980"
@@ -7314,29 +3534,6 @@
socket.io-client "2.1.1"
socket.io-parser "~3.2.0"
-socket.io@^2.0.3:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.3.0.tgz#cd762ed6a4faeca59bc1f3e243c0969311eb73fb"
- integrity sha512-2A892lrj0GcgR/9Qk81EaY2gYhCBxurV0PfmmESO6p27QPrUK1J3zdns+5QPqvUYK2q657nSj0guoIil9+7eFg==
- dependencies:
- debug "~4.1.0"
- engine.io "~3.4.0"
- has-binary2 "~1.0.2"
- socket.io-adapter "~1.1.0"
- socket.io-client "2.3.0"
- socket.io-parser "~3.4.0"
-
-source-map-resolve@^0.5.0:
- version "0.5.3"
- resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"
- integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==
- dependencies:
- atob "^2.1.2"
- decode-uri-component "^0.2.0"
- resolve-url "^0.2.1"
- source-map-url "^0.4.0"
- urix "^0.1.0"
-
source-map-support@~0.5.12:
version "0.5.16"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042"
@@ -7345,12 +3542,7 @@
buffer-from "^1.0.0"
source-map "^0.6.0"
-source-map-url@^0.4.0:
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3"
- integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=
-
-source-map@^0.5.0, source-map@^0.5.6, source-map@^0.5.7:
+source-map@^0.5.0:
version "0.5.7"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
@@ -7386,38 +3578,6 @@
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654"
integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==
-spdy-transport@^2.0.18:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-2.1.1.tgz#c54815d73858aadd06ce63001e7d25fa6441623b"
- integrity sha512-q7D8c148escoB3Z7ySCASadkegMmUZW8Wb/Q1u0/XBgDKMO880rLQDj8Twiew/tYi7ghemKUi/whSYOwE17f5Q==
- dependencies:
- debug "^2.6.8"
- detect-node "^2.0.3"
- hpack.js "^2.1.6"
- obuf "^1.1.1"
- readable-stream "^2.2.9"
- safe-buffer "^5.0.1"
- wbuf "^1.7.2"
-
-spdy@^3.3.3:
- version "3.4.7"
- resolved "https://registry.yarnpkg.com/spdy/-/spdy-3.4.7.tgz#42ff41ece5cc0f99a3a6c28aabb73f5c3b03acbc"
- integrity sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=
- dependencies:
- debug "^2.6.8"
- handle-thing "^1.2.5"
- http-deceiver "^1.2.7"
- safe-buffer "^5.0.1"
- select-hose "^2.0.0"
- spdy-transport "^2.0.18"
-
-split-string@^3.0.1, split-string@^3.0.2:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2"
- integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==
- dependencies:
- extend-shallow "^3.0.0"
-
sprintf-js@~1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
@@ -7438,54 +3598,11 @@
safer-buffer "^2.0.2"
tweetnacl "~0.14.0"
-stable@^0.1.6:
- version "0.1.8"
- resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf"
- integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==
-
-stack-trace@0.0.x:
- version "0.0.10"
- resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0"
- integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=
-
-stacky@^1.3.1:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/stacky/-/stacky-1.3.1.tgz#3f117e5187b9a73d23f876d69f05c85b11804a12"
- integrity sha1-PxF+UYe5pz0j+HbWnwXIWxGAShI=
- dependencies:
- chalk "^1.1.1"
- lodash "^3.0.0"
-
-static-extend@^0.1.1:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6"
- integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=
- dependencies:
- define-property "^0.2.5"
- object-copy "^0.1.0"
-
"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@^1.0.0, statuses@^1.5.0, statuses@~1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
-statuses@~1.4.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087"
- integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==
-
-stream-shift@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d"
- integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==
-
-stream@0.0.2:
- version "0.0.2"
- resolved "https://registry.yarnpkg.com/stream/-/stream-0.0.2.tgz#7f5363f057f6592c5595f00bc80a27f5cec1f0ef"
- integrity sha1-f1Nj8Ff2WSxVlfALyAon9c7B8O8=
- dependencies:
- emitter-component "^1.1.1"
-
streamroller@^1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-1.0.6.tgz#8167d8496ed9f19f05ee4b158d9611321b8cacd9"
@@ -7497,12 +3614,7 @@
fs-extra "^7.0.1"
lodash "^4.17.14"
-streamsearch@0.1.2:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
- integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=
-
-"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1:
+"string-width@^1.0.2 || 2":
version "2.1.1"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
@@ -7535,32 +3647,6 @@
define-properties "^1.1.3"
function-bind "^1.1.1"
-string_decoder@^1.1.1:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
- integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
- dependencies:
- safe-buffer "~5.2.0"
-
-string_decoder@~0.10.x:
- version "0.10.31"
- resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
- integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
-
-string_decoder@~1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
- integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
- dependencies:
- safe-buffer "~5.1.0"
-
-strip-ansi@^3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
- integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=
- dependencies:
- ansi-regex "^2.0.0"
-
strip-ansi@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
@@ -7575,60 +3661,16 @@
dependencies:
ansi-regex "^4.1.0"
-strip-ansi@~0.1.0:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.1.1.tgz#39e8a98d044d150660abe4a6808acf70bb7bc991"
- integrity sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=
-
-strip-bom-stream@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz#e7144398577d51a6bed0fa1994fa05f43fd988ee"
- integrity sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=
- dependencies:
- first-chunk-stream "^1.0.0"
- strip-bom "^2.0.0"
-
-strip-bom@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
- integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=
- dependencies:
- is-utf8 "^0.2.0"
-
strip-bom@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=
-strip-eof@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
- integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=
-
-strip-indent@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2"
- integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=
- dependencies:
- get-stdin "^4.0.1"
-
-strip-indent@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68"
- integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=
-
-strip-json-comments@2.0.1, strip-json-comments@~2.0.1:
+strip-json-comments@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
-supports-color@3.1.2:
- version "3.1.2"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5"
- integrity sha1-cqJiiU2dQIuVbKBf83su2KbiotU=
- dependencies:
- has-flag "^1.0.0"
-
supports-color@6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a"
@@ -7636,11 +3678,6 @@
dependencies:
has-flag "^3.0.0"
-supports-color@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
- integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=
-
supports-color@^5.3.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
@@ -7648,46 +3685,18 @@
dependencies:
has-flag "^3.0.0"
-sw-precache@^5.1.1:
- version "5.2.1"
- resolved "https://registry.yarnpkg.com/sw-precache/-/sw-precache-5.2.1.tgz#06134f319eec68f3b9583ce9a7036b1c119f7179"
- integrity sha512-8FAy+BP/FXE+ILfiVTt+GQJ6UEf4CVHD9OfhzH0JX+3zoy2uFk7Vn9EfXASOtVmmIVbL3jE/W8Z66VgPSZcMhw==
+supports-color@^7.1.0:
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1"
+ integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==
dependencies:
- dom-urls "^1.1.0"
- es6-promise "^4.0.5"
- glob "^7.1.1"
- lodash.defaults "^4.2.0"
- lodash.template "^4.4.0"
- meow "^3.7.0"
- mkdirp "^0.5.1"
- pretty-bytes "^4.0.2"
- sw-toolbox "^3.4.0"
- update-notifier "^2.3.0"
-
-sw-toolbox@^3.4.0:
- version "3.6.0"
- resolved "https://registry.yarnpkg.com/sw-toolbox/-/sw-toolbox-3.6.0.tgz#26df1d1c70348658e4dea2884319149b7b3183b5"
- integrity sha1-Jt8dHHA0hljk3qKIQxkUm3sxg7U=
- dependencies:
- path-to-regexp "^1.0.1"
- serviceworker-cache-polyfill "^4.0.0"
+ has-flag "^4.0.0"
systemjs@^4.0.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/systemjs/-/systemjs-4.1.1.tgz#c90061456f9707478d487b47f3b92b9896032889"
integrity sha512-/0x3bcMrl1pxDCLw6sJWEKPVy0ZGEu7I0nItFSHxfPoDU2Lll6TUyB1wqltvbm7n5y5jVOoK4lei4oMpmW7XJQ==
-table-layout@^0.4.3:
- version "0.4.5"
- resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-0.4.5.tgz#d906de6a25fa09c0c90d1d08ecd833ecedcb7378"
- integrity sha512-zTvf0mcggrGeTe/2jJ6ECkJHAQPIYEwDoqsiqBjI24mvRmQbInK5jq33fyypaCBxX08hMkfmdOqj6haT33EqWw==
- dependencies:
- array-back "^2.0.0"
- deep-extend "~0.6.0"
- lodash.padend "^4.6.1"
- typical "^2.6.1"
- wordwrapjs "^3.0.0"
-
table-layout@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-1.0.1.tgz#8411181ee951278ad0638aea2f779a9ce42894f9"
@@ -7698,52 +3707,6 @@
typical "^5.2.0"
wordwrapjs "^4.0.0"
-tar-stream@2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.0.0.tgz#8829bbf83067bc0288a9089db49c56be395b6aea"
- integrity sha512-n2vtsWshZOVr/SY4KtslPoUlyNh06I2SGgAOCZmquCEjlbV/LjY2CY80rDtdQRHFOYXNlgBDo6Fr3ww2CWPOtA==
- dependencies:
- bl "^2.2.0"
- end-of-stream "^1.4.1"
- fs-constants "^1.0.0"
- inherits "^2.0.3"
- readable-stream "^3.1.1"
-
-tar-stream@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.0.tgz#d1aaa3661f05b38b5acc9b7020efdca5179a2cc3"
- integrity sha512-+DAn4Nb4+gz6WZigRzKEZl1QuJVOLtAwwF+WUxy1fJ6X63CaGaUAxJRD2KEn1OMfcbCjySTYpNC6WmfQoIEOdw==
- dependencies:
- bl "^3.0.0"
- end-of-stream "^1.4.1"
- fs-constants "^1.0.0"
- inherits "^2.0.3"
- readable-stream "^3.1.1"
-
-temp@^0.8.1:
- version "0.8.4"
- resolved "https://registry.yarnpkg.com/temp/-/temp-0.8.4.tgz#8c97a33a4770072e0a05f919396c7665a7dd59f2"
- integrity sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==
- dependencies:
- rimraf "~2.6.2"
-
-term-size@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69"
- integrity sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=
- dependencies:
- execa "^0.7.0"
-
-ternary-stream@^2.0.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/ternary-stream/-/ternary-stream-2.1.1.tgz#4ad64b98668d796a085af2c493885a435a8a8bfc"
- integrity sha512-j6ei9hxSoyGlqTmoMjOm+QNvUKDOIY6bNl4Uh1lhBvl6yjPW2iLqxDUYyfDPZknQ4KdRziFl+ec99iT4l7g0cw==
- dependencies:
- duplexify "^3.5.0"
- fork-stream "^0.0.4"
- merge-stream "^1.0.0"
- through2 "^2.0.1"
-
terser@^4.6.4:
version "4.6.10"
resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.10.tgz#90f5bd069ff456ddbc9503b18e52f9c493d3b7c2"
@@ -7763,16 +3726,6 @@
read-pkg-up "^4.0.0"
require-main-filename "^2.0.0"
-text-encoding@0.6.4:
- version "0.6.4"
- resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19"
- integrity sha1-45mpgiV6J22uQou5KEXLcb3CbRk=
-
-text-hex@1.0.x:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5"
- integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==
-
thenify-all@^1.0.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726"
@@ -7787,43 +3740,6 @@
dependencies:
any-promise "^1.0.0"
-through2-filter@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-2.0.0.tgz#60bc55a0dacb76085db1f9dae99ab43f83d622ec"
- integrity sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=
- dependencies:
- through2 "~2.0.0"
- xtend "~4.0.0"
-
-through2-filter@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-3.0.0.tgz#700e786df2367c2c88cd8aa5be4cf9c1e7831254"
- integrity sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==
- dependencies:
- through2 "~2.0.0"
- xtend "~4.0.0"
-
-through2@^0.6.0:
- version "0.6.5"
- resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48"
- integrity sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=
- dependencies:
- readable-stream ">=1.0.33-1 <1.1.0-0"
- xtend ">=4.0.0 <4.1.0-0"
-
-through2@^2.0.0, through2@^2.0.1, through2@~2.0.0:
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
- integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==
- dependencies:
- readable-stream "~2.3.6"
- xtend "~4.0.1"
-
-timed-out@^4.0.0:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f"
- integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=
-
tmp@0.0.33, tmp@0.0.x:
version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
@@ -7831,43 +3747,16 @@
dependencies:
os-tmpdir "~1.0.2"
-to-absolute-glob@^0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz#1cdfa472a9ef50c239ee66999b662ca0eb39937f"
- integrity sha1-HN+kcqnvUMI57maZm2YsoOs5k38=
- dependencies:
- extend-shallow "^2.0.1"
-
to-array@0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890"
integrity sha1-F+bBH3PdTz10zaek/zI46a2b+JA=
-to-fast-properties@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
- integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=
-
to-fast-properties@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=
-to-object-path@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af"
- integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=
- dependencies:
- kind-of "^3.0.2"
-
-to-regex-range@^2.1.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38"
- integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=
- dependencies:
- is-number "^3.0.0"
- repeat-string "^1.6.1"
-
to-regex-range@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
@@ -7875,29 +3764,11 @@
dependencies:
is-number "^7.0.0"
-to-regex@^3.0.1, to-regex@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce"
- integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==
- dependencies:
- define-property "^2.0.2"
- extend-shallow "^3.0.2"
- regex-not "^1.0.2"
- safe-regex "^1.1.0"
-
toidentifier@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
-tough-cookie@~2.4.3:
- version "2.4.3"
- resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781"
- integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==
- dependencies:
- psl "^1.1.24"
- punycode "^1.4.1"
-
tough-cookie@~2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
@@ -7913,21 +3784,6 @@
dependencies:
punycode "^2.1.0"
-trim-newlines@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
- integrity sha1-WIeWa7WCpFA6QetST301ARgVphM=
-
-trim-right@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
- integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=
-
-triple-beam@^1.2.0, triple-beam@^1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9"
- integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==
-
tsscmp@1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb"
@@ -7945,22 +3801,12 @@
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
-type-detect@0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-0.1.1.tgz#0ba5ec2a885640e470ea4e8505971900dac58822"
- integrity sha1-C6XsKohWQORw6k6FBZcZANrFiCI=
-
-type-detect@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2"
- integrity sha1-diIXzAbbJY7EiQihKY6LlRIejqI=
-
-type-detect@^4.0.0, type-detect@^4.0.5:
+type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5, type-detect@^4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
-type-is@^1.6.16, type-is@^1.6.4, type-is@~1.6.17, type-is@~1.6.18:
+type-is@^1.6.16, type-is@~1.6.17:
version "1.6.18"
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
@@ -7968,16 +3814,6 @@
media-typer "0.3.0"
mime-types "~2.1.24"
-typedarray@^0.0.6:
- version "0.0.6"
- resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
- integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
-
-typical@^2.6.1:
- version "2.6.1"
- resolved "https://registry.yarnpkg.com/typical/-/typical-2.6.1.tgz#5c080e5d661cbbe38259d2e70a3c7253e873881d"
- integrity sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=
-
typical@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4"
@@ -7988,19 +3824,6 @@
resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066"
integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==
-ua-parser-js@^0.7.15:
- version "0.7.21"
- resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.21.tgz#853cf9ce93f642f67174273cc34565ae6f308777"
- integrity sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ==
-
-uglify-js@3.4.x:
- version "3.4.10"
- resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.10.tgz#9ad9563d8eb3acdfb8d38597d2af1d815f6a755f"
- integrity sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==
- dependencies:
- commander "~2.19.0"
- source-map "~0.6.1"
-
uglify-js@^3.5.1:
version "3.8.1"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.8.1.tgz#43bb15ce6f545eaa0a64c49fd29375ea09fa0f93"
@@ -8014,16 +3837,6 @@
resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c"
integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==
-underscore@^1.8.3:
- version "1.9.2"
- resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.2.tgz#0c8d6f536d6f378a5af264a72f7bec50feb7cf2f"
- integrity sha512-D39qtimx0c1fI3ya1Lnhk3E9nONswSKhnffBI0gME9C99fYOkNi04xs8K6pePLhvl1frbDemkaBQ5ikWllR2HQ==
-
-underscore@~1.6.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.6.0.tgz#8b38b10cacdef63337b8b24e4ff86d45aea529a8"
- integrity sha1-izixDKze9jM3uLJOT/htRa6lKag=
-
unicode-canonical-property-names-ecmascript@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818"
@@ -8052,31 +3865,6 @@
resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57"
integrity sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==
-union-value@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847"
- integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==
- dependencies:
- arr-union "^3.1.0"
- get-value "^2.0.6"
- is-extendable "^0.1.1"
- set-value "^2.0.1"
-
-unique-stream@^2.0.2:
- version "2.3.1"
- resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.3.1.tgz#c65d110e9a4adf9a6c5948b28053d9a8d04cbeac"
- integrity sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==
- dependencies:
- json-stable-stringify-without-jsonify "^1.0.1"
- through2-filter "^3.0.0"
-
-unique-string@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a"
- integrity sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=
- dependencies:
- crypto-random-string "^1.0.0"
-
universalify@^0.1.0:
version "0.1.2"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
@@ -8087,42 +3875,6 @@
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
-unset-value@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559"
- integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=
- dependencies:
- has-value "^0.3.1"
- isobject "^3.0.0"
-
-untildify@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/untildify/-/untildify-2.1.0.tgz#17eb2807987f76952e9c0485fc311d06a826a2e0"
- integrity sha1-F+soB5h/dpUunASF/DEdBqgmouA=
- dependencies:
- os-homedir "^1.0.0"
-
-unzip-response@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97"
- integrity sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=
-
-update-notifier@^2.2.0, update-notifier@^2.3.0:
- version "2.5.0"
- resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.5.0.tgz#d0744593e13f161e406acb1d9408b72cad08aff6"
- integrity sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==
- dependencies:
- boxen "^1.2.1"
- chalk "^2.0.1"
- configstore "^3.0.0"
- import-lazy "^2.1.0"
- is-ci "^1.0.10"
- is-installed-globally "^0.1.0"
- is-npm "^1.0.0"
- latest-version "^3.0.0"
- semver-diff "^2.0.0"
- xdg-basedir "^3.0.0"
-
upper-case@^1.1.1:
version "1.1.3"
resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598"
@@ -8135,28 +3887,6 @@
dependencies:
punycode "^2.1.0"
-urijs@^1.16.1, urijs@^1.19.1:
- version "1.19.2"
- resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.2.tgz#f9be09f00c4c5134b7cb3cf475c1dd394526265a"
- integrity sha512-s/UIq9ap4JPZ7H1EB5ULo/aOUbWqfDi7FKzMC2Nz+0Si8GiT1rIEaprt8hy3Vy2Ex2aJPpOQv4P4DuOZ+K1c6w==
-
-urix@^0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
- integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=
-
-url-parse-lax@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73"
- integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=
- dependencies:
- prepend-http "^1.0.1"
-
-use@^3.1.0:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
- integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==
-
useragent@2.3.0, useragent@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.3.0.tgz#217f943ad540cb2128658ab23fc960f6a88c9972"
@@ -8165,37 +3895,16 @@
lru-cache "4.1.x"
tmp "0.0.x"
-util-deprecate@^1.0.1, util-deprecate@~1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
- integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
-
-"util@>=0.10.3 <1":
- version "0.12.1"
- resolved "https://registry.yarnpkg.com/util/-/util-0.12.1.tgz#f908e7b633e7396c764e694dd14e716256ce8ade"
- integrity sha512-MREAtYOp+GTt9/+kwf00IYoHZyjM8VU4aVrkzUlejyqaIjd2GztVl5V9hGXKlvBKE3gENn/FMfHE5v6hElXGcQ==
- dependencies:
- inherits "^2.0.3"
- is-arguments "^1.0.4"
- is-generator-function "^1.0.7"
- object.entries "^1.1.0"
- safe-buffer "^5.1.2"
-
utils-merge@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
-uuid@^3.2.1, uuid@^3.3.2:
+uuid@^3.3.2:
version "3.4.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
-vali-date@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/vali-date/-/vali-date-1.0.0.tgz#1b904a59609fb328ef078138420934f6b86709a6"
- integrity sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=
-
valid-url@^1.0.9:
version "1.0.9"
resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200"
@@ -8209,12 +3918,7 @@
spdx-correct "^3.0.0"
spdx-expression-parse "^3.0.0"
-vargs@^0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/vargs/-/vargs-0.1.0.tgz#6b6184da6520cc3204ce1b407cac26d92609ebff"
- integrity sha1-a2GE2mUgzDIEzhtAfKwm2SYJ6/8=
-
-vary@^1, vary@^1.1.2, vary@~1.1.2:
+vary@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
@@ -8228,155 +3932,11 @@
core-util-is "1.0.2"
extsprintf "^1.2.0"
-vinyl-fs@^2.4.4:
- version "2.4.4"
- resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-2.4.4.tgz#be6ff3270cb55dfd7d3063640de81f25d7532239"
- integrity sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=
- dependencies:
- duplexify "^3.2.0"
- glob-stream "^5.3.2"
- graceful-fs "^4.0.0"
- gulp-sourcemaps "1.6.0"
- is-valid-glob "^0.3.0"
- lazystream "^1.0.0"
- lodash.isequal "^4.0.0"
- merge-stream "^1.0.0"
- mkdirp "^0.5.0"
- object-assign "^4.0.0"
- readable-stream "^2.0.4"
- strip-bom "^2.0.0"
- strip-bom-stream "^1.0.0"
- through2 "^2.0.0"
- through2-filter "^2.0.0"
- vali-date "^1.0.0"
- vinyl "^1.0.0"
-
-vinyl@^1.0.0, vinyl@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884"
- integrity sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=
- dependencies:
- clone "^1.0.0"
- clone-stats "^0.0.1"
- replace-ext "0.0.1"
-
-vlq@^0.2.2:
- version "0.2.3"
- resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26"
- integrity sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==
-
void-elements@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=
-vscode-uri@=1.0.6:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-1.0.6.tgz#6b8f141b0bbc44ad7b07e94f82f168ac7608ad4d"
- integrity sha512-sLI2L0uGov3wKVb9EB+vIQBl9tVP90nqRvxSoJ35vI3NjxE8jfsE5DSOhWgSunHSZmKS4OCi2jrtfxK7uyp2ww==
-
-wbuf@^1.1.0, wbuf@^1.7.2:
- version "1.7.3"
- resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df"
- integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==
- dependencies:
- minimalistic-assert "^1.0.0"
-
-wct-browser-legacy@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/wct-browser-legacy/-/wct-browser-legacy-1.0.2.tgz#6be39174bd37e2903028d3dbd2292f9c4ec59767"
- integrity sha512-23rbZwBh/DxWU36htJN9lsyBq3NxgVbuyMUq7fgFP6ZVTel+uFWO6LPXPoZQ6VyvXvlUYLE5PxY+ZdJ88a4COw==
- dependencies:
- "@polymer/polymer" "^3.0.0"
- "@polymer/sinonjs" "^1.14.1"
- "@polymer/test-fixture" "^3.0.0-pre.1"
- "@webcomponents/webcomponentsjs" "^2.0.0"
- accessibility-developer-tools "^2.12.0"
- async "^1.5.2"
- chai "^3.5.0"
- lodash "^3.10.1"
- mocha "^3.4.2"
- sinon "^1.17.1"
- sinon-chai "^2.10.0"
- stacky "^1.3.1"
-
-wct-local@^2.1.1:
- version "2.1.5"
- resolved "https://registry.yarnpkg.com/wct-local/-/wct-local-2.1.5.tgz#f7986753e3ad9a35d39178a9989350523561fff1"
- integrity sha512-eqoZhjGy4Xq2tY0uB46Grkw/ztq+/rC0ImbYKl62unFHXtOgal+kkvnxR3SLRFNM8ty9+ItgycPeH0IpTqVL+w==
- dependencies:
- "@types/express" "^4.0.30"
- "@types/freeport" "^1.0.19"
- "@types/launchpad" "^0.6.0"
- "@types/which" "^1.3.1"
- chalk "^2.3.0"
- cleankill "^2.0.0"
- freeport "^1.0.4"
- launchpad "^0.7.0"
- selenium-standalone "^6.7.0"
- which "^1.0.8"
-
-wct-sauce@^2.0.2:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/wct-sauce/-/wct-sauce-2.1.0.tgz#67d0be346aabbbc28384e8d143b8d3ca7ba774c0"
- integrity sha512-c3R4PJcbpS7Gxv2vZ4HDAqpXV6cT9peslAWMU7hHH9PMhKDPbn8RNa6E4DVL0tOmZznB+3cRmtZ6+vJ/aDwu1A==
- dependencies:
- chalk "^2.4.1"
- cleankill "^2.0.0"
- lodash "^4.17.10"
- request "^2.85.0"
- sauce-connect-launcher "^1.0.0"
- temp "^0.8.1"
- uuid "^3.2.1"
-
-wd@^1.2.0:
- version "1.12.1"
- resolved "https://registry.yarnpkg.com/wd/-/wd-1.12.1.tgz#067eb3674db00eeb9e506701f9314657c44d5a89"
- integrity sha512-O99X8OnOgkqfmsPyLIRzG9LmZ+rjmdGFBCyhGpnsSL4MB4xzHoeWmSVcumDiQ5QqPZcwGkszTgeJvjk2VjtiNw==
- dependencies:
- archiver "^3.0.0"
- async "^2.0.0"
- lodash "^4.0.0"
- mkdirp "^0.5.1"
- q "^1.5.1"
- request "2.88.0"
- vargs "^0.1.0"
-
-web-component-tester@^6.9.2:
- version "6.9.2"
- resolved "https://registry.yarnpkg.com/web-component-tester/-/web-component-tester-6.9.2.tgz#40a7b824f2cf3cbc4305552bdfc3357977ded48a"
- integrity sha512-s2kB/+IE8XWcnxY1fqSpqTiiHEGHWgUWariAbiRlxmAvWSuvaCVNALHYebsZrLCNCLHKcJR8/sGv/bw0MWMvjw==
- dependencies:
- "@polymer/sinonjs" "^1.14.1"
- "@polymer/test-fixture" "^0.0.3"
- "@webcomponents/webcomponentsjs" "^1.0.7"
- accessibility-developer-tools "^2.12.0"
- async "^2.4.1"
- body-parser "^1.17.2"
- bower-config "^1.4.0"
- chalk "^1.1.3"
- cleankill "^2.0.0"
- express "^4.15.3"
- findup-sync "^2.0.0"
- glob "^7.1.2"
- lodash "^3.10.1"
- multer "^1.3.0"
- nomnom "^1.8.1"
- polyserve "^0.27.13"
- resolve "^1.5.0"
- semver "^5.3.0"
- send "^0.16.1"
- server-destroy "^1.0.1"
- sinon "^2.3.5"
- sinon-chai "^2.10.0"
- socket.io "^2.0.3"
- stacky "^1.3.1"
- wd "^1.2.0"
- optionalDependencies:
- update-notifier "^2.2.0"
- wct-local "^2.1.1"
- wct-sauce "^2.0.2"
-
webidl-conversions@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
@@ -8387,15 +3947,6 @@
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb"
integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==
-whatwg-url@^6.4.0:
- version "6.5.0"
- resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.5.0.tgz#f2df02bff176fd65070df74ad5ccbb5a199965a8"
- integrity sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==
- dependencies:
- lodash.sortby "^4.7.0"
- tr46 "^1.0.1"
- webidl-conversions "^4.0.2"
-
whatwg-url@^7.0.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06"
@@ -8410,7 +3961,7 @@
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
-which@1.3.1, which@^1.0.8, which@^1.2.1, which@^1.2.14, which@^1.2.9, which@^1.3.1:
+which@1.3.1, which@^1.2.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
@@ -8424,49 +3975,11 @@
dependencies:
string-width "^1.0.2 || 2"
-widest-line@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc"
- integrity sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==
- dependencies:
- string-width "^2.1.1"
-
-winston-transport@^4.2.0, winston-transport@^4.3.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.3.0.tgz#df68c0c202482c448d9b47313c07304c2d7c2c66"
- integrity sha512-B2wPuwUi3vhzn/51Uukcao4dIduEiPOcOt9HJ3QeaXgkJ5Z7UwpBzxS4ZGNHtrxrUvTwemsQiSys0ihOf8Mp1A==
- dependencies:
- readable-stream "^2.3.6"
- triple-beam "^1.2.0"
-
-winston@^3.0.0:
- version "3.2.1"
- resolved "https://registry.yarnpkg.com/winston/-/winston-3.2.1.tgz#63061377976c73584028be2490a1846055f77f07"
- integrity sha512-zU6vgnS9dAWCEKg/QYigd6cgMVVNwyTzKs81XZtTFuRwJOcDdBg7AU0mXVyNbs7O5RH2zdv+BdNZUlx7mXPuOw==
- dependencies:
- async "^2.6.1"
- diagnostics "^1.1.1"
- is-stream "^1.1.0"
- logform "^2.1.1"
- one-time "0.0.4"
- readable-stream "^3.1.1"
- stack-trace "0.0.x"
- triple-beam "^1.3.0"
- winston-transport "^4.3.0"
-
wordwrap@~0.0.2:
version "0.0.3"
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc=
-wordwrapjs@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-3.0.0.tgz#c94c372894cadc6feb1a66bff64e1d9af92c5d1e"
- integrity sha512-mO8XtqyPvykVCsrwj5MlOVWvSnCdT+C+QVbm6blradR7JExAhbkZ7hZ9A+9NUtwzSqrlUo9a67ws0EiILrvRpw==
- dependencies:
- reduce-flatten "^1.0.1"
- typical "^2.6.1"
-
wordwrapjs@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.0.tgz#9aa9394155993476e831ba8e59fb5795ebde6800"
@@ -8489,20 +4002,6 @@
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
-write-file-atomic@^2.0.0:
- version "2.4.3"
- resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481"
- integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==
- dependencies:
- graceful-fs "^4.1.11"
- imurmurhash "^0.1.4"
- signal-exit "^3.0.2"
-
-ws@^7.1.2:
- version "7.2.1"
- resolved "https://registry.yarnpkg.com/ws/-/ws-7.2.1.tgz#03ed52423cd744084b2cf42ed197c8b65a936b8e"
- integrity sha512-sucePNSafamSKoOqoNfBd8V0StlkzJKL2ZAhGQinCfNQ+oacw+Pk7lcdAElecBF2VkLNZRiIb5Oi1Q5lVUVt2A==
-
ws@~3.3.1:
version "3.3.3"
resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2"
@@ -8512,38 +4011,11 @@
safe-buffer "~5.1.0"
ultron "~1.1.0"
-ws@~6.1.0:
- version "6.1.4"
- resolved "https://registry.yarnpkg.com/ws/-/ws-6.1.4.tgz#5b5c8800afab925e94ccb29d153c8d02c1776ef9"
- integrity sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==
- dependencies:
- async-limiter "~1.0.0"
-
-xdg-basedir@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4"
- integrity sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=
-
-xmlbuilder@8.2.2:
- version "8.2.2"
- resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-8.2.2.tgz#69248673410b4ba42e1a6136551d2922335aa773"
- integrity sha1-aSSGc0ELS6QuGmE2VR0pIjNap3M=
-
-xmldom@0.1.x:
- version "0.1.31"
- resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.31.tgz#b76c9a1bd9f0a9737e5a72dc37231cf38375e2ff"
- integrity sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==
-
xmlhttprequest-ssl@~1.5.4:
version "1.5.5"
resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e"
integrity sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=
-"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@~4.0.0, xtend@~4.0.1:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
- integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
-
y18n@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
@@ -8616,14 +4088,6 @@
y18n "^4.0.0"
yargs-parser "^13.1.1"
-yauzl@^2.10.0:
- version "2.10.0"
- resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
- integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=
- dependencies:
- buffer-crc32 "~0.2.3"
- fd-slicer "~1.1.0"
-
yeast@0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419"
@@ -8633,12 +4097,3 @@
version "1.2.1"
resolved "https://registry.yarnpkg.com/ylru/-/ylru-1.2.1.tgz#f576b63341547989c1de7ba288760923b27fe84f"
integrity sha512-faQrqNMzcPCHGVC2aaOINk13K+aaBDUPjGWl0teOXywElLjyVAB6Oe2jj62jHYtwsU49jXhScYbvPENK+6zAvQ==
-
-zip-stream@^2.1.2:
- version "2.1.3"
- resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-2.1.3.tgz#26cc4bdb93641a8590dd07112e1f77af1758865b"
- integrity sha512-EkXc2JGcKhO5N5aZ7TmuNo45budRaFGHOmz24wtJR7znbNqDPmdZtUauKX6et8KAVseAMBOyWJqEpXcHTBsh7Q==
- dependencies:
- archiver-utils "^2.1.0"
- compress-commons "^2.1.1"
- readable-stream "^3.4.0"
diff --git a/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy b/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy
index d162714..32ba0bc 100644
--- a/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy
+++ b/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy
@@ -139,7 +139,7 @@
// Content between webcomponents-lite and the load of the main app element
// run before polymer-resin is installed so may have security consequences.
// Contact your local security engineer if you have any questions, and
- // CC them on any changes that load content before gr-app.html.
+ // CC them on any changes that load content before gr-app.js.
//
// github.com/Polymer/polymer-resin/blob/master/getting-started.md#integrating
{if $assetsPath and $assetsBundle}
diff --git a/resources/com/google/gerrit/server/mail/CommentHtml.soy b/resources/com/google/gerrit/server/mail/CommentHtml.soy
index 534cbdb..617c8d17 100644
--- a/resources/com/google/gerrit/server/mail/CommentHtml.soy
+++ b/resources/com/google/gerrit/server/mail/CommentHtml.soy
@@ -111,7 +111,9 @@
{for $group in $commentFiles}
<li style="{$fileLiStyle}">
<p>
- <a href="{$group.link}">{$group.title}:</a>
+ {if $group.link}<a href="{$group.link}">{/if}
+ {$group.title}:
+ {if $group.link}</a>{/if}
</p>
<ul style="{$ulStyle}">
diff --git a/tools/bzl/maven_jar.bzl b/tools/bzl/maven_jar.bzl
index 2f5447b..9908ee8 100644
--- a/tools/bzl/maven_jar.bzl
+++ b/tools/bzl/maven_jar.bzl
@@ -189,7 +189,6 @@
"repository": attr.string(default = MAVEN_CENTRAL),
"sha1": attr.string(),
"src_sha1": attr.string(),
- "unsign": attr.bool(default = False),
"exports": attr.string_list(),
"deps": attr.string_list(),
"_download_script": attr.label(default = Label("//tools:download_file.py")),
diff --git a/tools/bzl/plugin.bzl b/tools/bzl/plugin.bzl
index d49e700..ce5d62d 100644
--- a/tools/bzl/plugin.bzl
+++ b/tools/bzl/plugin.bzl
@@ -2,6 +2,8 @@
load("//tools/bzl:genrule2.bzl", "genrule2")
load("//:version.bzl", "GERRIT_VERSION")
+IN_TREE_BUILD_MODE = True
+
PLUGIN_DEPS = ["//plugins:plugin-lib"]
PLUGIN_DEPS_NEVERLINK = ["//plugins:plugin-lib-neverlink"]
diff --git a/tools/maven/gerrit-acceptance-framework_pom.xml b/tools/maven/gerrit-acceptance-framework_pom.xml
index 8748250..14c726e 100644
--- a/tools/maven/gerrit-acceptance-framework_pom.xml
+++ b/tools/maven/gerrit-acceptance-framework_pom.xml
@@ -29,9 +29,6 @@
<name>Ben Rohlfs</name>
</developer>
<developer>
- <name>Dave Borowitz</name>
- </developer>
- <developer>
<name>David Ostrovsky</name>
</developer>
<developer>
@@ -53,6 +50,9 @@
<name>Martin Fick</name>
</developer>
<developer>
+ <name>Matthias Sohn</name>
+ </developer>
+ <developer>
<name>Ole Rehmsen</name>
</developer>
<developer>
@@ -61,6 +61,9 @@
<developer>
<name>Saša Živkov</name>
</developer>
+ <developer>
+ <name>Sven Selberg</name>
+ </developer>
</developers>
<mailingLists>
diff --git a/tools/maven/gerrit-extension-api_pom.xml b/tools/maven/gerrit-extension-api_pom.xml
index ae31ac9..bd323ba 100644
--- a/tools/maven/gerrit-extension-api_pom.xml
+++ b/tools/maven/gerrit-extension-api_pom.xml
@@ -29,9 +29,6 @@
<name>Ben Rohlfs</name>
</developer>
<developer>
- <name>Dave Borowitz</name>
- </developer>
- <developer>
<name>David Ostrovsky</name>
</developer>
<developer>
@@ -53,6 +50,9 @@
<name>Martin Fick</name>
</developer>
<developer>
+ <name>Matthias Sohn</name>
+ </developer>
+ <developer>
<name>Ole Rehmsen</name>
</developer>
<developer>
@@ -61,6 +61,9 @@
<developer>
<name>Saša Živkov</name>
</developer>
+ <developer>
+ <name>Sven Selberg</name>
+ </developer>
</developers>
<mailingLists>
diff --git a/tools/maven/gerrit-plugin-api_pom.xml b/tools/maven/gerrit-plugin-api_pom.xml
index dc25c80..3b059e5 100644
--- a/tools/maven/gerrit-plugin-api_pom.xml
+++ b/tools/maven/gerrit-plugin-api_pom.xml
@@ -29,9 +29,6 @@
<name>Ben Rohlfs</name>
</developer>
<developer>
- <name>Dave Borowitz</name>
- </developer>
- <developer>
<name>David Ostrovsky</name>
</developer>
<developer>
@@ -53,6 +50,9 @@
<name>Martin Fick</name>
</developer>
<developer>
+ <name>Matthias Sohn</name>
+ </developer>
+ <developer>
<name>Ole Rehmsen</name>
</developer>
<developer>
@@ -61,6 +61,9 @@
<developer>
<name>Saša Živkov</name>
</developer>
+ <developer>
+ <name>Sven Selberg</name>
+ </developer>
</developers>
<mailingLists>
diff --git a/tools/maven/gerrit-war_pom.xml b/tools/maven/gerrit-war_pom.xml
index d21f88c..b8fa132 100644
--- a/tools/maven/gerrit-war_pom.xml
+++ b/tools/maven/gerrit-war_pom.xml
@@ -29,9 +29,6 @@
<name>Ben Rohlfs</name>
</developer>
<developer>
- <name>Dave Borowitz</name>
- </developer>
- <developer>
<name>David Ostrovsky</name>
</developer>
<developer>
@@ -53,6 +50,9 @@
<name>Martin Fick</name>
</developer>
<developer>
+ <name>Matthias Sohn</name>
+ </developer>
+ <developer>
<name>Ole Rehmsen</name>
</developer>
<developer>
@@ -61,6 +61,9 @@
<developer>
<name>Saša Živkov</name>
</developer>
+ <developer>
+ <name>Sven Selberg</name>
+ </developer>
</developers>
<mailingLists>
diff --git a/tools/nongoogle.bzl b/tools/nongoogle.bzl
index 26dcd31..96ea42c 100644
--- a/tools/nongoogle.bzl
+++ b/tools/nongoogle.bzl
@@ -102,8 +102,8 @@
maven_jar(
name = "jackson-core",
- artifact = "com.fasterxml.jackson.core:jackson-core:2.11.0",
- sha1 = "f84302e14648f9f63c0c73951054aeb2ff0b810a",
+ artifact = "com.fasterxml.jackson.core:jackson-core:2.11.1",
+ sha1 = "8b02908d53183fdf9758e7e20f2fdee87613a962",
)
# Google internal dependencies: these are developed at Google, so there is
diff --git a/yarn.lock b/yarn.lock
index 02ac32e..e7423a2 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -9055,7 +9055,7 @@
request "2.88.0"
vargs "^0.1.0"
-web-component-tester@^6.5.1, web-component-tester@^6.9.0:
+web-component-tester@^6.9.0:
version "6.9.2"
resolved "https://registry.yarnpkg.com/web-component-tester/-/web-component-tester-6.9.2.tgz#40a7b824f2cf3cbc4305552bdfc3357977ded48a"
integrity sha512-s2kB/+IE8XWcnxY1fqSpqTiiHEGHWgUWariAbiRlxmAvWSuvaCVNALHYebsZrLCNCLHKcJR8/sGv/bw0MWMvjw==