OXYGENHUB

Coverage / src/diffusionview.ts 91.5%

65 of 71 lines run, 9 of 9 functions, 21 of 28 branches · run #23 on main · run missed

10×
// Diffusion in the editor, without VS Code (oxygenhub-vscode#5): how a pin
20×
// between an upstream and its consumer looks. The hub's pill has two halves,
30×
// the upstream's state and the consumer's; a tree row has one icon, so it
40×
// shows the more urgent of the two and says both in words.
51×
6
import type { DiffusionHalf, DiffusionPin } from "./hubapi";
71×
80×
/** A codicon and a theme colour id. */
9
export interface Look {
10
  icon: string;
11
  color: string;
12
}
131×
140×
/** Most urgent first: a failure, then what nothing checked, then waiting. */
151×
const URGENCY = ["red", "amber", "grey", "green", "off"];
161×
171×
/** The tone a row shows: the more urgent half, ignoring a consumer that does not follow. */
181×
export function tone(pin: DiffusionPin): string {
194×
  const tones = [pin.upstream_state.tone, pin.consumer_state.tone].filter((t) => t !== "off");
204×
  return tones.sort((a, b) => rank(a) - rank(b))[0] ?? "off";
214×
}
221×
234×
function rank(t: string): number {
244×
  const i = URGENCY.indexOf(t);
254×
  return i < 0 ? URGENCY.length : i;
263×
}
273×
283×
export function look(t: string): Look {
293×
  switch (t) {
303×
    case "green":
313×
      return { icon: "pass-filled", color: "testing.iconPassed" };
323×
    case "red":
333×
      return { icon: "error", color: "testing.iconFailed" };
343×
    case "amber":
353×
      return { icon: "warning", color: "list.warningForeground" };
363×
    case "grey":
373×
      return { icon: "clock", color: "testing.iconQueued" };
383×
    default:
393×
      return { icon: "circle-outline", color: "disabledForeground" };
403×
  }
413×
}
421×
431×
/** The row's name: the repository on the other end of the pin. */
441×
export function pinLabel(pin: DiffusionPin, side: "takes" | "gives"): string {
452×
  return side === "takes" ? pin.upstream : pin.consumer;
463×
}
473×
483×
/** "untested │ passes · 2 behind · bump #304", as the hub's pill reads. */
493×
export function pinDescription(pin: DiffusionPin): string {
503×
  const parts = [`${pin.upstream_state.word} │ ${pin.consumer_state.word}`];
513×
  if (pin.behind !== null && pin.behind !== undefined && pin.behind > 0) {
521×
    parts.push(`${pin.behind} behind`);
531×
  }
543×
  if (pin.bump !== null && pin.bump !== undefined) {
551×
    parts.push(`bump #${pin.bump}`);
561×
  }
573×
  return parts.join(" · ");
583×
}
591×
601×
const FOLLOW: Record<string, string> = { off: "does not follow", green: "follows when the upstream is green", any: "follows every move" };
611×
621×
/** The tooltip, in Markdown: both halves' sentences, then the pin. */
631×
export function pinTooltip(pin: DiffusionPin): string {
641×
  const half = (who: string, h: DiffusionHalf) => `**${who}: ${h.word}.** ${h.title}`;
651×
  const run = pin.run !== null && pin.run !== undefined ? ` · run #${pin.run}${pin.run_status ? ` ${pin.run_status}` : ""}` : "";
661×
  return [
671×
    half(pin.upstream, pin.upstream_state),
681×
    half(pin.consumer, pin.consumer_state),
691×
    `Pinned at \`${pin.path}\` on \`${pin.bookmark}\`; ${pin.consumer} ${FOLLOW[pin.follow] ?? pin.follow}.${pin.bump !== null && pin.bump !== undefined ? ` Open bump #${pin.bump}${run}.` : ""}`,
701×
  ].join("\n\n");
711×
}