Radish alpha
r
Radicle desktop app
Radicle
Git (anonymous pull)
Log in to clone via SSH
Add tests for clipboard, issue listing and issues
Sebastian Martinez committed 1 year ago
commit 777430ab92858ed8301557c22bfcf9db35c2acdb
parent 58891de06fcb30e242acb4458953a3c07327a39f
10 files changed +105 -6
modified .github/workflows/check-e2e.yml
@@ -28,7 +28,7 @@ jobs:

      - name: Install Playwright browsers
        if: steps.playwright-dep-cache.outputs.cache-hit != 'true'
-
        run: npx playwright install webkit
+
        run: npx playwright install webkit chromium

      - name: Install Radicle binaries
        run: |
modified src/components/Header.svelte
@@ -94,7 +94,7 @@
        </OutlineButton>
        <Popover popoverPositionRight="0" popoverPositionTop="3rem">
          {#snippet toggle(onclick)}
-
            <NakedButton variant="ghost" {onclick}>
+
            <NakedButton title="Settings" variant="ghost" {onclick}>
              <Icon name="settings" />
            </NakedButton>
          {/snippet}
modified src/components/Id.svelte
@@ -2,7 +2,7 @@
  import type { ComponentProps, Snippet } from "svelte";

  import { debounce } from "lodash";
-
  import { writeText } from "@tauri-apps/plugin-clipboard-manager";
+
  import { writeToClipboard } from "@app/lib/invoke";

  import { formatOid } from "@app/lib/utils";

@@ -18,7 +18,7 @@
  }, 1000);

  async function copy() {
-
    await writeText(clipboard);
+
    await writeToClipboard(clipboard);
    icon = "checkmark";
    tooltip = "Copied to clipboard";
    restoreIcon();
modified src/components/NakedButton.svelte
@@ -3,11 +3,12 @@

  interface Props {
    children: Snippet;
+
    title?: string;
    variant: "primary" | "secondary" | "ghost";
    onclick?: () => void;
  }

-
  const { children, variant, onclick }: Props = $props();
+
  const { children, title, variant, onclick }: Props = $props();

  const style = $derived(
    `--button-color-1: var(--color-fill-${variant});` +
@@ -203,7 +204,7 @@
</style>

<!-- svelte-ignore a11y_click_events_have_key_events -->
-
<div class="container" {onclick} role="button" tabindex="0" {style}>
+
<div class="container" {onclick} {title} role="button" tabindex="0" {style}>
  <div class="pixel p1-1"></div>
  <div class="pixel p1-2"></div>
  <div class="pixel p1-3"></div>
modified src/components/RepoCard.svelte
@@ -52,6 +52,7 @@
      {/if}
    </div>
    <Id
+
      ariaLabel="repo-id"
      clipboard={repo.rid}
      shorten={false}
      variant="oid"
modified src/lib/invoke.ts
@@ -19,3 +19,19 @@ export async function invoke<T = null>(
      });
  }
}
+

+
export async function writeToClipboard(
+
  text: string,
+
  opts?: {
+
    label?: string;
+
  },
+
) {
+
  if (window.__TAURI_INTERNALS__) {
+
    await tauri.invoke("plugin:clipboard-manager|write_text", {
+
      label: opts?.label,
+
      text,
+
    });
+
  } else {
+
    await navigator.clipboard.writeText(text);
+
  }
+
}
added tests/e2e/clipboard.spec.ts
@@ -0,0 +1,31 @@
+
import { chromium } from "playwright";
+

+
import { expect, markdownRid, test } from "@tests/support/fixtures.js";
+

+
// We explicitly run all clipboard tests withing the context of a single test
+
// so that we don't run into race conditions, because there is no way to isolate
+
// the clipboard in Playwright yet.
+
test("copy to clipboard", async () => {
+
  const browser = await chromium.launch();
+
  const context = await browser.newContext();
+
  await context.grantPermissions(["clipboard-read", "clipboard-write"]);
+
  const page = await context.newPage();
+

+
  await page.goto("/repos");
+

+
  // Reset system clipboard to a known state.
+
  await page.evaluate<string>("navigator.clipboard.writeText('')");
+

+
  // Repo ID.
+
  {
+
    await page.getByLabel("repo-id").first().click();
+
    const clipboardContent = await page.evaluate<string>(
+
      "navigator.clipboard.readText()",
+
    );
+
    expect(clipboardContent).toBe(markdownRid);
+
  }
+

+
  // Clear the system clipboard contents so developers don't wonder why there's
+
  // random stuff in their clipboard after running tests.
+
  await page.evaluate<string>("navigator.clipboard.writeText('')");
+
});
added tests/e2e/repo/issue.spec.ts
@@ -0,0 +1,8 @@
+
import { test, expect, cobRid } from "@tests/support/fixtures.js";
+

+
test("navigate single issue", async ({ page }) => {
+
  await page.goto(`/repos/${cobRid}/issues?status=all`);
+
  await page.getByText("This title has **markdown**").click();
+

+
  await expect(page).toHaveURL(/\/issues\/[0-9a-f]{40}/);
+
});
added tests/e2e/repo/issues.spec.ts
@@ -0,0 +1,10 @@
+
import { test, cobRid, expect } from "@tests/support/fixtures.js";
+

+
test("navigate issues listing", async ({ page }) => {
+
  await page.goto(`/repos/${cobRid}/issues?show=all`);
+
  await expect(page.locator(".issue-teaser")).toHaveCount(3);
+

+
  await page.getByRole("link", { name: "Closed" }).click();
+
  await expect(page.locator(".issue-teaser")).toHaveCount(2);
+
  await expect(page).toHaveURL(`/repos/${cobRid}/issues?status=closed`);
+
});
added tests/e2e/theme.spec.ts
@@ -0,0 +1,32 @@
+
import { test, expect } from "@tests/support/fixtures.js";
+

+
test("default theme", async ({ page }) => {
+
  await page.goto("/repos");
+

+
  await expect(page.locator("html")).toHaveAttribute("data-theme", "dark");
+
});
+

+
test("theme persistence", async ({ page }) => {
+
  await page.goto("/repos");
+
  await expect(page.getByRole("button", { name: "markdown" })).toBeVisible();
+
  await page.getByRole("button", { name: "Settings" }).click();
+

+
  await page.getByRole("button", { name: "Light", exact: true }).click();
+
  await expect(page.locator("html")).toHaveAttribute("data-theme", "light");
+

+
  await page.reload();
+

+
  await expect(page.locator("html")).toHaveAttribute("data-theme", "light");
+
});
+

+
test("change theme", async ({ page }) => {
+
  await page.goto("/repos");
+
  await expect(page.getByRole("button", { name: "markdown" })).toBeVisible();
+
  await page.getByRole("button", { name: "Settings" }).click();
+

+
  await page.getByRole("button", { name: "Light", exact: true }).click();
+
  await expect(page.locator("html")).toHaveAttribute("data-theme", "light");
+

+
  await page.getByRole("button", { name: "Dark", exact: true }).click();
+
  await expect(page.locator("html")).toHaveAttribute("data-theme", "dark");
+
});