darabos commited on
Commit
04c6ee3
·
1 Parent(s): e621a02

Use Aria labels for links in tests.

Browse files
lynxkite-app/web/src/Code.tsx CHANGED
@@ -3,7 +3,7 @@
3
  import Editor, { type Monaco } from "@monaco-editor/react";
4
  import type { editor } from "monaco-editor";
5
  import { useEffect, useRef } from "react";
6
- import { Link, useLocation } from "react-router";
7
  import { WebsocketProvider } from "y-websocket";
8
  import * as Y from "yjs";
9
  // @ts-ignore
@@ -14,9 +14,10 @@ import Backspace from "~icons/tabler/backspace.jsx";
14
  import Close from "~icons/tabler/x.jsx";
15
  import favicon from "./assets/favicon.ico";
16
  import theme from "./code-theme.ts";
 
17
 
18
  export default function Code() {
19
- const path = decodeURIComponent(useLocation().pathname).replace(/^\/code\//, "");
20
  const parentDir = path!.split("/").slice(0, -1).join("/");
21
  const yDocRef = useRef<any>();
22
  const wsProviderRef = useRef<any>();
 
3
  import Editor, { type Monaco } from "@monaco-editor/react";
4
  import type { editor } from "monaco-editor";
5
  import { useEffect, useRef } from "react";
6
+ import { Link } from "react-router";
7
  import { WebsocketProvider } from "y-websocket";
8
  import * as Y from "yjs";
9
  // @ts-ignore
 
14
  import Close from "~icons/tabler/x.jsx";
15
  import favicon from "./assets/favicon.ico";
16
  import theme from "./code-theme.ts";
17
+ import { usePath } from "./common.ts";
18
 
19
  export default function Code() {
20
+ const path = usePath().replace(/^[/]code[/]/, "");
21
  const parentDir = path!.split("/").slice(0, -1).join("/");
22
  const yDocRef = useRef<any>();
23
  const wsProviderRef = useRef<any>();
lynxkite-app/web/src/Directory.tsx CHANGED
@@ -1,8 +1,9 @@
1
  import { useState } from "react";
2
  // The directory browser.
3
- import { Link, useLocation, useNavigate } from "react-router";
4
  import useSWR from "swr";
5
  import type { DirectoryEntry } from "./apiTypes.ts";
 
6
 
7
  // @ts-ignore
8
  import File from "~icons/tabler/file";
@@ -58,7 +59,7 @@ function EntryCreator(props: {
58
  const fetcher = (url: string) => fetch(url).then((res) => res.json());
59
 
60
  export default function () {
61
- const path = decodeURIComponent(useLocation().pathname).replace(/^[/]$|^[/]dir$|^[/]dir[/]/, "");
62
  const encodedPath = encodeURIComponent(path || "");
63
  const list = useSWR(`/api/dir/list?path=${encodedPath}`, fetcher, {
64
  dedupingInterval: 0,
@@ -160,7 +161,7 @@ export default function () {
160
 
161
  {path ? (
162
  <div className="breadcrumbs">
163
- <Link to="/dir/">
164
  <Home />
165
  </Link>{" "}
166
  <span className="current-folder">{path}</span>
 
1
  import { useState } from "react";
2
  // The directory browser.
3
+ import { Link, useNavigate } from "react-router";
4
  import useSWR from "swr";
5
  import type { DirectoryEntry } from "./apiTypes.ts";
6
+ import { usePath } from "./common.ts";
7
 
8
  // @ts-ignore
9
  import File from "~icons/tabler/file";
 
59
  const fetcher = (url: string) => fetch(url).then((res) => res.json());
60
 
61
  export default function () {
62
+ const path = usePath().replace(/^[/]$|^[/]dir$|^[/]dir[/]/, "");
63
  const encodedPath = encodeURIComponent(path || "");
64
  const list = useSWR(`/api/dir/list?path=${encodedPath}`, fetcher, {
65
  dedupingInterval: 0,
 
161
 
162
  {path ? (
163
  <div className="breadcrumbs">
164
+ <Link to="/dir/" aria-label="home">
165
  <Home />
166
  </Link>{" "}
167
  <span className="current-folder">{path}</span>
lynxkite-app/web/src/common.ts ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ import { useLocation } from "react-router";
2
+
3
+ export function usePath() {
4
+ // Decode special characters. Drop trailing slash. (Some clients add it, e.g. Playwright.)
5
+ const path = decodeURIComponent(useLocation().pathname).replace(/[/]$/, "");
6
+ return path;
7
+ }
lynxkite-app/web/src/workspace/Workspace.tsx CHANGED
@@ -18,7 +18,7 @@ import {
18
  } from "@xyflow/react";
19
  import axios from "axios";
20
  import { type MouseEvent, useCallback, useEffect, useMemo, useState } from "react";
21
- import { useLocation } from "react-router";
22
  import useSWR, { type Fetcher } from "swr";
23
  import { WebsocketProvider } from "y-websocket";
24
  // @ts-ignore
@@ -31,6 +31,7 @@ import Restart from "~icons/tabler/rotate-clockwise.jsx";
31
  import Close from "~icons/tabler/x.jsx";
32
  import type { Workspace, WorkspaceNode } from "../apiTypes.ts";
33
  import favicon from "../assets/favicon.ico";
 
34
  // import NodeWithTableView from './NodeWithTableView';
35
  import EnvironmentSelector from "./EnvironmentSelector";
36
  import { LynxKiteState } from "./LynxKiteState";
@@ -55,7 +56,7 @@ function LynxKiteFlow() {
55
  const reactFlow = useReactFlow();
56
  const [nodes, setNodes] = useState([] as Node[]);
57
  const [edges, setEdges] = useState([] as Edge[]);
58
- const path = decodeURIComponent(useLocation().pathname).replace(/^\/edit\//, "");
59
  const shortPath = path!
60
  .split("/")
61
  .pop()!
@@ -335,9 +336,9 @@ function LynxKiteFlow() {
335
  return (
336
  <div className="workspace">
337
  <div className="top-bar bg-neutral">
338
- <a className="logo" href="">
339
  <img alt="" src={favicon} />
340
- </a>
341
  <div className="ws-name">{shortPath}</div>
342
  <title>{shortPath}</title>
343
  <EnvironmentSelector
@@ -357,9 +358,9 @@ function LynxKiteFlow() {
357
  <button className="btn btn-link" onClick={executeWorkspace}>
358
  <Restart />
359
  </button>
360
- <a className="btn btn-link" href={`/dir/${parentDir}`}>
361
  <Close />
362
- </a>
363
  </div>
364
  </div>
365
  <div style={{ height: "100%", width: "100vw" }} onDragOver={onDragOver} onDrop={onDrop}>
 
18
  } from "@xyflow/react";
19
  import axios from "axios";
20
  import { type MouseEvent, useCallback, useEffect, useMemo, useState } from "react";
21
+ import { Link } from "react-router";
22
  import useSWR, { type Fetcher } from "swr";
23
  import { WebsocketProvider } from "y-websocket";
24
  // @ts-ignore
 
31
  import Close from "~icons/tabler/x.jsx";
32
  import type { Workspace, WorkspaceNode } from "../apiTypes.ts";
33
  import favicon from "../assets/favicon.ico";
34
+ import { usePath } from "../common.ts";
35
  // import NodeWithTableView from './NodeWithTableView';
36
  import EnvironmentSelector from "./EnvironmentSelector";
37
  import { LynxKiteState } from "./LynxKiteState";
 
56
  const reactFlow = useReactFlow();
57
  const [nodes, setNodes] = useState([] as Node[]);
58
  const [edges, setEdges] = useState([] as Edge[]);
59
+ const path = usePath().replace(/^[/]edit[/]/, "");
60
  const shortPath = path!
61
  .split("/")
62
  .pop()!
 
336
  return (
337
  <div className="workspace">
338
  <div className="top-bar bg-neutral">
339
+ <Link className="logo" to="/">
340
  <img alt="" src={favicon} />
341
+ </Link>
342
  <div className="ws-name">{shortPath}</div>
343
  <title>{shortPath}</title>
344
  <EnvironmentSelector
 
358
  <button className="btn btn-link" onClick={executeWorkspace}>
359
  <Restart />
360
  </button>
361
+ <Link className="btn btn-link" to={`/dir/${parentDir}`} aria-label="close">
362
  <Close />
363
+ </Link>
364
  </div>
365
  </div>
366
  <div style={{ height: "100%", width: "100vw" }} onDragOver={onDragOver} onDrop={onDrop}>
lynxkite-app/web/tests/lynxkite.ts CHANGED
@@ -155,7 +155,7 @@ export class Workspace {
155
  }
156
 
157
  async close() {
158
- await this.page.locator('a[href="/dir/"]').click();
159
  }
160
  }
161
 
@@ -220,6 +220,6 @@ export class Splash {
220
  }
221
 
222
  async goHome() {
223
- await this.page.locator('a[href="/dir/"]').click();
224
  }
225
  }
 
155
  }
156
 
157
  async close() {
158
+ await this.page.getByRole("link", { name: "close" }).click();
159
  }
160
  }
161
 
 
220
  }
221
 
222
  async goHome() {
223
+ await this.page.getByRole("link", { name: "home" }).click();
224
  }
225
  }