From 2bad94457ca33b20b3fde998f02ba94418bbe337 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C5=ABdolfs=20O=C5=A1i=C5=86=C5=A1?= Date: Thu, 16 Feb 2023 18:54:52 +0100 Subject: [PATCH] Migrate to the heartwood protocol stack MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rลซdolfs Oลกiล†ลก --- .github/workflows/check-e2e.yml | 14 +- scripts/create-seed-fixture | 116 ++++---- scripts/create-seed-fixture-heartwood | 120 --------- scripts/run-http-api-with-fixtures | 128 --------- scripts/run-httpd-with-fixtures | 2 +- src/App.svelte | 4 +- src/App/Header/Connect.svelte | 13 +- src/App/Header/SearchResultsModal.svelte | 4 +- src/components/Authorship.svelte | 14 +- src/components/Comment/Avatar.svelte | 12 +- src/config.json | 55 ++-- src/global.d.ts | 2 - src/lib/api.ts | 20 +- src/lib/cobs.ts | 1 - src/lib/config.ts | 6 + src/lib/issue.ts | 23 +- src/lib/patch.ts | 251 ------------------ src/lib/project.ts | 170 ++---------- src/lib/router.ts | 27 -- src/lib/router/definitions.ts | 4 +- src/lib/search.ts | 8 +- src/lib/seed.ts | 125 ++------- src/lib/utils.ts | 134 ++++++---- src/views/home/Index.svelte | 6 +- src/views/projects/Blob.svelte | 4 +- src/views/projects/CloneButton.svelte | 9 +- src/views/projects/Commit.svelte | 2 +- src/views/projects/Commit/CommitTeaser.svelte | 6 - src/views/projects/Header.svelte | 21 +- src/views/projects/Issue.svelte | 16 -- src/views/projects/Issue/New.svelte | 13 +- src/views/projects/Issues.svelte | 3 +- src/views/projects/Patch.svelte | 151 ----------- src/views/projects/Patch/PatchSideBar.svelte | 54 ---- src/views/projects/Patch/PatchTabBar.svelte | 102 ------- src/views/projects/Patch/PatchTeaser.svelte | 114 -------- src/views/projects/Patch/PatchTimeline.svelte | 73 ----- src/views/projects/Patch/Review.svelte | 31 --- src/views/projects/Patches.svelte | 94 ------- src/views/projects/PeerSelector.svelte | 17 +- src/views/projects/ProjectMeta.svelte | 16 +- src/views/projects/Tree.svelte | 6 +- src/views/projects/Tree/Folder.svelte | 6 +- src/views/projects/View.svelte | 27 +- src/views/seeds/Routes.svelte | 11 - src/views/seeds/View.svelte | 36 +-- src/views/seeds/View/Projects.svelte | 8 +- tests/e2e/clipboard.spec.ts | 25 +- tests/e2e/project.spec.ts | 78 ++---- tests/e2e/project/commit.spec.ts | 31 +-- tests/e2e/project/commits.spec.ts | 84 ++---- tests/e2e/search.spec.ts | 7 +- tests/e2e/seed.spec.ts | 5 +- tests/fixtures/seeds/palm-heartwood.tar.bz2 | Bin 28873 -> 0 bytes tests/fixtures/seeds/palm.tar.bz2 | Bin 36569 -> 28873 bytes tests/support/fixtures.ts | 38 ++- tests/support/globalSetup.ts | 20 +- tests/unit/utils.test.ts | 77 ++++-- vite.config.ts | 1 - 59 files changed, 462 insertions(+), 1983 deletions(-) delete mode 100755 scripts/create-seed-fixture-heartwood delete mode 100755 scripts/run-http-api-with-fixtures delete mode 100644 src/lib/patch.ts delete mode 100644 src/views/projects/Patch.svelte delete mode 100644 src/views/projects/Patch/PatchSideBar.svelte delete mode 100644 src/views/projects/Patch/PatchTabBar.svelte delete mode 100644 src/views/projects/Patch/PatchTeaser.svelte delete mode 100644 src/views/projects/Patch/PatchTimeline.svelte delete mode 100644 src/views/projects/Patch/Review.svelte delete mode 100644 src/views/projects/Patches.svelte delete mode 100644 src/views/seeds/Routes.svelte delete mode 100644 tests/fixtures/seeds/palm-heartwood.tar.bz2 diff --git a/.github/workflows/check-e2e.yml b/.github/workflows/check-e2e.yml index 322e3180e..205595720 100644 --- a/.github/workflows/check-e2e.yml +++ b/.github/workflows/check-e2e.yml @@ -14,8 +14,8 @@ jobs: matrix: # Disable firefox until this is fixed upstream: # https://github.com/microsoft/playwright/issues/21145 - # browser: [chromium, firefox, visual, heartwood] - browser: [chromium, visual, heartwood] + # browser: [chromium, firefox, visual] + browser: [chromium, visual] timeout-minutes: 30 runs-on: ubuntu-latest steps: @@ -59,19 +59,13 @@ jobs: - name: Start http-api test server run: | - if [ ${{ matrix.browser }} = "heartwood" ]; then - mkdir -p tests/artifacts - ./scripts/run-httpd-with-fixtures --non-interactive --download 2>&1 | tee tests/artifacts/httpd-${{ matrix.browser }}.log & - else - ./scripts/run-http-api-with-fixtures --non-interactive --detach - fi + mkdir -p tests/artifacts; + ./scripts/run-httpd-with-fixtures --non-interactive --download 2>&1 | tee tests/artifacts/httpd-${{ matrix.browser }}.log & - name: Run Playwright tests run: | if [ ${{ matrix.browser }} = "visual" ] && [ ${{ github.ref }} = "refs/heads/master" ]; then npm run test:e2e -- --project ${{ matrix.browser }} --update-snapshots; - elif [ ${{ matrix.browser }} = "heartwood" ]; then - HEARTWOOD=true npm run test:e2e -- --project chromium; else npm run test:e2e -- --project ${{ matrix.browser }}; fi diff --git a/scripts/create-seed-fixture b/scripts/create-seed-fixture index 15c58a224..376dd1b48 100755 --- a/scripts/create-seed-fixture +++ b/scripts/create-seed-fixture @@ -1,30 +1,29 @@ #!/usr/bin/env bash + +killall radicle-node +killall git-daemon + set -euo pipefail -function cleanup { - docker kill radicle-git-server-test -} -trap cleanup EXIT - - -PASSPHRASE=asdf -REV=40bdc662b2d48cbfaa87182b21457ef8f861b04a +export RAD_PASSPHRASE=asdf REPO_ROOT=$(git rev-parse --show-toplevel) -ID=$(echo $RANDOM | md5sum | head -c 8) -BASE_PATH=$REPO_ROOT/tests/tmp/create-seed-fixture-$ID +ID=$(echo $RANDOM | md5sum | head -c 4) +BASE_PATH=$REPO_ROOT/tests/tmp/seed-fixture-$ID TEST_REPO_ARCHIVE=$REPO_ROOT/tests/fixtures/repos/source-browsing.tar.bz2 TEST_REPO_NAME=source-browsing TEST_REPO_PATH=$BASE_PATH/repos/$TEST_REPO_NAME PALM_RAD_HOME=$BASE_PATH/seeds/palm +PALM_CHECKOUT=$BASE_PATH/checkout/palm ALICE_RAD_HOME=$BASE_PATH/peers/alice ALICE_CHECKOUT=$BASE_PATH/checkout/alice BOB_RAD_HOME=$BASE_PATH/peers/bob BOB_CHECKOUT=$BASE_PATH/checkout/bob mkdir -p $PALM_RAD_HOME +mkdir -p $PALM_CHECKOUT mkdir -p $ALICE_RAD_HOME mkdir -p $ALICE_CHECKOUT mkdir -p $BOB_RAD_HOME @@ -33,62 +32,89 @@ mkdir -p $TEST_REPO_PATH tar -xf $TEST_REPO_ARCHIVE -C $TEST_REPO_PATH -RAD_HOME=$PALM_RAD_HOME rad auth --init --name palm --passphrase $PASSPHRASE +### PALM NODE ### -docker run \ - --detach \ - --init \ - --publish 8778:8778 \ - --rm \ - --env RAD_HOME=/app/radicle \ - --name radicle-git-server-test \ - --volume $PALM_RAD_HOME:/app/radicle \ - "gcr.io/radicle-services/git-server:$REV" \ - --passphrase $PASSPHRASE \ - --allow-unauthorized-keys +eval $(ssh-agent) -# git-server takes a while to copy commit hooks to the monorepo -sleep 10 +export RAD_HOME=$PALM_RAD_HOME +export RAD_SEED=ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee -GIT_AUTHOR_NAME="Alice Liddell" -GIT_AUTHOR_EMAIL="alice@radicle.xyz" -GIT_COMMITTER_NAME="Alice Liddell" -GIT_COMMITTER_EMAIL="alice@radicle.xyz" +rad auth +radicle-node --listen 0.0.0.0:3446 --git-daemon 0.0.0.0:4446 & -RAD_HOME=$ALICE_RAD_HOME rad auth --init --name alice --passphrase $PASSPHRASE +### ALICE ### + +export RAD_HOME=$ALICE_RAD_HOME +export RAD_SEED=ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +export GIT_AUTHOR_NAME="Alice Liddell" +export GIT_AUTHOR_EMAIL="alice@radicle.xyz" +export GIT_COMMITTER_NAME="Alice Liddell" +export GIT_COMMITTER_EMAIL="alice@radicle.xyz" + +rad auth cd $ALICE_CHECKOUT git clone $TEST_REPO_PATH cd $TEST_REPO_NAME -git checkout feature/branch -git checkout orphaned-branch + git checkout main +rad init --name "source-browsing" \ + --description "Git repository for source browsing tests" \ + --default-branch "main" \ + --no-confirm -RAD_HOME=$ALICE_RAD_HOME rad init --name "source-browsing" --description "Git repository for source browsing tests" --default-branch "main" --no-confirm +git checkout feature/branch +git push rad -sleep 10 -RAD_HOME=$ALICE_RAD_HOME rad push --seed 0.0.0.0:8778 --all --sync -PROJECT_ID=$(rad .) +git checkout orphaned-branch +git push rad +radicle-node --listen 0.0.0.0:3444 --git-daemon 0.0.0.0:4444 \ + --connect z6Mkk7oqY4pPxhMmGEotDYsFo97vhCj85BLY1H256HrJmjN8@0.0.0.0:3446 & -GIT_AUTHOR_NAME="Bob Belcher" -GIT_AUTHOR_EMAIL="bob@radicle.xyz" -GIT_COMMITTER_NAME="Bob Belcher" -GIT_COMMITTER_EMAIL="bob@radicle.xyz" +sleep 1 -RAD_HOME=$BOB_RAD_HOME rad auth --init --name bob --passphrase $PASSPHRASE +### PALM CLONE ### + +cd $PALM_CHECKOUT +export RAD_HOME=$PALM_RAD_HOME +rad clone rad:zKtT7DmF9H34KkvcKj9PHW19WzjT + +### BOB ### + +export GIT_AUTHOR_NAME="Bob Belcher" +export GIT_AUTHOR_EMAIL="bob@radicle.xyz" +export GIT_COMMITTER_NAME="Bob Belcher" +export GIT_COMMITTER_EMAIL="bob@radicle.xyz" +export GIT_COMMITTER_DATE="Mon Dec 21 14:00 2022 +0100" + +export RAD_HOME=$BOB_RAD_HOME +export RAD_SEED=fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe + +rad auth +rad auth +radicle-node --listen 0.0.0.0:3445 --git-daemon 0.0.0.0:4445 \ + --connect z6Mkk7oqY4pPxhMmGEotDYsFo97vhCj85BLY1H256HrJmjN8@0.0.0.0:3446 & + +sleep 2 cd $BOB_CHECKOUT -RAD_HOME=$BOB_RAD_HOME rad clone $PROJECT_ID --seed 0.0.0.0:8778 --no-confirm +rad clone rad:zKtT7DmF9H34KkvcKj9PHW19WzjT cd $TEST_REPO_NAME echo "Updated readme" > README.md git add README.md -git commit --message "Update readme" --date "Mon Nov 21 14:00 2022 +0100" -RAD_HOME=$BOB_RAD_HOME rad push --seed 0.0.0.0:8778 -RAD_HOME=$BOB_RAD_HOME rad sync --seed 0.0.0.0:8778 --self -RAD_HOME=$BOB_RAD_HOME rad sync --seed 0.0.0.0:8778 +git commit --message "Update readme" --date "$GIT_COMMITTER_DATE" +git push rad + +### WAIT FOR SYNC WITH PALM ### + +sleep 2 cd $BASE_PATH tar -cjf palm.tar.bz2 --exclude "post-receive" --exclude "pre-receive" -C $PALM_RAD_HOME . + +killall radicle-node +killall git-daemon diff --git a/scripts/create-seed-fixture-heartwood b/scripts/create-seed-fixture-heartwood deleted file mode 100755 index 45bd91869..000000000 --- a/scripts/create-seed-fixture-heartwood +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/env bash - -killall radicle-node -killall git-daemon - -set -euo pipefail - -export RAD_PASSPHRASE=asdf - -REPO_ROOT=$(git rev-parse --show-toplevel) -ID=$(echo $RANDOM | md5sum | head -c 4) -BASE_PATH=$REPO_ROOT/tests/tmp/heartwood-$ID - -TEST_REPO_ARCHIVE=$REPO_ROOT/tests/fixtures/repos/source-browsing.tar.bz2 -TEST_REPO_NAME=source-browsing -TEST_REPO_PATH=$BASE_PATH/repos/$TEST_REPO_NAME - -PALM_RAD_HOME=$BASE_PATH/seeds/palm -PALM_CHECKOUT=$BASE_PATH/checkout/palm -ALICE_RAD_HOME=$BASE_PATH/peers/alice -ALICE_CHECKOUT=$BASE_PATH/checkout/alice -BOB_RAD_HOME=$BASE_PATH/peers/bob -BOB_CHECKOUT=$BASE_PATH/checkout/bob - -mkdir -p $PALM_RAD_HOME -mkdir -p $PALM_CHECKOUT -mkdir -p $ALICE_RAD_HOME -mkdir -p $ALICE_CHECKOUT -mkdir -p $BOB_RAD_HOME -mkdir -p $BOB_CHECKOUT -mkdir -p $TEST_REPO_PATH - -tar -xf $TEST_REPO_ARCHIVE -C $TEST_REPO_PATH - -### PALM NODE ### - -eval $(ssh-agent) - -export RAD_HOME=$PALM_RAD_HOME -export RAD_SEED=ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee - -rad auth -radicle-node --listen 0.0.0.0:3446 --git-daemon 0.0.0.0:4446 & - -### ALICE ### - -export RAD_HOME=$ALICE_RAD_HOME -export RAD_SEED=ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - -export GIT_AUTHOR_NAME="Alice Liddell" -export GIT_AUTHOR_EMAIL="alice@radicle.xyz" -export GIT_COMMITTER_NAME="Alice Liddell" -export GIT_COMMITTER_EMAIL="alice@radicle.xyz" - -rad auth - -cd $ALICE_CHECKOUT - -git clone $TEST_REPO_PATH -cd $TEST_REPO_NAME - -git checkout main -rad init --name "source-browsing" \ - --description "Git repository for source browsing tests" \ - --default-branch "main" \ - --no-confirm - -git checkout feature/branch -git push rad - -git checkout orphaned-branch -git push rad - -radicle-node --listen 0.0.0.0:3444 --git-daemon 0.0.0.0:4444 \ - --connect z6Mkk7oqY4pPxhMmGEotDYsFo97vhCj85BLY1H256HrJmjN8@0.0.0.0:3446 & - -sleep 1 - -### PALM CLONE ### - -cd $PALM_CHECKOUT -export RAD_HOME=$PALM_RAD_HOME -rad clone rad:zKtT7DmF9H34KkvcKj9PHW19WzjT - -### BOB ### - -export GIT_AUTHOR_NAME="Bob Belcher" -export GIT_AUTHOR_EMAIL="bob@radicle.xyz" -export GIT_COMMITTER_NAME="Bob Belcher" -export GIT_COMMITTER_EMAIL="bob@radicle.xyz" -export GIT_COMMITTER_DATE="Mon Dec 21 14:00 2022 +0100" - -export RAD_HOME=$BOB_RAD_HOME -export RAD_SEED=fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe - -rad auth -rad auth -radicle-node --listen 0.0.0.0:3445 --git-daemon 0.0.0.0:4445 \ - --connect z6Mkk7oqY4pPxhMmGEotDYsFo97vhCj85BLY1H256HrJmjN8@0.0.0.0:3446 & - -sleep 2 - -cd $BOB_CHECKOUT -rad clone rad:zKtT7DmF9H34KkvcKj9PHW19WzjT - -cd $TEST_REPO_NAME -echo "Updated readme" > README.md -git add README.md -git commit --message "Update readme" --date "$GIT_COMMITTER_DATE" -git push rad - -### WAIT FOR SYNC WITH PALM ### - -sleep 2 - -cd $BASE_PATH -tar -cjf palm.tar.bz2 --exclude "post-receive" --exclude "pre-receive" -C $PALM_RAD_HOME . - -killall radicle-node -killall git-daemon diff --git a/scripts/run-http-api-with-fixtures b/scripts/run-http-api-with-fixtures deleted file mode 100755 index 461d2fff1..000000000 --- a/scripts/run-http-api-with-fixtures +++ /dev/null @@ -1,128 +0,0 @@ -#!/bin/sh -set -e - -REV=40bdc662b2d48cbfaa87182b21457ef8f861b04a - -REPO_ROOT=$(git rev-parse --show-toplevel) -FIXTURE=$REPO_ROOT/tests/fixtures/seeds/palm.tar.bz2 -WORKSPACE=$REPO_ROOT/tests/tmp/palm -PASSPHRASE=asdf -CONTAINER_NAME=radicle-http-api-with-fixtures -HTTP_API_BINARY=radicle-http-api - -show_usage() { - echo - echo "Starts a http-api backend with test fixtures." - echo - echo "USAGE:" - echo " run-http-api-with-fixtures [-b|d|h|n]" - echo - echo "OPTIONS:" - echo " -b --binary Use a ${HTTP_API_BINARY} binary that is in PATH to avoid using Docker." - echo " -d --detach Daemonize the docker process." - echo " -h --help Print this Help." - echo " -n --non-interactive Run in non-interactive mode, no user prompts." - echo -} - -prompt_workspace_removal() { - echo "This will irrevocably destroy the following directories:" - echo - echo $WORKSPACE - echo - - read -r -p "Are you sure you want to continue? [yes/no]: " confirm - case "$confirm" in - [yY][eE][sS]) - rm -rf $WORKSPACE - echo "Done" - ;; - *) - echo "Ok, I won't touch your data." - exit - ;; - esac -} - -prepare_workspace() { - echo - echo "Unpacking fixture $FIXTURE" - mkdir -p $WORKSPACE - tar -xf $FIXTURE -C $WORKSPACE -} - -run_docker() { - echo "Starting docker at container $CONTAINER_NAME at $REV" - echo " http-api --root $WORKSPACE --passphrase $PASSPHRASE" - echo - - exec docker run \ - --init \ - --publish 8777:8777 \ - --rm \ - --name $CONTAINER_NAME \ - --volume $WORKSPACE:/app/radicle \ - "$@" \ - "gcr.io/radicle-services/http-api:$REV" \ - --passphrase $PASSPHRASE -} - -run_binary() { - if ! [ -x "$(command -v $HTTP_API_BINARY)" ]; then - echo - echo "Couldn't find the $HTTP_API_BINARY binary in your PATH." - echo "You can compile it from source:" - echo " ๐Ÿ‘‰ https://github.com/radicle-dev/radicle-client-services/tree/${REV}/http-api" - echo - exit 1 - fi - - echo - echo "Starting $HTTP_API_BINARY" - echo " $HTTP_API_BINARY --listen 0.0.0.0:8777 --root ${WORKSPACE} --passphrase $PASSPHRASE" - echo - - $HTTP_API_BINARY --listen 0.0.0.0:8777 --root $WORKSPACE --passphrase $PASSPHRASE -} - -BINARY=false -NON_INTERACTIVE=false -DETACH=false - -while [ $# -ne 0 ]; do - case "$1" in - --binary | -b) - BINARY=true - ;; - --detach | -d) - DETACH=true - ;; - --non-interactive | -n) - NON_INTERACTIVE=true - ;; - *) - show_usage - exit - ;; - esac - - shift -done - -if [ "$NON_INTERACTIVE" = true ]; then - rm -rf $WORKSPACE - prepare_workspace -else - prompt_workspace_removal - prepare_workspace -fi - -if [ "$BINARY" = true ]; then - run_binary -else - if [ "$DETACH" = true ]; then - run_docker --detach - else - run_docker - fi -fi diff --git a/scripts/run-httpd-with-fixtures b/scripts/run-httpd-with-fixtures index fb92549bc..c6804cf66 100755 --- a/scripts/run-httpd-with-fixtures +++ b/scripts/run-httpd-with-fixtures @@ -4,7 +4,7 @@ set -e REV=f1de61ad8897a845f2be49e3e2b2951bc678b678 REPO_ROOT=$(git rev-parse --show-toplevel) -FIXTURE=$REPO_ROOT/tests/fixtures/seeds/palm-heartwood.tar.bz2 +FIXTURE=$REPO_ROOT/tests/fixtures/seeds/palm.tar.bz2 WORKSPACE=$REPO_ROOT/tests/tmp/palm PASSPHRASE=asdf BINARY_PATH="$REPO_ROOT/tests/tmp" diff --git a/src/App.svelte b/src/App.svelte index 7a55b0e79..2116ccb16 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -13,7 +13,7 @@ import Home from "@app/views/home/Index.svelte"; import Session from "@app/views/session/Index.svelte"; import Projects from "@app/views/projects/View.svelte"; - import Seeds from "@app/views/seeds/Routes.svelte"; + import Seeds from "@app/views/seeds/View.svelte"; const activeRouteStore = router.activeRouteStore; @@ -60,7 +60,7 @@ {#if $activeRouteStore.resource === "home"} {:else if $activeRouteStore.resource === "seeds"} - + {:else if $activeRouteStore.resource === "session"} {:else if $activeRouteStore.resource === "projects"} diff --git a/src/App/Header/Connect.svelte b/src/App/Header/Connect.svelte index 32a190ea9..eb30cabae 100644 --- a/src/App/Header/Connect.svelte +++ b/src/App/Header/Connect.svelte @@ -3,17 +3,13 @@ import { closeFocused } from "@app/components/Floating.svelte"; import { sessionStore, disconnect } from "@app/lib/session"; - import { toClipboard } from "@app/lib/utils"; + import { toClipboard, formatNodeId } from "@app/lib/utils"; import Avatar from "@app/components/Comment/Avatar.svelte"; import Button from "@app/components/Button.svelte"; import Floating from "@app/components/Floating.svelte"; import Icon from "@app/components/Icon.svelte"; - function formatId(id: string) { - return id.substring(0, 4) + " โ€“ " + id.substring(id.length - 4, id.length); - } - let icon: "clipboard-small" | "checkmark-small" = "clipboard-small"; const restoreIcon = debounce(() => { @@ -43,7 +39,7 @@ position: absolute; right: 5rem; top: 5rem; - width: 16.5rem; + width: 15rem; } .info { align-items: flex-start; @@ -118,7 +114,6 @@ font-family: var(--font-family-monospace); font-size: var(--font-size-tiny); user-select: none; - width: 11rem; word-break: break-all; } .disconnect { @@ -171,7 +166,7 @@ title={$sessionStore.publicKey} />
- {formatId($sessionStore.publicKey)} + {formatNodeId($sessionStore.publicKey)}
{:else} @@ -214,7 +209,7 @@ } }}>
- {$sessionStore.publicKey} + {formatNodeId($sessionStore.publicKey)}
diff --git a/src/App/Header/SearchResultsModal.svelte b/src/App/Header/SearchResultsModal.svelte index b8f775cf9..0b1ab2079 100644 --- a/src/App/Header/SearchResultsModal.svelte +++ b/src/App/Header/SearchResultsModal.svelte @@ -4,7 +4,7 @@ import * as modal from "@app/lib/modal"; import Link from "@app/components/Link.svelte"; import Modal from "@app/components/Modal.svelte"; - import { formatRadicleId, getSeedEmoji } from "@app/lib/utils"; + import { formatRepositoryId, getSeedEmoji } from "@app/lib/utils"; export let query: string; export let results: ProjectResult[]; @@ -48,7 +48,7 @@ {getSeedEmoji(project.seed.host)} {project.info.name} -  {formatRadicleId(project.info.id)} +  {formatRepositoryId(project.info.id)} diff --git a/src/components/Authorship.svelte b/src/components/Authorship.svelte index 7905883ee..1a4df24ab 100644 --- a/src/components/Authorship.svelte +++ b/src/components/Authorship.svelte @@ -1,11 +1,7 @@ - -
-
-
-
- - {patch.title} - - {patch.id} - - {formatObjectId(patch.id)} - -
-
- {capitalize(patch.state)} -
-
- -
- - - -
- {#if activeTab === PatchTab.Timeline} -
- - -
- {:else if activeTab === PatchTab.Diff && revision.changeset} - onBrowse(e, revision.oid)} /> - {:else if activeTab === PatchTab.Diff} - - No changeset found - - We couldn't find a changeset related to this patch or revision - - - {/if} -
-
diff --git a/src/views/projects/Patch/PatchSideBar.svelte b/src/views/projects/Patch/PatchSideBar.svelte deleted file mode 100644 index 9e9ded115..000000000 --- a/src/views/projects/Patch/PatchSideBar.svelte +++ /dev/null @@ -1,54 +0,0 @@ - - - - - diff --git a/src/views/projects/Patch/PatchTabBar.svelte b/src/views/projects/Patch/PatchTabBar.svelte deleted file mode 100644 index bd7e1f715..000000000 --- a/src/views/projects/Patch/PatchTabBar.svelte +++ /dev/null @@ -1,102 +0,0 @@ - - - - -
- { - dispatch("switchTab", e.detail); - }} - active={activeTab} /> - - - - - - - - -
diff --git a/src/views/projects/Patch/PatchTeaser.svelte b/src/views/projects/Patch/PatchTeaser.svelte deleted file mode 100644 index 07955430a..000000000 --- a/src/views/projects/Patch/PatchTeaser.svelte +++ /dev/null @@ -1,114 +0,0 @@ - - - - -
-
-
-
-
-
- - {patch.title} - {formatObjectId(patch.id)} -
- -
- {#if commentCount > 0} -
-
- ๐Ÿ’ฌ - {commentCount} -
-
- {/if} -
diff --git a/src/views/projects/Patch/PatchTimeline.svelte b/src/views/projects/Patch/PatchTimeline.svelte deleted file mode 100644 index b54414995..000000000 --- a/src/views/projects/Patch/PatchTimeline.svelte +++ /dev/null @@ -1,73 +0,0 @@ - - - - -
- {#each timeline as element} - {#if element.type === TimelineType.Merge && element.inner.peer.person} -
- -
- {:else if element.type === TimelineType.Review && element.inner.author.id} -
- -
- {:else if element.type === TimelineType.Comment} -
- - {#key element.inner} - - {/key} -
- {:else if element.type === TimelineType.Thread} -
- - {#if !window.HEARTWOOD} -
- {#each element.inner.replies as comment} - - {/each} -
- {/if} -
- {/if} - {/each} -
diff --git a/src/views/projects/Patch/Review.svelte b/src/views/projects/Patch/Review.svelte deleted file mode 100644 index b635d872c..000000000 --- a/src/views/projects/Patch/Review.svelte +++ /dev/null @@ -1,31 +0,0 @@ - - - - -{#if review.comment.body} - -{:else} -
- -
-{/if} diff --git a/src/views/projects/Patches.svelte b/src/views/projects/Patches.svelte deleted file mode 100644 index a1b559a34..000000000 --- a/src/views/projects/Patches.svelte +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - -
-
- - router.updateProjectRoute({ - search: `state=${e.detail}`, - })} - active={state} /> -
- - {#if filteredPatches.length} -
- {#each filteredPatches as patch} - -
{ - router.updateProjectRoute({ - view: { resource: "patch", params: { patch: patch.id } }, - }); - }}> - -
- {/each} -
- {:else} - -
{capitalize(state)} patches
-
No patches matched the current filter
-
- {/if} -
diff --git a/src/views/projects/PeerSelector.svelte b/src/views/projects/PeerSelector.svelte index 0a1c2a609..82eef4700 100644 --- a/src/views/projects/PeerSelector.svelte +++ b/src/views/projects/PeerSelector.svelte @@ -21,24 +21,17 @@ }[] = []; function createTitle(p: Peer): string { - const name = p.person?.name ? p.person.name : p.id; + const nodeId = formatNodeId(p.id); return p.delegate - ? `${name} is a delegate of this project` - : `${name} is a peer tracked by this seed`; + ? `${nodeId} is a delegate of this project` + : `${nodeId} is a peer tracked by this node`; } onMount(() => { meta = peers.find(p => p.id === peer); items = peers.map(p => { - if (!p.person?.name) { - console.debug("Not able to resolve peer identity for: ", p.id); - } - const key = p.person?.name - ? `${p.person.name} ${p.id}` - : p.id; - return { - key, + key: formatNodeId(p.id), value: p.id, title: createTitle(p), badge: p.delegate ? "delegate" : null, @@ -91,7 +84,7 @@ {#if meta} - {meta.person?.name ?? formatNodeId(meta.id)} + {formatNodeId(meta.id)} {#if meta.delegate} delegate diff --git a/src/views/projects/ProjectMeta.svelte b/src/views/projects/ProjectMeta.svelte index bbfe3c574..351fc30ed 100644 --- a/src/views/projects/ProjectMeta.svelte +++ b/src/views/projects/ProjectMeta.svelte @@ -1,13 +1,13 @@ {#each tree.entries as entry (entry.path)} - {#if window.HEARTWOOD ? entry.kind === "tree" : entry.info.objectType === "TREE"} + {#if entry.kind === "tree"} @@ -30,7 +30,7 @@ onSelect({ detail: entry.path })} /> {/if} {/each} diff --git a/src/views/projects/Tree/Folder.svelte b/src/views/projects/Tree/Folder.svelte index ca5aa72ef..a36195d53 100644 --- a/src/views/projects/Tree/Folder.svelte +++ b/src/views/projects/Tree/Folder.svelte @@ -74,10 +74,10 @@ {:then tree} {#if tree} {#each tree.entries as entry (entry.path)} - {#if window.HEARTWOOD ? entry.kind === "tree" : entry.info.objectType === "TREE"} + {#if entry.kind === "tree"} { onSelectFile({ detail: entry.path }); }} /> diff --git a/src/views/projects/View.svelte b/src/views/projects/View.svelte index ce2fd6b4b..a3140429c 100644 --- a/src/views/projects/View.svelte +++ b/src/views/projects/View.svelte @@ -1,10 +1,8 @@ - -{#if host === "radicle.local"} - -{:else} - -{/if} diff --git a/src/views/seeds/View.svelte b/src/views/seeds/View.svelte index bedcfbbc2..da8c6ddb8 100644 --- a/src/views/seeds/View.svelte +++ b/src/views/seeds/View.svelte @@ -1,25 +1,27 @@ @@ -81,7 +83,7 @@ {hostName} -{#await Seed.lookup(host, Number(port))} +{#await Seed.lookup(seedHost)}
@@ -99,17 +101,19 @@
Address
- +
Seed ID
- {formatSeedId(seed.id)} + {formatNodeId(seed.id)}
API Port
-
{port}
+
{seed.addr.port}
Version
@@ -133,7 +137,7 @@ {:catch}
{/await} diff --git a/src/views/seeds/View/Projects.svelte b/src/views/seeds/View/Projects.svelte index bf7b95cb3..a6ca6a0a2 100644 --- a/src/views/seeds/View/Projects.svelte +++ b/src/views/seeds/View/Projects.svelte @@ -6,6 +6,7 @@ import * as router from "@app/lib/router"; import List from "@app/components/List.svelte"; import Widget from "@app/views/projects/Widget.svelte"; + import { config } from "@app/lib/config"; export let seed: Seed; export let projects: proj.ProjectInfo[]; @@ -39,9 +40,10 @@ params: { view: { resource: "tree" }, id: project.id, - seed: seed.addr.port - ? `${seed.addr.host}:${seed.addr.port}` - : seed.addr.host, + seed: + seed.addr.port === config.seeds.defaultHttpdPort + ? seed.addr.host + : `${seed.addr.host}:${seed.addr.port}`, revision: project.head ?? undefined, hash: undefined, search: undefined, diff --git a/tests/e2e/clipboard.spec.ts b/tests/e2e/clipboard.spec.ts index 2856a4167..36b68b386 100644 --- a/tests/e2e/clipboard.spec.ts +++ b/tests/e2e/clipboard.spec.ts @@ -3,7 +3,6 @@ import { expect, projectFixtureUrl, rid, - ridPrefix, seedRemote, test, } from "@tests/support/fixtures.js"; @@ -37,33 +36,43 @@ test("copy to clipboard", async ({ page, browserName, context }) => { const clipboardContent = await page.evaluate( "navigator.clipboard.readText()", ); - expect(clipboardContent).toBe(`${ridPrefix}${rid}`); + expect(clipboardContent).toBe(`${rid}`); } // `rad clone` URL. { await page.getByText("Clone").click(); - await page - .locator(`text=rad clone rad://0.0.0.0/${rid.substring(0, 6)}`) - .hover(); + await page.locator(`text=rad clone ${rid.substring(0, 6)}`).hover(); await page .locator(".clone-url-wrapper > span") .first() .locator(".clipboard") .click(); - await expectClipboard(`rad clone rad://0.0.0.0/${rid}`, page); + await expectClipboard(`rad clone ${rid}`, page); } // `git clone` URL. { await page.getByText("Clone").click(); - await page.locator(`text=https://0.0.0.0/${rid.substring(0, 6)}`).hover(); + await page + .locator( + `text=git clone https://0.0.0.0/${rid + .replace("rad:", "") + .substring(0, 10)}`, + ) + .hover(); await page .locator(".clone-url-wrapper > span") .last() .locator(".clipboard") .click(); - await expectClipboard(`https://0.0.0.0/${rid}.git`, page); + await expectClipboard( + `git clone https://0.0.0.0/${rid.replace( + "rad:", + "", + )}.git source-browsing`, + page, + ); } await page.goto("/seeds/radicle.local"); diff --git a/tests/e2e/project.spec.ts b/tests/e2e/project.spec.ts index 0e4859b2c..4b65d8d8d 100644 --- a/tests/e2e/project.spec.ts +++ b/tests/e2e/project.spec.ts @@ -6,7 +6,6 @@ import { expect, projectFixtureUrl, rid, - ridPrefix, test, } from "@tests/support/fixtures.js"; import { expectUrlPersistsReload } from "@tests/support/router"; @@ -29,7 +28,7 @@ test("navigate to project", async ({ page }) => { // Header. { const name = page.locator("text=source-browsing"); - const id = page.locator(`text=${ridPrefix}${rid}`); + const id = page.locator(`text=${rid}`); const description = page.locator( "text=Git repository for source browsing tests", ); @@ -245,10 +244,10 @@ test("clone modal", async ({ page }) => { await page.goto(projectFixtureUrl); await page.getByText("Clone").click(); + await expect(page.locator(`text=rad clone ${rid}`)).toBeVisible(); await expect( - page.locator(`text=rad clone rad://0.0.0.0/${rid}`), + page.locator(`text=https://0.0.0.0/${rid.replace("rad:", "")}.git`), ).toBeVisible(); - await expect(page.locator(`text=https://0.0.0.0/${rid}.git`)).toBeVisible(); }); test("peer and branch switching", async ({ page }) => { @@ -257,18 +256,13 @@ test("peer and branch switching", async ({ page }) => { // Alice's peer. { await page.getByTitle("Change peer").click(); - if (process.env.HEARTWOOD) { - await page.locator(`text=${aliceRemote}`).click(); - await expect(page.getByTitle("Change peer")).toHaveText( - `did:key:${aliceRemote.substring(0, 6)}โ€ฆ${aliceRemote.slice(-6)}`, - ); - } else { - await page.locator("text=alice").click(); - await expect(page.getByTitle("Change peer")).toHaveText("alice delegate"); - } + await page.locator(`text=${aliceRemote.substring(0, 6)}`).click(); + await expect(page.getByTitle("Change peer")).toHaveText( + `did:key:${aliceRemote.substring(0, 6)}โ€ฆ${aliceRemote.slice(-6)}`, + ); await expect( page.locator( - `text=source-browsing / ${aliceRemote.substring( + `text=source-browsing / did:key:${aliceRemote.substring( 0, 6, )}โ€ฆ${aliceRemote.slice(-6)}`, @@ -326,32 +320,19 @@ test("peer and branch switching", async ({ page }) => { // Bob's peer. { await page.getByTitle("Change peer").click(); - if (process.env.HEARTWOOD) { - await page.locator(`text=${bobRemote}`).click(); - await expect(page.getByTitle("Change peer")).toHaveText( - `did:key:${bobRemote.substring(0, 6)}โ€ฆ${bobRemote.slice(-6)}`, - ); - } else { - await page.locator("text=bob").click(); - await expect(page.getByTitle("Change peer")).toHaveText("bob"); - } + await page.locator(`text=${bobRemote.substring(0, 6)}`).click(); + await expect(page.getByTitle("Change peer")).toHaveText( + `did:key:${bobRemote.substring(0, 6)}โ€ฆ${bobRemote.slice(-6)}`, + ); await expect(page.getByTitle("Change peer")).not.toHaveText("delegate"); // Default `main` branch. { - if (process.env.HEARTWOOD) { - await expect(page.getByTitle("Current branch")).toContainText( - "main 1e0bb83", - ); - await expectCounts({ commits: 9, contributors: 2 }, page); - await expect(page.locator("text=1e0bb83 Update readme")).toBeVisible(); - } else { - await expect(page.getByTitle("Current branch")).toContainText( - "main 2b32f6f", - ); - await expectCounts({ commits: 9, contributors: 2 }, page); - await expect(page.locator("text=2b32f6f Update readme")).toBeVisible(); - } + await expect(page.getByTitle("Current branch")).toContainText( + "main 1e0bb83", + ); + await expectCounts({ commits: 9, contributors: 2 }, page); + await expect(page.locator("text=1e0bb83 Update readme")).toBeVisible(); } } }); @@ -360,11 +341,7 @@ test("only one modal can be open at a time", async ({ page }) => { await page.goto(projectFixtureUrl); await page.getByTitle("Change peer").click(); - if (process.env.HEARTWOOD) { - await page.locator(`text=${aliceRemote.substring(0, 6)}`).click(); - } else { - await page.locator(`text=alice ${aliceRemote.substring(0, 6)}`).click(); - } + await page.locator(`text=${aliceRemote.substring(0, 6)}`).click(); await page.getByText("Clone").click(); await expect(page.locator("text=Code font")).not.toBeVisible(); @@ -381,11 +358,7 @@ test("only one modal can be open at a time", async ({ page }) => { await page.getByTitle("Change peer").click(); await expect(page.locator("text=Code font")).not.toBeVisible(); await expect(page.locator("text=Use the Radicle CLI")).not.toBeVisible(); - if (process.env.HEARTWOOD) { - await expect(page.locator(`text=${bobRemote}`)).toBeVisible(); - } else { - await expect(page.locator("text=bob hyyzz9")).toBeVisible(); - } + await expect(page.locator(`text=${bobRemote.substring(0, 6)}`)).toBeVisible(); await expect(page.locator("text=feature/branch")).not.toBeVisible(); await page.locator('button[name="Settings"]').click(); @@ -398,7 +371,7 @@ test("only one modal can be open at a time", async ({ page }) => { test.describe("browser error handling", () => { test("error appears when folder can't be loaded", async ({ page }) => { await page.route( - `**/v1/projects/${ridPrefix}${rid}/tree/${aliceMainHead}/markdown/`, + `**/v1/projects/${rid}/tree/${aliceMainHead}/markdown/`, route => route.fulfill({ status: 500 }), ); @@ -413,7 +386,7 @@ test.describe("browser error handling", () => { }); test("error appears when file can't be loaded", async ({ page }) => { await page.route( - `**/v1/projects/${ridPrefix}${rid}/blob/${aliceMainHead}/.hidden`, + `**/v1/projects/${rid}/blob/${aliceMainHead}/.hidden`, route => route.fulfill({ status: 500 }), ); @@ -423,9 +396,8 @@ test.describe("browser error handling", () => { await expect(page.locator("text=Not able to load file")).toBeVisible(); }); test("error appears when README can't be loaded", async ({ page }) => { - await page.route( - `**/v1/projects/${ridPrefix}${rid}/readme/${aliceMainHead}`, - route => route.fulfill({ status: 500 }), + await page.route(`**/v1/projects/${rid}/readme/${aliceMainHead}`, route => + route.fulfill({ status: 500 }), ); await page.goto(projectFixtureUrl); @@ -435,7 +407,7 @@ test.describe("browser error handling", () => { }); test("error appears when navigating to missing file", async ({ page }) => { await page.route( - `**/v1/projects/${ridPrefix}${rid}/blob/${aliceMainHead}/.hidden`, + `**/v1/projects/${rid}/blob/${aliceMainHead}/.hidden`, route => route.fulfill({ status: 500 }), ); @@ -447,7 +419,7 @@ test.describe("browser error handling", () => { page, }) => { await page.route( - `**/v1/projects/${ridPrefix}${rid}/blob/${aliceMainHead}/src/black-square.png`, + `**/v1/projects/${rid}/blob/${aliceMainHead}/src/black-square.png`, route => route.fulfill({ status: 404 }), ); diff --git a/tests/e2e/project/commit.spec.ts b/tests/e2e/project/commit.spec.ts index adb75b59f..6e288b91c 100644 --- a/tests/e2e/project/commit.spec.ts +++ b/tests/e2e/project/commit.spec.ts @@ -5,18 +5,12 @@ import { bobRemote, } from "@tests/support/fixtures.js"; -const modifiedFileFixture = `${projectFixtureUrl}/remotes/${bobRemote}/commits/${ - process.env.HEARTWOOD - ? "1e0bb83a89b63da815f2fc24e7ae3c5ceb30e0eb" - : "2b32f6fe50090ebdb4cd7441e943330da3e6ff04" -}`; +const modifiedFileFixture = `${projectFixtureUrl}/remotes/${bobRemote}/commits/${"1e0bb83a89b63da815f2fc24e7ae3c5ceb30e0eb"}`; test("navigation from commit list", async ({ page }) => { await page.goto(projectFixtureUrl); await page.getByTitle("Change peer").click(); - await page - .locator(process.env.HEARTWOOD ? `text=${bobRemote}` : "text=bob hyyzz9") - .click(); + await page.locator(`text=${bobRemote.substring(0, 6)}`).click(); await page.locator('role=button[name="Commit count"]').click(); await page.locator("text=Update readme").click(); @@ -35,13 +29,7 @@ test("relative timestamps", async ({ page }) => { }); await page.goto(modifiedFileFixture); await expect( - page.locator( - `.commit header >> text=${ - process.env.HEARTWOOD - ? "Bob Belcher committed now" - : "bob committed 22 hours ago" - }`, - ), + page.locator(`.commit header >> text=${"Bob Belcher committed now"}`), ).toBeVisible(); }); @@ -52,16 +40,9 @@ test("modified file", async ({ page }) => { { const header = page.locator(".commit header"); await expect(header.locator("text=Update readme")).toBeVisible(); - if (!process.env.HEARTWOOD) { - await expect(header.locator("text=Verified")).toBeVisible(); - await expect( - header.locator("text=2b32f6fe50090ebdb4cd7441e943330da3e6ff04"), - ).toBeVisible(); - } else { - await expect( - header.locator("text=1e0bb83a89b63da815f2fc24e7ae3c5ceb30e0eb"), - ).toBeVisible(); - } + await expect( + header.locator("text=1e0bb83a89b63da815f2fc24e7ae3c5ceb30e0eb"), + ).toBeVisible(); } // Diff header. diff --git a/tests/e2e/project/commits.spec.ts b/tests/e2e/project/commits.spec.ts index f81da4359..b2729a9a6 100644 --- a/tests/e2e/project/commits.spec.ts +++ b/tests/e2e/project/commits.spec.ts @@ -13,15 +13,10 @@ test("peer and branch switching", async ({ page }) => { // Alice's peer. { await page.getByTitle("Change peer").click(); - if (process.env.HEARTWOOD) { - await page.locator(`text=${aliceRemote}`).click(); - await expect(page.getByTitle("Change peer")).toHaveText( - `did:key:${aliceRemote.substring(0, 6)}โ€ฆ${aliceRemote.slice(-6)}`, - ); - } else { - await page.locator("text=alice hybg18").click(); - await expect(page.getByTitle("Change peer")).toHaveText("alice delegate"); - } + await page.locator(`text=${aliceRemote.substring(0, 6)}`).click(); + await expect(page.getByTitle("Change peer")).toHaveText( + `did:key:${aliceRemote.substring(0, 6)}โ€ฆ${aliceRemote.slice(-6)}`, + ); await expect(page.getByText("Thursday, November 17, 2022")).toBeVisible(); await expect( @@ -66,20 +61,15 @@ test("peer and branch switching", async ({ page }) => { // Bob's peer. { await page.getByTitle("Change peer").click(); - if (process.env.HEARTWOOD) { - await page.locator(`text=${bobRemote}`).click(); - await expect(page.getByTitle("Change peer")).toHaveText( - `did:key:${bobRemote.substring(0, 6)}โ€ฆ${bobRemote.slice(-6)}`, - ); - } else { - await page.locator("text=bob hyyzz9").click(); - await expect(page.getByTitle("Change peer")).toHaveText("bob"); - } + await page.locator(`text=${bobRemote.substring(0, 6)}`).click(); + await expect(page.getByTitle("Change peer")).toHaveText( + `did:key:${bobRemote.substring(0, 6)}โ€ฆ${bobRemote.slice(-6)}`, + ); await expect(page.getByText("Tuesday, December 20, 2022")).toBeVisible(); await expect( page.locator(".commit-group-headers").first().locator(".commit-teaser"), - ).toHaveCount(process.env.HEARTWOOD ? 1 : 3); + ).toHaveCount(1); await expect(page.getByText("Thursday, November 17, 2022")).toBeVisible(); await expect( @@ -88,13 +78,8 @@ test("peer and branch switching", async ({ page }) => { await page.pause(); const latestCommit = page.locator(".commit-teaser").first(); - if (process.env.HEARTWOOD) { - await expect(latestCommit).toContainText("Update readme"); - await expect(latestCommit).toContainText("1e0bb83"); - } else { - await expect(latestCommit).toContainText("Update readme"); - await expect(latestCommit).toContainText("2b32f6f"); - } + await expect(latestCommit).toContainText("Update readme"); + await expect(latestCommit).toContainText("1e0bb83"); const earliestCommit = page.locator(".commit-teaser").last(); await expect(earliestCommit).toContainText( @@ -104,30 +89,6 @@ test("peer and branch switching", async ({ page }) => { } }); -test("verified badge", async ({ page }) => { - await page.goto(projectFixtureUrl); - await page.locator('role=button[name="Commit count"]').click(); - - await page.getByTitle("Change peer").click(); - if (process.env.HEARTWOOD) { - await page.locator(`text=${bobRemote}`).click(); - await expect(page.getByTitle("Change peer")).toHaveText( - `did:key:${bobRemote.substring(0, 6)}โ€ฆ${bobRemote.slice(-6)}`, - ); - } else { - await page.locator("text=bob hyyzz9").click(); - await expect(page.getByTitle("Change peer")).toHaveText("bob"); - // not applicable to heartwood? - await page.locator("text=Verified").hover(); - await expect( - page.locator( - "text=This commit was signed with the committer's radicle key.", - ), - ).toBeVisible(); - await expect(page.locator(`text=bob committed ${bobRemote}`)).toBeVisible(); - } -}); - test("relative timestamps", async ({ page }) => { await page.addInitScript(() => { window.initializeTestStubs = () => { @@ -143,22 +104,13 @@ test("relative timestamps", async ({ page }) => { await page.locator('role=button[name="Commit count"]').click(); await page.getByTitle("Change peer").click(); - if (process.env.HEARTWOOD) { - await page.locator(`text=${bobRemote}`).click(); - await expect(page.getByTitle("Change peer")).toHaveText( - `did:key:${bobRemote.substring(0, 6)}โ€ฆ${bobRemote.slice(-6)}`, - ); - const latestCommit = page.locator(".commit-teaser").first(); - await expect(latestCommit).toContainText("Bob Belcher committed now"); - await expect(latestCommit).toContainText("1e0bb83"); - } else { - await page.locator("text=bob hyyzz9").click(); - await expect(page.getByTitle("Change peer")).toHaveText("bob"); - const latestCommit = page.locator(".commit-teaser").first(); - await expect(latestCommit).toContainText("bob committed 22 hours ago"); - await expect(latestCommit).toContainText("2b32f6f"); - } - + await page.locator(`text=${bobRemote.substring(0, 6)}`).click(); + await expect(page.getByTitle("Change peer")).toHaveText( + `did:key:${bobRemote.substring(0, 6)}โ€ฆ${bobRemote.slice(-6)}`, + ); + const latestCommit = page.locator(".commit-teaser").first(); + await expect(latestCommit).toContainText("Bob Belcher committed now"); + await expect(latestCommit).toContainText("1e0bb83"); const earliestCommit = page.locator(".commit-teaser").last(); await expect(earliestCommit).toContainText( "Alice Liddell committed last month", diff --git a/tests/e2e/search.spec.ts b/tests/e2e/search.spec.ts index f0d0071ba..5e64f3a8a 100644 --- a/tests/e2e/search.spec.ts +++ b/tests/e2e/search.spec.ts @@ -2,7 +2,6 @@ import { test, expect, rid, - ridPrefix, projectFixtureUrl, } from "@tests/support/fixtures.js"; @@ -10,11 +9,11 @@ test("navigate to existing project", async ({ page }) => { await page.goto("/"); const searchInput = page.getByPlaceholder("Search a nameโ€ฆ"); await searchInput.click(); - await searchInput.fill(`${ridPrefix}${rid}`); + await searchInput.fill(`${rid}`); await searchInput.press("Enter"); await expect(page).toHaveURL(`${projectFixtureUrl}/tree`); - await expect(searchInput).not.toHaveValue(`${ridPrefix}${rid}`); + await expect(searchInput).not.toHaveValue(`${rid}`); }); test("navigate to a project that does not exist", async ({ page }) => { @@ -22,7 +21,7 @@ test("navigate to a project that does not exist", async ({ page }) => { const searchInput = page.getByPlaceholder("Search a nameโ€ฆ"); await searchInput.click(); - const nonExistantId = `${ridPrefix}:zt${rid.substring(2)}`; + const nonExistantId = "rad:zAAAAAAAAAAAAAAAAAAAAAAAAAAA"; await searchInput.fill(nonExistantId); await searchInput.press("Enter"); diff --git a/tests/e2e/seed.spec.ts b/tests/e2e/seed.spec.ts index 88440d873..b4d79bc30 100644 --- a/tests/e2e/seed.spec.ts +++ b/tests/e2e/seed.spec.ts @@ -2,7 +2,6 @@ import { aliceMainHead, expect, rid, - ridPrefix, seedPort, seedRemote, seedVersion, @@ -44,8 +43,8 @@ test("seed projects", async ({ page }) => { // Show project ID on hover. { - await expect(project.locator(`text=${ridPrefix}${rid}`)).not.toBeVisible(); + await expect(project.locator(`text=${rid}`)).not.toBeVisible(); await project.hover(); - await expect(project.locator(`text=${ridPrefix}${rid}`)).toBeVisible(); + await expect(project.locator(`text=${rid}`)).toBeVisible(); } }); diff --git a/tests/fixtures/seeds/palm-heartwood.tar.bz2 b/tests/fixtures/seeds/palm-heartwood.tar.bz2 deleted file mode 100644 index e492b95abcc20f3e1650bcc76d2d1e5d291dbedf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28873 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%0A*Y(8!^!oZ!ISk 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 Y#MhD@VkQaz!{$kXd2z+Ht^OS^xk5 diff --git a/tests/fixtures/seeds/palm.tar.bz2 b/tests/fixtures/seeds/palm.tar.bz2 index f3a741854814b4712839c8c6c5d174c7693b01cf..e492b95abcc20f3e1650bcc76d2d1e5d291dbedf 100644 GIT binary patch literal 28873 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%0A*Y(8!^!oZ!ISk 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 Y#MhD@VkQaz!{$kXd2z+Ht^OS^xk5 literal 36569 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 hijvKd>4$DJ-tDky$(dw_ZGr#d?ntK!5&`qPW { async function assertHttpApiRunning(): Promise { const notRunningMessage = "The http-api server with test fixtures needs to be running.\n" + - (process.env.HEARTWOOD - ? "๐Ÿ‘‰ You can start it with `./scripts/run-httpd-with-fixtures`\n" - : "๐Ÿ‘‰ You can start it with `./scripts/run-http-api-with-fixtures`\n"); + "๐Ÿ‘‰ You can start it with `./scripts/run-httpd-with-fixtures`\n"; - let peerId: string | undefined = undefined; + let nodeId: string | undefined = undefined; try { - if (process.env.HEARTWOOD) { - const response = await fetch(`http://0.0.0.0:${seedPort}/api`); - const data = await response.json(); - peerId = data.node.id; - } else { - const response = await fetch(`http://0.0.0.0:${seedPort}`); - const data = await response.json(); - peerId = data.peer.id; - } + const response = await fetch(`http://0.0.0.0:${seedPort}/api`); + const data = await response.json(); + nodeId = data.node.id; } catch (err) { console.error(err); throw new Error(notRunningMessage); } - if (peerId !== seedRemote) { + if (nodeId !== seedRemote) { const wrongSeedMessage = `The server on port ${seedPort} doesn't have the right fixtures.\n`; throw new Error(wrongSeedMessage + notRunningMessage); } diff --git a/tests/unit/utils.test.ts b/tests/unit/utils.test.ts index 411ad12d0..4afd9d28a 100644 --- a/tests/unit/utils.test.ts +++ b/tests/unit/utils.test.ts @@ -9,6 +9,15 @@ describe("Format functions", () => { expect(utils.formatLocationHash(hash)).toEqual(expected); }); + test.each([ + { + id: "rad:zKtT7DmF9H34KkvcKj9PHW19WzjT", + expected: "rad:zKtT7Dโ€ฆ19WzjT", + }, + ])("formatRepositoryId $id => $expected", ({ id, expected }) => { + expect(utils.formatRepositoryId(id)).toEqual(expected); + }); + test.each([ { id: "did:key:z6MkmzRwg47UWQxczLLLFfkEwpBGitjzJ1vKPE8U9ymd6fz6", @@ -22,22 +31,17 @@ describe("Format functions", () => { expect(utils.formatNodeId(id)).toEqual(expected); }); - test("formatRadicleId", () => { - if (process.env.HEARTWOOD) { - expect(utils.formatRadicleId("rad:zKtT7DmF9H34KkvcKj9PHW19WzjT")).toEqual( - "rad:zKtT7Dโ€ฆ19WzjT", - ); - } else { - expect( - utils.formatRadicleId("rad:git:hnrkemobagsicpf9sr95o3g551otspcd84c9o"), - ).toEqual("rad:git:hnrkemโ€ฆd84c9o"); - } - }); - - test("formatRadicleId throw when wrong ID", () => { - expect(() => - utils.formatRadicleId("hnrkemobagsicpf9sr95o3g551otspcd84c9o"), - ).toThrow(); + test.each([ + { + id: "rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5", + expected: "rad:z4V1sjโ€ฆp4DtH5", + }, + { + id: "z4V1sjrXqjvFdnCUbxPFqd5p4DtH5", + expected: "rad:z4V1sjโ€ฆp4DtH5", + }, + ])("formatRepositoryId $id => $expected", ({ id, expected }) => { + expect(utils.formatRepositoryId(id)).toEqual(expected); }); test.each([ @@ -67,19 +71,40 @@ describe("String Assertions", () => { }); test.each([ - process.env.HEARTWOOD - ? { id: "rad:zKtT7DmF9H34KkvcKj9PHW19WzjT", expected: true } - : { id: "rad:git:hnrkemobagsicpf9sr95o3g551otspcd84c9o", expected: true }, + { id: "rad:zKtT7DmF9H34KkvcKj9PHW19WzjT", expected: true }, + { id: "z2H9aHDurxd8Uvx2jsvW4e5mamy5S", expected: true }, + { id: "rad:BBBBBBBBBBBBBBBBBBBBBBBBBBBB", expected: false }, { id: "0x1234567890123456789012345678901234567890", expected: false }, - ])("isRadicleId $id => $expected", ({ id, expected }) => { - expect(utils.isRadicleId(id)).toEqual(expected); + { + id: "did:key:z6MkwPUeUS2fJMfc2HZN1RQTQcTTuhw4HhPySB8JeUg2mVvx", + expected: false, + }, + { + id: "z6MkwPUeUS2fJMfc2HZN1RQTQcTTuhw4HhPySB8JeUg2mVvx", + expected: false, + }, + ])("isRepositoryId $id => $expected", ({ id, expected }) => { + expect(utils.isRepositoryId(id)).toEqual(expected); }); test.each([ - { id: "hnrkj4c35uoyceb3d1dsscx8qq55cikrd1aio", expected: true }, + { + id: "did:key:z6MkwPUeUS2fJMfc2HZN1RQTQcTTuhw4HhPySB8JeUg2mVvx", + expected: true, + }, + { + id: "z6MkwPUeUS2fJMfc2HZN1RQTQcTTuhw4HhPySB8JeUg2mVvx", + expected: true, + }, + { + id: "did:key:CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC", + expected: false, + }, + { id: "rad:zKtT7DmF9H34KkvcKj9PHW19WzjT", expected: false }, + { id: "z2H9aHDurxd8Uvx2jsvW4e5mamy5S", expected: false }, { id: "0x1234567890123456789012345678901234567890", expected: false }, - ])("isPeerId $id => $expected", ({ id, expected }) => { - expect(utils.isPeerId(id)).toEqual(expected); + ])("isNodeId $id => $expected", ({ id, expected }) => { + expect(utils.isNodeId(id)).toEqual(expected); }); test.each([ @@ -131,8 +156,8 @@ describe("Parse Functions", () => { pubkey: "z6MkmzRwg47UWQxczLLLFfkEwpBGitjzJ1vKPE8U9ymd6fz6", }, }, - ])("parseNid", ({ input, expected }) => { - expect(utils.parseNid(input)).toEqual(expected); + ])("parseNodeId", ({ input, expected }) => { + expect(utils.parseNodeId(input)).toEqual(expected); }); }); diff --git a/vite.config.ts b/vite.config.ts index 320702dba..667b667c1 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -12,7 +12,6 @@ function defineConstants() { const constants = { VITEST: process.env.VITEST !== undefined, PLAYWRIGHT: process.env.PLAYWRIGHT_TEST_BASE_URL !== undefined, - HEARTWOOD: process.env.HEARTWOOD !== undefined, }; // Don't overwrite HASH_ROUTING in Playwright tests, so we can control it