[golden] Diff page: Include grouping in URL params.

In a follow-up CL I will update the /json/v2/diff RPC to take a grouping, rather than a test name, as an argument.

Bug: skia:13712
Change-Id: I1c1b64fd7ab6cda199b7ed0f09d1b6500db94e1d
Reviewed-on: https://skia-review.googlesource.com/c/buildbot/+/576517
Reviewed-by: Kevin Lubick <kjlubick@google.com>
Commit-Queue: Leandro Lovisolo <lovisolo@google.com>
diff --git a/golden/modules/BUILD.bazel b/golden/modules/BUILD.bazel
index 418ffa2..94f9986 100644
--- a/golden/modules/BUILD.bazel
+++ b/golden/modules/BUILD.bazel
@@ -16,6 +16,10 @@
     name = "common_ts_lib",
     srcs = ["common.ts"],
     visibility = ["//visibility:public"],
+    deps = [
+        ":rpc_types_ts_lib",
+        "@npm//common-sk",
+    ],
 )
 
 ts_library(
diff --git a/golden/modules/common.ts b/golden/modules/common.ts
index 22811d4..968215f 100644
--- a/golden/modules/common.ts
+++ b/golden/modules/common.ts
@@ -1,3 +1,6 @@
+import { fromObject } from 'common-sk/modules/query';
+import { Params } from './rpc_types';
+
 /**
  * Takes a URL-encoded search query and returns that query with newlines between each of the
  * terms. This returned value should be easier for a human to understand.
@@ -62,12 +65,19 @@
  * @param crs Code review system. Optional, omit or use empty string for master branch.
  * @return {string}
  */
-export function diffPageHref(grouping: string, left: string, right: string, clID = '', crs = ''): string {
+export function diffPageHref(
+  grouping: Params,
+  left: string,
+  right: string,
+  clID = '',
+  crs = '',
+): string {
   if (!left || !right) {
     return '';
   }
 
-  const u = `/diff?test=${grouping}&left=${left}&right=${right}`;
+  const u = `/diff?grouping=${encodeURIComponent(fromObject(grouping))}`
+    + `&left=${left}&right=${right}`;
   if (clID) {
     return `${u}&changelist_id=${clID}&crs=${crs}`;
   }
diff --git a/golden/modules/common_test.ts b/golden/modules/common_test.ts
index f4d7046..ef27f81 100644
--- a/golden/modules/common_test.ts
+++ b/golden/modules/common_test.ts
@@ -59,18 +59,29 @@
 
 describe('diffPageHref', () => {
   it('returns a path with the digests in the expected order', () => {
-    expect(diffPageHref('my-test', aDigest, bDigest)).to.equal(
-      '/diff?test=my-test&left=aaab78c9711cb79197d47f448ba51338&right=bbb8b07beb4e1247c2cbafdb92b93e55',
+    expect(diffPageHref({ source_type: 'my-corpus', name: 'my-test' }, aDigest, bDigest)).to.equal(
+      '/diff?grouping=name%3Dmy-test%26source_type%3Dmy-corpus'
+        + '&left=aaab78c9711cb79197d47f448ba51338&right=bbb8b07beb4e1247c2cbafdb92b93e55',
     );
     // order matters
-    expect(diffPageHref('my-test', bDigest, aDigest)).to.equal(
-      '/diff?test=my-test&left=bbb8b07beb4e1247c2cbafdb92b93e55&right=aaab78c9711cb79197d47f448ba51338',
+    expect(diffPageHref({ source_type: 'my-corpus', name: 'my-test' }, bDigest, aDigest)).to.equal(
+      '/diff?grouping=name%3Dmy-test%26source_type%3Dmy-corpus'
+        + '&left=bbb8b07beb4e1247c2cbafdb92b93e55&right=aaab78c9711cb79197d47f448ba51338',
     );
   });
   it('supports an optional changelist id', () => {
-    expect(diffPageHref('my-test', aDigest, bDigest, '123456', 'github')).to.equal(
-      '/diff?test=my-test&left=aaab78c9711cb79197d47f448ba51338'
-      + '&right=bbb8b07beb4e1247c2cbafdb92b93e55&changelist_id=123456&crs=github',
+    expect(
+      diffPageHref(
+        { source_type: 'my-corpus', name: 'my-test' },
+        aDigest,
+        bDigest,
+        '123456',
+        'github',
+      ),
+    ).to.equal(
+      '/diff?grouping=name%3Dmy-test%26source_type%3Dmy-corpus'
+        + '&left=aaab78c9711cb79197d47f448ba51338'
+        + '&right=bbb8b07beb4e1247c2cbafdb92b93e55&changelist_id=123456&crs=github',
     );
   });
 });
diff --git a/golden/modules/details-page-sk/details-page-sk_puppeteer_test.ts b/golden/modules/details-page-sk/details-page-sk_puppeteer_test.ts
index 1608a94..47a00d7 100644
--- a/golden/modules/details-page-sk/details-page-sk_puppeteer_test.ts
+++ b/golden/modules/details-page-sk/details-page-sk_puppeteer_test.ts
@@ -70,7 +70,7 @@
 
       // This link should not have a changelist ID or CRS.
       expect(await detailsPageSkPO.digestDetailsSkPO.getDiffPageLink()).to.equal(
-        '/diff?test=My test has spaces'
+        '/diff?grouping=name%3DMy%2520test%2520has%2520spaces%26source_type%3Dinfra'
           + '&left=99c58c7002073346ff55f446d47d6311&right=6246b773851984c726cb2e1cb13510c2',
       );
     });
@@ -91,7 +91,7 @@
 
       // The changelist ID and CRS should be reflected in this link.
       expect(await detailsPageSkPO.digestDetailsSkPO.getDiffPageLink()).to.equal(
-        '/diff?test=My test has spaces'
+        '/diff?grouping=name%3DMy%2520test%2520has%2520spaces%26source_type%3Dinfra'
           + '&left=99c58c7002073346ff55f446d47d6311&right=6246b773851984c726cb2e1cb13510c2'
           + '&changelist_id=65432&crs=gerrit-internal',
       );
diff --git a/golden/modules/diff-page-sk/diff-page-sk-demo.ts b/golden/modules/diff-page-sk/diff-page-sk-demo.ts
index 075a7a7..412ca3d 100644
--- a/golden/modules/diff-page-sk/diff-page-sk-demo.ts
+++ b/golden/modules/diff-page-sk/diff-page-sk-demo.ts
@@ -24,7 +24,8 @@
 if (window.location.search.length === 0) {
   setQueryString(
     '?left=6246b773851984c726cb2e1cb13510c2&right=99c58c7002073346ff55f446d47d6311&'
-      + 'test=This%20is%20a%20test%20with%20spaces&changelist_id=12353&crs=gerrit',
+      + 'grouping=name%3DThis%2520is%2520a%2520test%2520with%2520spaces%26source_type%3Dinfra&'
+      + 'changelist_id=12353&crs=gerrit',
   );
 }
 
diff --git a/golden/modules/diff-page-sk/diff-page-sk.ts b/golden/modules/diff-page-sk/diff-page-sk.ts
index 2d4da22..1f06ae0 100644
--- a/golden/modules/diff-page-sk/diff-page-sk.ts
+++ b/golden/modules/diff-page-sk/diff-page-sk.ts
@@ -13,7 +13,7 @@
 import '../digest-details-sk';
 import { sendBeginTask, sendEndTask, sendFetchError } from '../common';
 import {
-  DigestComparison, GroupingsResponse, LeftDiffInfo, SRDiffDigest,
+  DigestComparison, GroupingsResponse, LeftDiffInfo, Params, SRDiffDigest,
 } from '../rpc_types';
 
 export class DiffPageSk extends ElementSk {
@@ -36,7 +36,7 @@
 
   private groupings: GroupingsResponse | null = null;
 
-  private grouping = '';
+  private grouping: Params = {};
 
   private leftDigest = '';
 
@@ -63,7 +63,7 @@
     this._stateChanged = stateReflector(
       /* getState */() => ({
         // provide empty values
-        test: this.grouping, // TODO(kjlubick) rename test -> grouping
+        grouping: this.grouping,
         left: this.leftDigest,
         right: this.rightDigest,
         changelist_id: this.changeListID,
@@ -73,7 +73,7 @@
           return;
         }
         // default values if not specified.
-        this.grouping = newState.test as string || '';
+        this.grouping = newState.grouping as Params || {};
         this.leftDigest = newState.left as string || '';
         this.rightDigest = newState.right as string || '';
         this.changeListID = newState.changelist_id as string || '';
@@ -116,9 +116,8 @@
     };
     sendBeginTask(this);
 
-    const urlBase = '/json/v2/diff';
-
-    const url = `${urlBase}?test=${encodeURIComponent(this.grouping)}`
+    // TODO(lovisolo): Replace with an RPC that takes groupings rather than test names.
+    const url = `/json/v2/diff?test=${encodeURIComponent(this.grouping.name)}`
       + `&left=${encodeURIComponent(this.leftDigest)}`
       + `&right=${encodeURIComponent(this.rightDigest)}`
       + `&changelist_id=${this.changeListID}&crs=${this.crs}`;
diff --git a/golden/modules/diff-page-sk/diff-page-sk_puppeteer_test.ts b/golden/modules/diff-page-sk/diff-page-sk_puppeteer_test.ts
index 024eb0c..4ae1c57 100644
--- a/golden/modules/diff-page-sk/diff-page-sk_puppeteer_test.ts
+++ b/golden/modules/diff-page-sk/diff-page-sk_puppeteer_test.ts
@@ -19,7 +19,7 @@
   // parameters in the below query string are different from said defaults. This allows this test
   // to verify that the page correctly parses out the query parameters.
   const baseParams = '?left=99c58c7002073346ff55f446d47d6311&right=6246b773851984c726cb2e1cb13510c2'
-      + '&test=My%20test%20has%20spaces';
+    + '&grouping=name%3DMy%2520test%2520has%2520spaces%26source_type%3Dinfra';
 
   it('should render the demo page', async () => {
     await navigateTo(testBed.page, testBed.baseUrl, baseParams);
@@ -51,8 +51,8 @@
 
       // This link should not have a changelist ID or CRS.
       expect(await diffPageSkPO.digestDetailsSkPO.getDiffPageLink()).to.equal(
-        '/diff?test=My test has spaces'
-              + '&left=99c58c7002073346ff55f446d47d6311&right=6246b773851984c726cb2e1cb13510c2',
+        '/diff?grouping=name%3DMy%2520test%2520has%2520spaces%26source_type%3Dinfra'
+          + '&left=99c58c7002073346ff55f446d47d6311&right=6246b773851984c726cb2e1cb13510c2',
       );
     });
 
@@ -70,7 +70,7 @@
 
       // The changelist ID and CRS should be reflected in this link.
       expect(await diffPageSkPO.digestDetailsSkPO.getDiffPageLink()).to.equal(
-        '/diff?test=My test has spaces'
+        '/diff?grouping=name%3DMy%2520test%2520has%2520spaces%26source_type%3Dinfra'
           + '&left=99c58c7002073346ff55f446d47d6311&right=6246b773851984c726cb2e1cb13510c2'
           + '&changelist_id=65432&crs=gerrit',
       );
diff --git a/golden/modules/diff-page-sk/diff-page-sk_test.ts b/golden/modules/diff-page-sk/diff-page-sk_test.ts
index af4f909..6e0b958 100644
--- a/golden/modules/diff-page-sk/diff-page-sk_test.ts
+++ b/golden/modules/diff-page-sk/diff-page-sk_test.ts
@@ -3,11 +3,9 @@
 import { expect } from 'chai';
 import { deepCopy } from 'common-sk/modules/object';
 import { eventPromise, eventSequencePromise, setUpElementUnderTest } from '../../../infra-sk/modules/test_util';
-import {
-  DigestComparison, DigestDetails, TriageRequestV3, TriageResponse,
-} from '../rpc_types';
+import { DigestComparison, TriageRequestV3, TriageResponse } from '../rpc_types';
 import { groupingsResponse } from '../search-page-sk/demo_data';
-import { twoHundredCommits, typicalDetails } from '../digest-details-sk/test_data';
+import { typicalDetails } from '../digest-details-sk/test_data';
 import { DiffPageSk } from './diff-page-sk';
 import { DiffPageSkPO } from './diff-page-sk_po';
 
diff --git a/golden/modules/digest-details-sk/digest-details-sk.ts b/golden/modules/digest-details-sk/digest-details-sk.ts
index 3a3f48b..736c4f5 100644
--- a/golden/modules/digest-details-sk/digest-details-sk.ts
+++ b/golden/modules/digest-details-sk/digest-details-sk.ts
@@ -117,20 +117,37 @@
     // TODO(kjlubick) would it be clearer to just tell the user the images differ in size and omit
     //  the (probably useless metrics)? Could we also include the actual dimensions of the two?
 
-    return html`
-      <div class=metrics_and_triage>
+    // We need the digest's grouping to compute a link to the diff page. If the digest has no
+    // params, we'll get an exception when computing the grouping. If we don't catch the exception,
+    // this whole element will fail to render.
+    let maybeGrouping: Params | null = null;
+    try {
+      maybeGrouping = ele.getGrouping();
+    } catch {
+      // Nothing to do.
+    }
+
+    // Only show a link to the diff page if we successfully computed the digest's grouping.
+    const diffPageLinkTemplate = maybeGrouping
+      ? html`
         <div>
           <a href=${diffPageHref(
-      ele._details.test,
-      ele._details.digest,
-      ele.right.digest,
-      ele._changeListID,
-      ele._crs,
-    )}
-             target=_blank rel=noopener class=diffpage_link>
+        ele.getGrouping(),
+        ele._details.digest,
+        ele.right.digest,
+        ele._changeListID,
+        ele._crs,
+      )}
+            target=_blank rel=noopener class=diffpage_link>
             Diff Details
           </a>
         </div>
+      `
+      : '';
+
+    return html`
+      <div class=metrics_and_triage>
+        ${diffPageLinkTemplate}
         <div class=size_warning ?hidden=${!ele.right.dimDiffer}>Images differ in size!</div>
         <div class=metric>
           <span>Diff metric:</span>
@@ -215,10 +232,10 @@
             @showblamelist=${ele.showBlamelist}>
         </dots-sk>
         <dots-legend-sk
+            .grouping=${ele.getGrouping()}
             .digests=${ele._details.traces.digests}
             .changeListID=${ele._changeListID}
             .crs=${ele._crs}
-            .test=${ele._details.test}
             .totalDigests=${ele._details.traces.total_digests || 0}>
         </dots-legend-sk>
       </div>
@@ -422,6 +439,39 @@
     this.setTriaged(newLabel);
   }
 
+  private getGrouping(): Params {
+    // Extract corpus.
+    const corpusKey = 'source_type';
+    if (!this._details.paramset[corpusKey]) {
+      throw new Error(`Digest is missing key "${corpusKey}".`);
+    }
+    if (this._details.paramset[corpusKey].length !== 1) {
+      throw new Error(
+        `Digest key "${corpusKey}" must have exactly one value;`
+        + `${this._details.paramset[corpusKey].length} values found.`,
+      );
+    }
+    const corpus = this._details.paramset[corpusKey][0];
+
+    // Build grouping.
+    const grouping: Params = {};
+    const groupingKeys = this._groupings.grouping_param_keys_by_corpus![corpus];
+    groupingKeys?.forEach((key) => {
+      if (!this._details.paramset[key]) {
+        throw new Error(`Digest is missing key "${key}"`);
+      }
+      if (this._details.paramset[key].length !== 1) {
+        throw new Error(
+          `Digest key ${key} must have exactly one value;`
+          + `${this._details.paramset[key].length} values found.`,
+        );
+      }
+      grouping[key] = this._details.paramset[key][0];
+    });
+
+    return grouping;
+  }
+
   setTriaged(label: Label): void {
     // We save the label before the triage action because the search page might change the label
     // when it handles the "triage" event, see
@@ -432,38 +482,16 @@
       new CustomEvent<Label>('triage', { bubbles: true, detail: label }),
     );
 
-    // Extract corpus.
-    const corpusKey = 'source_type';
-    if (!this._details.paramset[corpusKey]) {
-      errorMessage(`Digest is missing key "${corpusKey}".`);
-      return;
-    }
-    if (this._details.paramset[corpusKey].length !== 1) {
-      errorMessage(
-        `Digest key "${corpusKey}" must have exactly one value;`
-        + `${this._details.paramset[corpusKey].length} values found.`,
-      );
-      return;
-    }
-    const corpus = this._details.paramset[corpusKey][0];
-
-    // Build grouping.
-    const grouping: Params = {};
-    const groupingKeys = this._groupings.grouping_param_keys_by_corpus![corpus];
-    groupingKeys?.forEach((key) => {
-      if (!this._details.paramset[key]) {
-        errorMessage(`Digest is missing key "${key}"`);
+    let grouping: Params;
+    try {
+      grouping = this.getGrouping();
+    } catch (e) {
+      if (e instanceof Error) {
+        errorMessage(e.message);
         return;
       }
-      if (this._details.paramset[key].length !== 1) {
-        errorMessage(
-          `Digest key ${key} must have exactly one value;`
-          + `${this._details.paramset[key].length} values found.`,
-        );
-        return;
-      }
-      grouping[key] = this._details.paramset[key][0];
-    });
+      throw e;
+    }
 
     const triageRequest: TriageRequestV3 = {
       deltas: [
diff --git a/golden/modules/digest-details-sk/digest-details-sk_test.ts b/golden/modules/digest-details-sk/digest-details-sk_test.ts
index dbfea88..62d25f6 100644
--- a/golden/modules/digest-details-sk/digest-details-sk_test.ts
+++ b/golden/modules/digest-details-sk/digest-details-sk_test.ts
@@ -58,7 +58,7 @@
 
     it('shows the metrics and the link to the diff page', async () => {
       expect(await digestDetailsSkPO.getDiffPageLink()).to.equal(
-        '/diff?test=dots-legend-sk_too-many-digests'
+        '/diff?grouping=name%3Ddots-legend-sk_too-many-digests%26source_type%3Dinfra'
             + '&left=6246b773851984c726cb2e1cb13510c2&right=99c58c7002073346ff55f446d47d6311',
       );
 
@@ -200,8 +200,9 @@
       ]);
 
       expect(await digestDetailsSkPO.getDiffPageLink()).to.equal(
-        '/diff?test=dots-legend-sk_too-many-digests&left=6246b773851984c726cb2e1cb13510c2'
-            + '&right=99c58c7002073346ff55f446d47d6311&changelist_id=12345&crs=github',
+        '/diff?grouping=name%3Ddots-legend-sk_too-many-digests%26source_type%3Dinfra'
+        + '&left=6246b773851984c726cb2e1cb13510c2&right=99c58c7002073346ff55f446d47d6311'
+        + '&changelist_id=12345&crs=github',
       );
     });
 
diff --git a/golden/modules/dots-legend-sk/dots-legend-sk-demo.ts b/golden/modules/dots-legend-sk/dots-legend-sk-demo.ts
index 423c5bb..6b18f16 100644
--- a/golden/modules/dots-legend-sk/dots-legend-sk-demo.ts
+++ b/golden/modules/dots-legend-sk/dots-legend-sk-demo.ts
@@ -24,9 +24,9 @@
 ) {
   const dotsLegendSk = new DotsLegendSk();
   dotsLegendSk.id = id;
+  dotsLegendSk.grouping = { source_type: 'my-corpus', name: test };
   dotsLegendSk.digests = digests;
   dotsLegendSk.changeListID = clID;
-  dotsLegendSk.test = test;
   dotsLegendSk.totalDigests = digests.length;
   document.querySelector(parentSelector)!.appendChild(dotsLegendSk);
 }
diff --git a/golden/modules/dots-legend-sk/dots-legend-sk.ts b/golden/modules/dots-legend-sk/dots-legend-sk.ts
index a61a87e..d57afcf 100644
--- a/golden/modules/dots-legend-sk/dots-legend-sk.ts
+++ b/golden/modules/dots-legend-sk/dots-legend-sk.ts
@@ -14,7 +14,7 @@
   MAX_UNIQUE_DIGESTS,
 } from '../dots-sk/constants';
 import { detailHref, diffPageHref } from '../common';
-import { DigestStatus, Label } from '../rpc_types';
+import { DigestStatus, Label, Params } from '../rpc_types';
 
 import 'elements-sk/icon/cancel-icon-sk';
 import 'elements-sk/icon/check-circle-icon-sk';
@@ -34,9 +34,7 @@
     <a target=_blank class=digest href="${el.digestDetailHref(index)}">${digest.digest}</a>
     ${DotsLegendSk.statusIconTemplate(digest.status)}
     ${index > 0
-    ? html`<a target=_blank class=diff href="${el.digestDiffHref(index)}">
-                 diff
-               </a>`
+    ? html`<a target=_blank class=diff href="${el.digestDiffHref(index)}">diff</a>`
     : html`<span></span>`}
   `;
 
@@ -85,14 +83,14 @@
     }
   };
 
+  private _grouping: Params = {};
+
   private _digests: DigestStatus[] = [];
 
   private _changeListID = '';
 
   private _crs = '';
 
-  private _test = '';
-
   private _totalDigests = 0;
 
   constructor() {
@@ -104,6 +102,14 @@
     this._render();
   }
 
+  /** Grouping. */
+  get grouping(): Params { return this._grouping; }
+
+  set grouping(grouping: Params) {
+    this._grouping = grouping;
+    this._render();
+  }
+
   /** The digests to show. */
   get digests(): DigestStatus[] { return this._digests; }
 
@@ -128,14 +134,6 @@
     this._render();
   }
 
-  /** Test name. */
-  get test(): string { return this._test; }
-
-  set test(test: string) {
-    this._test = test;
-    this._render();
-  }
-
   /**
    * The total number of digests that were seen in this group of traces, which can be more than
    * digests.length, due to the fact that the backend limits the length of digests when it sends it
@@ -149,12 +147,17 @@
   }
 
   private digestDetailHref(index: number): string {
-    return detailHref(this._test, this._digests[index].digest, this.changeListID, this.crs);
+    return detailHref(this.grouping.name, this._digests[index].digest, this.changeListID, this.crs);
   }
 
   private digestDiffHref(index: number): string {
-    return diffPageHref(this._test, this._digests[0].digest, this._digests[index].digest,
-      this.changeListID, this.crs);
+    return diffPageHref(
+      this._grouping,
+      this._digests[0].digest,
+      this._digests[index].digest,
+      this.changeListID,
+      this.crs,
+    );
   }
 }
 
diff --git a/golden/modules/dots-legend-sk/dots-legend-sk_test.ts b/golden/modules/dots-legend-sk/dots-legend-sk_test.ts
index 4cabdc4..49be595 100644
--- a/golden/modules/dots-legend-sk/dots-legend-sk_test.ts
+++ b/golden/modules/dots-legend-sk/dots-legend-sk_test.ts
@@ -22,7 +22,7 @@
 
   describe('with less than MAX_UNIQUE_DIGESTS unique digests', () => {
     beforeEach(() => {
-      dotsLegendSk.test = 'My Test';
+      dotsLegendSk.grouping = { source_type: 'my-corpus', name: 'My Test' };
       dotsLegendSk.digests = [
         { digest: '00000000000000000000000000000000', status: 'untriaged' },
         { digest: '11111111111111111111111111111111', status: 'positive' },
@@ -78,7 +78,9 @@
     });
 
     it('renders diff links correctly', async () => {
-      const diffHrefFor = (d: string) => `/diff?test=My Test&left=00000000000000000000000000000000&right=${d}`;
+      const diffHrefFor = (d: string) => '/diff?'
+        + 'grouping=name%3DMy%2520Test%26source_type%3Dmy-corpus&'
+        + `left=00000000000000000000000000000000&right=${d}`;
       expect(await dotsLegendSkPO.getDiffHrefs()).to.deep.equal([
         diffHrefFor('11111111111111111111111111111111'),
         diffHrefFor('22222222222222222222222222222222'),
@@ -89,7 +91,7 @@
 
     describe('with CL ID and crs', () => {
       beforeEach(() => {
-        dotsLegendSk.test = 'My Test';
+        dotsLegendSk.grouping = { source_type: 'my-corpus', name: 'My Test' };
         dotsLegendSk.changeListID = '123456';
         dotsLegendSk.crs = 'gerrit';
       });
@@ -106,8 +108,9 @@
       });
 
       it('renders diff links correctly', async () => {
-        const diffHrefFor = (d: string) => '/diff?test=My Test&left=00000000000000000000000000000000'
-            + `&right=${d}&changelist_id=123456&crs=gerrit`;
+        const diffHrefFor = (d: string) => '/diff?'
+          + 'grouping=name%3DMy%2520Test%26source_type%3Dmy-corpus&'
+          + `left=00000000000000000000000000000000&right=${d}&changelist_id=123456&crs=gerrit`;
         expect(await dotsLegendSkPO.getDiffHrefs()).to.deep.equal([
           diffHrefFor('11111111111111111111111111111111'),
           diffHrefFor('22222222222222222222222222222222'),
@@ -120,7 +123,7 @@
 
   describe('with exactly MAX_UNIQUE_DIGESTS unique digests', () => {
     beforeEach(() => {
-      dotsLegendSk.test = 'My Test';
+      dotsLegendSk.grouping = { source_type: 'my-corpus', name: 'My Test' };
       dotsLegendSk.digests = [
         { digest: '00000000000000000000000000000000', status: 'untriaged' },
         { digest: '11111111111111111111111111111111', status: 'positive' },
@@ -180,7 +183,9 @@
     });
 
     it('renders diff links correctly', async () => {
-      const diffHrefFor = (d: string) => `/diff?test=My Test&left=00000000000000000000000000000000&right=${d}`;
+      const diffHrefFor = (d: string) => '/diff?'
+        + 'grouping=name%3DMy%2520Test%26source_type%3Dmy-corpus&'
+        + `left=00000000000000000000000000000000&right=${d}`;
       expect(await dotsLegendSkPO.getDiffHrefs()).to.deep.equal([
         diffHrefFor('11111111111111111111111111111111'),
         diffHrefFor('22222222222222222222222222222222'),
@@ -196,7 +201,7 @@
 
   describe('with more than MAX_UNIQUE_DIGESTS unique digests', () => {
     beforeEach(() => {
-      dotsLegendSk.test = 'My Test';
+      dotsLegendSk.grouping = { source_type: 'my-corpus', name: 'My Test' };
       dotsLegendSk.digests = [
         { digest: '00000000000000000000000000000000', status: 'untriaged' },
         { digest: '11111111111111111111111111111111', status: 'positive' },
@@ -259,7 +264,9 @@
     });
 
     it('renders diff links correctly', async () => {
-      const diffHrefFor = (d: string) => `/diff?test=My Test&left=00000000000000000000000000000000&right=${d}`;
+      const diffHrefFor = (d: string) => '/diff?'
+        + 'grouping=name%3DMy%2520Test%26source_type%3Dmy-corpus&'
+        + `left=00000000000000000000000000000000&right=${d}`;
       expect(await dotsLegendSkPO.getDiffHrefs()).to.deep.equal([
         diffHrefFor('11111111111111111111111111111111'),
         diffHrefFor('22222222222222222222222222222222'),