Merge "Fix copy behavior in comment textarea"
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/VisibleRefFilterIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/RefAdvertisementIT.java
similarity index 62%
rename from gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/VisibleRefFilterIT.java
rename to gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/RefAdvertisementIT.java
index fd2385b..521ccc4 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/VisibleRefFilterIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/RefAdvertisementIT.java
@@ -15,6 +15,7 @@
package com.google.gerrit.acceptance.git;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.common.truth.TruthJUnit.assume;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
@@ -34,18 +35,25 @@
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.config.AnonymousCowardName;
import com.google.gerrit.server.edit.ChangeEditModifier;
import com.google.gerrit.server.git.ProjectConfig;
+import com.google.gerrit.server.git.ReceiveCommitsAdvertiseRefsHook;
import com.google.gerrit.server.git.SearchingChangeCacheImpl;
import com.google.gerrit.server.git.TagCache;
import com.google.gerrit.server.git.VisibleRefFilter;
+import com.google.gerrit.server.notedb.ChangeNoteUtil;
import com.google.gerrit.server.project.ProjectControl;
import com.google.gerrit.server.project.Util;
+import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.testutil.DisabledReviewDb;
+import com.google.gerrit.testutil.TestChanges;
import com.google.inject.Inject;
import com.google.inject.Provider;
+import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
@@ -53,11 +61,12 @@
import org.junit.Test;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
@NoHttpd
-public class VisibleRefFilterIT extends AbstractDaemonTest {
+public class RefAdvertisementIT extends AbstractDaemonTest {
@Inject
private ChangeEditModifier editModifier;
@@ -74,12 +83,23 @@
@Inject
private Provider<CurrentUser> userProvider;
+ @Inject
+ private ChangeNoteUtil noteUtil;
+
+ @Inject
+ @AnonymousCowardName
+ private String anonymousCowardName;
+
private AccountGroup.UUID admins;
- private Change.Id c1;
- private Change.Id c2;
+ private ChangeData c1;
+ private ChangeData c2;
+ private ChangeData c3;
+ private ChangeData c4;
private String r1;
private String r2;
+ private String r3;
+ private String r4;
@Before
public void setUp() throws Exception {
@@ -111,17 +131,31 @@
.branch("branch")
.create(new BranchInput());
+ // First 2 changes are merged, which means the tags pointing to them are
+ // visible.
allow(Permission.SUBMIT, admins, "refs/for/refs/heads/*");
PushOneCommit.Result mr = pushFactory.create(db, admin.getIdent(), testRepo)
.to("refs/for/master%submit");
mr.assertOkStatus();
- c1 = mr.getChange().getId();
- r1 = changeRefPrefix(c1);
+ c1 = mr.getChange();
+ r1 = changeRefPrefix(c1.getId());
PushOneCommit.Result br = pushFactory.create(db, admin.getIdent(), testRepo)
.to("refs/for/branch%submit");
br.assertOkStatus();
- c2 = br.getChange().getId();
- r2 = changeRefPrefix(c2);
+ c2 = br.getChange();
+ r2 = changeRefPrefix(c2.getId());
+
+ // Second 2 changes are unmerged.
+ mr = pushFactory.create(db, admin.getIdent(), testRepo)
+ .to("refs/for/master");
+ mr.assertOkStatus();
+ c3 = mr.getChange();
+ r3 = changeRefPrefix(c3.getId());
+ br = pushFactory.create(db, admin.getIdent(), testRepo)
+ .to("refs/for/branch");
+ br.assertOkStatus();
+ c4 = br.getChange();
+ r4 = changeRefPrefix(c4.getId());
try (Repository repo = repoManager.openRepository(project)) {
// master-tag -> master
@@ -139,7 +173,7 @@
}
@Test
- public void allRefsVisibleNoRefsMetaConfig() throws Exception {
+ public void uploadPackAllRefsVisibleNoRefsMetaConfig() throws Exception {
ProjectConfig cfg = projectCache.checkedGet(project).getConfig();
Util.allow(cfg, Permission.READ, REGISTERED_USERS, "refs/*");
Util.allow(cfg, Permission.READ, admins, RefNames.REFS_CONFIG);
@@ -147,12 +181,16 @@
saveProjectConfig(project, cfg);
setApiUser(user);
- assertRefs(
+ assertUploadPackRefs(
"HEAD",
r1 + "1",
r1 + "meta",
r2 + "1",
r2 + "meta",
+ r3 + "1",
+ r3 + "meta",
+ r4 + "1",
+ r4 + "meta",
"refs/heads/branch",
"refs/heads/master",
"refs/tags/branch-tag",
@@ -160,16 +198,20 @@
}
@Test
- public void allRefsVisibleWithRefsMetaConfig() throws Exception {
+ public void uploadPackAllRefsVisibleWithRefsMetaConfig() throws Exception {
allow(Permission.READ, REGISTERED_USERS, "refs/*");
allow(Permission.READ, REGISTERED_USERS, RefNames.REFS_CONFIG);
- assertRefs(
+ assertUploadPackRefs(
"HEAD",
r1 + "1",
r1 + "meta",
r2 + "1",
r2 + "meta",
+ r3 + "1",
+ r3 + "meta",
+ r4 + "1",
+ r4 + "meta",
"refs/heads/branch",
"refs/heads/master",
RefNames.REFS_CONFIG,
@@ -178,28 +220,32 @@
}
@Test
- public void subsetOfBranchesVisibleIncludingHead() throws Exception {
+ public void uploadPackSubsetOfBranchesVisibleIncludingHead() throws Exception {
allow(Permission.READ, REGISTERED_USERS, "refs/heads/master");
deny(Permission.READ, REGISTERED_USERS, "refs/heads/branch");
setApiUser(user);
- assertRefs(
+ assertUploadPackRefs(
"HEAD",
r1 + "1",
r1 + "meta",
+ r3 + "1",
+ r3 + "meta",
"refs/heads/master",
"refs/tags/master-tag");
}
@Test
- public void subsetOfBranchesVisibleNotIncludingHead() throws Exception {
+ public void uploadPackSubsetOfBranchesVisibleNotIncludingHead() throws Exception {
deny(Permission.READ, REGISTERED_USERS, "refs/heads/master");
allow(Permission.READ, REGISTERED_USERS, "refs/heads/branch");
setApiUser(user);
- assertRefs(
+ assertUploadPackRefs(
r2 + "1",
r2 + "meta",
+ r4 + "1",
+ r4 + "meta",
"refs/heads/branch",
"refs/tags/branch-tag",
// master branch is not visible but master-tag is reachable from branch
@@ -208,12 +254,12 @@
}
@Test
- public void subsetOfBranchesVisibleWithEdit() throws Exception {
+ public void uploadPackSubsetOfBranchesVisibleWithEdit() throws Exception {
allow(Permission.READ, REGISTERED_USERS, "refs/heads/master");
deny(Permission.READ, REGISTERED_USERS, "refs/heads/branch");
- Change c = notesFactory.createChecked(db, project, c1).getChange();
- PatchSet ps1 = getPatchSet(new PatchSet.Id(c1, 1));
+ Change c = notesFactory.createChecked(db, project, c1.getId()).getChange();
+ PatchSet ps1 = getPatchSet(new PatchSet.Id(c1.getId(), 1));
// Admin's edit is not visible.
setApiUser(admin);
@@ -223,59 +269,64 @@
setApiUser(user);
editModifier.createEdit(c, ps1);
- assertRefs(
+ assertUploadPackRefs(
"HEAD",
r1 + "1",
r1 + "meta",
+ r3 + "1",
+ r3 + "meta",
"refs/heads/master",
"refs/tags/master-tag",
- "refs/users/01/1000001/edit-" + c1.get() + "/1");
+ "refs/users/01/1000001/edit-" + c1.getId() + "/1");
}
@Test
- public void subsetOfRefsVisibleWithAccessDatabase() throws Exception {
+ public void uploadPackSubsetOfRefsVisibleWithAccessDatabase() throws Exception {
allowGlobalCapabilities(REGISTERED_USERS, GlobalCapability.ACCESS_DATABASE);
try {
deny(Permission.READ, REGISTERED_USERS, "refs/heads/master");
allow(Permission.READ, REGISTERED_USERS, "refs/heads/branch");
- Change c = notesFactory.createChecked(db, project, c1).getChange();
- PatchSet ps1 = getPatchSet(new PatchSet.Id(c1, 1));
+ PatchSet ps1 = getPatchSet(new PatchSet.Id(c1.getId(), 1));
setApiUser(admin);
- editModifier.createEdit(c, ps1);
+ editModifier.createEdit(c1.change(), ps1);
setApiUser(user);
- assertRefs(
+ assertUploadPackRefs(
// Change 1 is visible due to accessDatabase capability, even though
// refs/heads/master is not.
r1 + "1",
r1 + "meta",
r2 + "1",
r2 + "meta",
+ r3 + "1",
+ r3 + "meta",
+ r4 + "1",
+ r4 + "meta",
"refs/heads/branch",
"refs/tags/branch-tag",
// See comment in subsetOfBranchesVisibleNotIncludingHead.
"refs/tags/master-tag",
// All edits are visible due to accessDatabase capability.
- "refs/users/00/1000000/edit-" + c1.get() + "/1");
+ "refs/users/00/1000000/edit-" + c1.getId() + "/1");
} finally {
removeGlobalCapabilities(REGISTERED_USERS, GlobalCapability.ACCESS_DATABASE);
}
}
@Test
- public void draftRefs() throws Exception {
+ public void uploadPackDraftRefs() throws Exception {
allow(Permission.READ, REGISTERED_USERS, "refs/heads/*");
PushOneCommit.Result br = pushFactory.create(db, admin.getIdent(), testRepo)
.to("refs/drafts/master");
br.assertOkStatus();
- Change.Id c3 = br.getChange().getId();
- String r3 = changeRefPrefix(c3);
+ Change.Id c5 = br.getChange().getId();
+ String r5 = changeRefPrefix(c5);
- // Only admin can see admin's draft change.
+ // Only admin can see admin's draft change (5).
setApiUser(admin);
- assertRefs(
+ assertUploadPackRefs(
"HEAD",
r1 + "1",
r1 + "meta",
@@ -283,6 +334,10 @@
r2 + "meta",
r3 + "1",
r3 + "meta",
+ r4 + "1",
+ r4 + "meta",
+ r5 + "1",
+ r5 + "meta",
"refs/heads/branch",
"refs/heads/master",
RefNames.REFS_CONFIG,
@@ -291,12 +346,16 @@
// user can't.
setApiUser(user);
- assertRefs(
+ assertUploadPackRefs(
"HEAD",
r1 + "1",
r1 + "meta",
r2 + "1",
r2 + "meta",
+ r3 + "1",
+ r3 + "meta",
+ r4 + "1",
+ r4 + "meta",
"refs/heads/branch",
"refs/heads/master",
"refs/tags/branch-tag",
@@ -304,7 +363,7 @@
}
@Test
- public void noSearchingChangeCacheImpl() throws Exception {
+ public void uploadPackNoSearchingChangeCacheImpl() throws Exception {
allow(Permission.READ, REGISTERED_USERS, "refs/heads/*");
setApiUser(user);
@@ -320,6 +379,10 @@
r1 + "meta",
r2 + "1",
r2 + "meta",
+ r3 + "1",
+ r3 + "meta",
+ r4 + "1",
+ r4 + "meta",
"refs/heads/branch",
"refs/heads/master",
"refs/tags/branch-tag",
@@ -328,7 +391,7 @@
}
@Test
- public void sequencesWithAccessDatabase() throws Exception {
+ public void uploadPackSequencesWithAccessDatabase() throws Exception {
assume().that(notesMigration.readChangeSequence()).isTrue();
try (Repository repo = repoManager.openRepository(allProjects)) {
setApiUser(user);
@@ -348,6 +411,82 @@
}
}
+ @Test
+ public void receivePackListsOpenChangesAsAdditionalHaves() throws Exception {
+ ReceiveCommitsAdvertiseRefsHook.Result r = getReceivePackRefs();
+ assertThat(r.allRefs().keySet()).containsExactly(
+ // meta refs are excluded even when NoteDb is enabled.
+ "HEAD",
+ "refs/heads/branch",
+ "refs/heads/master",
+ "refs/meta/config",
+ "refs/tags/branch-tag",
+ "refs/tags/master-tag");
+ assertThat(r.additionalHaves()).containsExactly(obj(c3, 1), obj(c4, 1));
+ }
+
+ @Test
+ public void receivePackRespectsVisibilityOfOpenChanges() throws Exception {
+ allow(Permission.READ, REGISTERED_USERS, "refs/heads/master");
+ deny(Permission.READ, REGISTERED_USERS, "refs/heads/branch");
+ setApiUser(user);
+
+ assertThat(getReceivePackRefs().additionalHaves())
+ .containsExactly(obj(c3, 1));
+ }
+
+ @Test
+ public void receivePackListsOnlyLatestPatchSet() throws Exception {
+ testRepo.reset(obj(c3, 1));
+ PushOneCommit.Result r = amendChange(c3.change().getKey().get());
+ r.assertOkStatus();
+ c3 = r.getChange();
+ assertThat(getReceivePackRefs().additionalHaves())
+ .containsExactly(obj(c3, 2), obj(c4, 1));
+ }
+
+ @Test
+ public void receivePackOmitsMissingObject() throws Exception {
+ // Use the tactic from ConsistencyCheckerIT to insert a new patch set with a
+ // missing object.
+ String rev = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
+ try (Repository repo = repoManager.openRepository(project)) {
+ TestRepository<?> tr = new TestRepository<>(repo);
+ String subject = "Subject for missing commit";
+ Change c = new Change(c3.change());
+ PatchSet.Id psId = new PatchSet.Id(c3.getId(), 2);
+ c.setCurrentPatchSet(psId, subject, c.getOriginalSubject());
+
+ PatchSet ps = TestChanges.newPatchSet(psId, rev, admin.getId());
+ db.patchSets().insert(Collections.singleton(ps));
+ db.changes().update(Collections.singleton(c));
+
+ if (notesMigration.commitChangeWrites()) {
+ PersonIdent committer = serverIdent.get();
+ PersonIdent author = noteUtil.newIdent(
+ accountCache.get(admin.getId()).getAccount(),
+ committer.getWhen(),
+ committer,
+ anonymousCowardName);
+ tr.branch(RefNames.changeMetaRef(c3.getId()))
+ .commit()
+ .author(author)
+ .committer(committer)
+ .message(
+ "Update patch set " + psId.get() + "\n"
+ + "\n"
+ + "Patch-set: " + psId.get() + "\n"
+ + "Commit: " + rev + "\n"
+ + "Subject: " + subject + "\n")
+ .create();
+ }
+ indexer.index(db, c.getProject(), c.getId());
+ }
+
+ assertThat(getReceivePackRefs().additionalHaves())
+ .containsExactly(obj(c4, 1));
+ }
+
/**
* Assert that refs seen by a non-admin user match expected.
*
@@ -356,7 +495,8 @@
* from the expected list before comparing to the actual results.
* @throws Exception
*/
- private void assertRefs(String... expectedWithMeta) throws Exception {
+ private void assertUploadPackRefs(String... expectedWithMeta)
+ throws Exception {
try (Repository repo = repoManager.openRepository(project)) {
assertRefs(
repo,
@@ -391,6 +531,15 @@
}
}
+ private ReceiveCommitsAdvertiseRefsHook.Result getReceivePackRefs()
+ throws Exception {
+ ReceiveCommitsAdvertiseRefsHook hook =
+ new ReceiveCommitsAdvertiseRefsHook(queryProvider, project);
+ try (Repository repo = repoManager.openRepository(project)) {
+ return hook.advertiseRefs(repo.getAllRefs());
+ }
+ }
+
private ProjectControl projectControl() throws Exception {
return projectControlFactory.controlFor(project, userProvider.get());
}
@@ -402,4 +551,12 @@
projectControlFactory.controlFor(project, userProvider.get()),
db, true);
}
+
+ private static ObjectId obj(ChangeData cd, int psNum) throws Exception {
+ PatchSet.Id psId = new PatchSet.Id(cd.getId(), psNum);
+ PatchSet ps = cd.patchSet(psId);
+ assertWithMessage("%s not found in %s", psId, cd.patchSets()).that(ps)
+ .isNotNull();
+ return ObjectId.fromString(ps.getRevision().get());
+ }
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommitsAdvertiseRefsHook.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommitsAdvertiseRefsHook.java
index 51c2a80..5df6caf 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommitsAdvertiseRefsHook.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommitsAdvertiseRefsHook.java
@@ -16,11 +16,15 @@
import static org.eclipse.jgit.lib.RefDatabase.ALL;
+import com.google.auto.value.AutoValue;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
+import com.google.gerrit.server.index.change.ChangeField;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.gerrit.server.util.MagicBranch;
@@ -46,6 +50,13 @@
private static final Logger log = LoggerFactory
.getLogger(ReceiveCommitsAdvertiseRefsHook.class);
+ @VisibleForTesting
+ @AutoValue
+ public abstract static class Result {
+ public abstract Map<String, Ref> allRefs();
+ public abstract Set<ObjectId> additionalHaves();
+ }
+
private final Provider<InternalChangeQuery> queryProvider;
private final Project.NameKey projectName;
@@ -77,28 +88,46 @@
throw ex;
}
}
+ Result r = advertiseRefs(oldRefs);
+ rp.setAdvertisedRefs(r.allRefs(), r.additionalHaves());
+ }
+
+ @VisibleForTesting
+ public Result advertiseRefs(Map<String, Ref> oldRefs) {
Map<String, Ref> r = Maps.newHashMapWithExpectedSize(oldRefs.size());
+ Set<ObjectId> allPatchSets = Sets.newHashSetWithExpectedSize(oldRefs.size());
for (Map.Entry<String, Ref> e : oldRefs.entrySet()) {
String name = e.getKey();
if (!skip(name)) {
r.put(name, e.getValue());
}
+ if (name.startsWith(RefNames.REFS_CHANGES)) {
+ allPatchSets.add(e.getValue().getObjectId());
+ }
}
- rp.setAdvertisedRefs(r, advertiseOpenChanges());
+ return new AutoValue_ReceiveCommitsAdvertiseRefsHook_Result(
+ r, advertiseOpenChanges(allPatchSets));
}
- private Set<ObjectId> advertiseOpenChanges() {
+ private Set<ObjectId> advertiseOpenChanges(Set<ObjectId> allPatchSets) {
// Advertise some recent open changes, in case a commit is based on one.
int limit = 32;
try {
Set<ObjectId> r = Sets.newHashSetWithExpectedSize(limit);
for (ChangeData cd : queryProvider.get()
+ .setRequestedFields(ImmutableSet.of(ChangeField.PATCH_SET.getName()))
.enforceVisibility(true)
.setLimit(limit)
.byProjectOpen(projectName)) {
PatchSet ps = cd.currentPatchSet();
if (ps != null) {
- r.add(ObjectId.fromString(ps.getRevision().get()));
+ ObjectId id = ObjectId.fromString(ps.getRevision().get());
+ // Ensure we actually observed a patch set ref pointing to this
+ // object, in case the database is out of sync with the repo and the
+ // object doesn't actually exist.
+ if (allPatchSets.contains(id)) {
+ r.add(id);
+ }
}
}
return r;
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html
index 108ac92..3ad2d257 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html
@@ -59,6 +59,9 @@
.notApproved {
background-color: #ffd4d4;
}
+ .labelStatus {
+ max-width: 9em;
+ }
@media screen and (max-width: 50em), screen and (min-width: 75em) {
:host {
display: table;
@@ -174,6 +177,14 @@
</span>
</section>
</template>
+ <template is="dom-if" if="[[_showLabelStatus]]">
+ <section>
+ <span class="title">Label Status</span>
+ <span class="value labelStatus">
+ [[_computeSubmitStatus(change.labels)]]
+ </span>
+ </section>
+ </template>
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
</template>
<script src="gr-change-metadata.js"></script>
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.js b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.js
index 661a296..184215e 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.js
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.js
@@ -37,6 +37,10 @@
type: Boolean,
computed: '_computeShowReviewersByState(serverConfig)',
},
+ _showLabelStatus: {
+ type: Boolean,
+ computed: '_computeShowLabelStatus(change)',
+ },
},
behaviors: [
@@ -143,5 +147,30 @@
}
}.bind(this));
},
+
+ _computeShowLabelStatus: function(change) {
+ var isNewChange = change.status === this.ChangeStatus.NEW;
+ var hasLabels = Object.keys(change.labels).length > 0;
+ return isNewChange && hasLabels;
+ },
+
+ _computeSubmitStatus: function(labels) {
+ var missingLabels = [];
+ var output = '';
+ for (var label in labels) {
+ var obj = labels[label];
+ if (!obj.optional && !obj.approved) {
+ missingLabels.push(label);
+ }
+ }
+ if (missingLabels.length) {
+ output += 'Needs ';
+ output += missingLabels.join(' and ');
+ output += missingLabels.length > 1 ? ' labels' : ' label';
+ } else {
+ output = 'Ready to ubmit';
+ }
+ return output;
+ },
});
})();
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.html
index 22080e8..281636c 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.html
@@ -78,6 +78,22 @@
assert.isTrue(hasCc());
});
+ test('computes submit status', function() {
+ var labels = {};
+ assert.equal(element._computeSubmitStatus(labels), 'Ready to Submit');
+ labels = { test: {} };
+ assert.equal(element._computeSubmitStatus(labels), 'Needs test Label');
+ labels.test.approved = true;
+ assert.equal(element._computeSubmitStatus(labels), 'Ready to Submit');
+ labels.test.approved = false;
+ labels.test.optional = true;
+ assert.equal(element._computeSubmitStatus(labels), 'Ready to Submit');
+ labels.test.optional = false;
+ labels.test2 = {};
+ assert.equal(element._computeSubmitStatus(labels),
+ 'Needs test and test2 Labels');
+ });
+
suite('remove reviewer votes', function() {
var sandbox;
setup(function() {