From f72405a3e49d2370fc64263ebef883318004894d Mon Sep 17 00:00:00 2001 From: xphoniex Date: Tue, 27 Dec 2022 13:45:51 +0000 Subject: [PATCH] Add support for Heartwood MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Rūdolfs Ošiņš Signed-off-by: xphoniex Signed-off-by: Rūdolfs Ošiņš --- .github/workflows/check-e2e.yml | 11 +- scripts/create-seed-fixture-heartwood | 51 +++++++ scripts/run-http-api-with-fixtures | 32 ++--- scripts/run-httpd-with-fixtures | 132 ++++++++++++++++++ src/components/Authorship.svelte | 8 +- src/components/Form.svelte | 12 +- src/global.d.ts | 2 + src/lib/api.ts | 6 +- src/lib/diff.ts | 1 + src/lib/issue.ts | 29 ++-- src/lib/patch.ts | 14 +- src/lib/project.ts | 122 +++++++++------- src/lib/registrar.ts | 20 +-- src/lib/seed.ts | 57 +++++--- src/lib/utils.ts | 18 ++- src/views/projects/Blob.svelte | 4 +- src/views/projects/Commit.svelte | 5 +- src/views/projects/Commit/CommitTeaser.svelte | 2 +- src/views/projects/Header.svelte | 5 +- src/views/projects/Issue.svelte | 19 ++- src/views/projects/Patch.svelte | 4 +- src/views/projects/Patch/PatchTimeline.svelte | 12 +- src/views/projects/Tree.svelte | 8 +- src/views/projects/Tree/Folder.svelte | 7 +- src/views/registrations/View.svelte | 4 +- tests/e2e/project.spec.ts | 12 ++ tests/e2e/project/commit.spec.ts | 20 +++ tests/e2e/project/commits.spec.ts | 12 ++ tests/fixtures/seeds/palm-heartwood.tar.bz2 | Bin 0 -> 15745 bytes tests/support/fixtures.ts | 48 +++++-- tests/support/globalSetup.ts | 20 ++- tests/unit/router.test.ts | 9 +- tests/unit/utils.test.ts | 16 ++- tests/visual/landingPage.spec.ts | 10 ++ tests/visual/seed.spec.ts | 10 ++ vite.config.ts | 1 + 36 files changed, 561 insertions(+), 182 deletions(-) create mode 100755 scripts/create-seed-fixture-heartwood create mode 100755 scripts/run-httpd-with-fixtures create mode 100644 tests/fixtures/seeds/palm-heartwood.tar.bz2 diff --git a/.github/workflows/check-e2e.yml b/.github/workflows/check-e2e.yml index 36072c27b..5a876c68b 100644 --- a/.github/workflows/check-e2e.yml +++ b/.github/workflows/check-e2e.yml @@ -12,7 +12,7 @@ jobs: continue-on-error: true strategy: matrix: - browser: [chromium, firefox, visual] + browser: [chromium, firefox, visual, heartwood] timeout-minutes: 30 runs-on: ubuntu-latest steps: @@ -59,12 +59,19 @@ jobs: run: npx playwright install-deps - name: Start http-api test server - run: ./scripts/run-http-api-with-fixtures --non-interactive --detach + run: | + if [ ${{ matrix.browser }} = "heartwood" ]; then + ./scripts/run-httpd-with-fixtures --non-interactive --detach + else + ./scripts/run-http-api-with-fixtures --non-interactive --detach + fi - 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-heartwood b/scripts/create-seed-fixture-heartwood new file mode 100755 index 000000000..894425184 --- /dev/null +++ b/scripts/create-seed-fixture-heartwood @@ -0,0 +1,51 @@ +#!/usr/bin/env bash +set -euo pipefail + +PASSPHRASE=asdf +SEED="0.0.0.0:8080" + +REPO_ROOT=$(git rev-parse --show-toplevel) +ID=$(echo $RANDOM | md5sum | head -c 8) +BASE_PATH=$REPO_ROOT/tests/tmp/create-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 +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 $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 + +RAD_HOME=$PALM_RAD_HOME RAD_PASSPHRASE=$PASSPHRASE rad auth + +GIT_AUTHOR_NAME="Alice Liddell" +GIT_AUTHOR_EMAIL="alice@radicle.xyz" +GIT_COMMITTER_NAME="Alice Liddell" +GIT_COMMITTER_EMAIL="alice@radicle.xyz" + +RAD_DEBUG=1 RAD_HOME=$ALICE_RAD_HOME RAD_PASSPHRASE=$PASSPHRASE 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_HOME=$ALICE_RAD_HOME RAD_PASSPHRASE=$PASSPHRASE rad init --name "source-browsing" --description "Git repository for source browsing tests" --default-branch "main" --no-confirm +PROJECT_ID=$(RAD_HOME=$ALICE_RAD_HOME RAD_PASSPHRASE=$PASSPHRASE rad .) + +cd $BASE_PATH +tar -cjf palm.tar.bz2 --exclude "post-receive" --exclude "pre-receive" -C $ALICE_RAD_HOME . diff --git a/scripts/run-http-api-with-fixtures b/scripts/run-http-api-with-fixtures index d3947d4de..461d2fff1 100755 --- a/scripts/run-http-api-with-fixtures +++ b/scripts/run-http-api-with-fixtures @@ -10,8 +10,7 @@ PASSPHRASE=asdf CONTAINER_NAME=radicle-http-api-with-fixtures HTTP_API_BINARY=radicle-http-api -show_usage() -{ +show_usage() { echo echo "Starts a http-api backend with test fixtures." echo @@ -26,8 +25,7 @@ show_usage() echo } -prompt_workspace_removal() -{ +prompt_workspace_removal() { echo "This will irrevocably destroy the following directories:" echo echo $WORKSPACE @@ -35,19 +33,18 @@ prompt_workspace_removal() 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 - ;; + [yY][eE][sS]) + rm -rf $WORKSPACE + echo "Done" + ;; + *) + echo "Ok, I won't touch your data." + exit + ;; esac } -prepare_workspace() -{ +prepare_workspace() { echo echo "Unpacking fixture $FIXTURE" mkdir -p $WORKSPACE @@ -94,13 +91,13 @@ DETACH=false while [ $# -ne 0 ]; do case "$1" in - --binary|-b) + --binary | -b) BINARY=true ;; - --detach|-d) + --detach | -d) DETACH=true ;; - --non-interactive|-n) + --non-interactive | -n) NON_INTERACTIVE=true ;; *) @@ -120,7 +117,6 @@ else prepare_workspace fi - if [ "$BINARY" = true ]; then run_binary else diff --git a/scripts/run-httpd-with-fixtures b/scripts/run-httpd-with-fixtures new file mode 100755 index 000000000..78618c30d --- /dev/null +++ b/scripts/run-httpd-with-fixtures @@ -0,0 +1,132 @@ +#!/bin/sh +set -e + +REV=1f55d7a32750b3e63c56aad00370411b90420a29 + +REPO_ROOT=$(git rev-parse --show-toplevel) +FIXTURE=$REPO_ROOT/tests/fixtures/seeds/palm-heartwood.tar.bz2 +WORKSPACE=$REPO_ROOT/tests/tmp/palm +PASSPHRASE=asdf +CONTAINER_NAME=radicle-httpd-with-fixtures +HTTP_API_BINARY=radicle-httpd + +show_usage() { + echo + echo "Starts a radicle-httpd backend with test fixtures." + echo + echo "USAGE:" + echo " run-httpd-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 + if [ "$CI" = true ]; then + sudo chown -R 0:0 $WORKSPACE + fi +} + +run_docker() { + echo "Starting docker at container $CONTAINER_NAME at $REV" + echo " RAD_HOME=$WORKSPACE RAD_PASSPHRASE=$PASSPHRASE radicle-http" + echo + + exec docker run \ + --init \ + --publish 8080:8080 \ + --rm \ + --name $CONTAINER_NAME \ + --volume $WORKSPACE:/app/radicle \ + "$@" \ + --env "RAD_HOME=/app/radicle" \ + --env "RAD_PASSPHRASE=$PASSPHRASE" \ + "gcr.io/radicle-services/radicle-httpd:$REV" +} + +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/heartwood" + echo + exit 1 + fi + + echo + echo "Starting $HTTP_API_BINARY" + echo " RAD_HOME=$WORKSPACE $HTTP_API_BINARY" + echo + + RAD_HOME=$WORKSPACE RAD_PASSPHRASE=$PASSPHRASE $HTTP_API_BINARY +} + +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/src/components/Authorship.svelte b/src/components/Authorship.svelte index 70cf25360..a3d3af5d6 100644 --- a/src/components/Authorship.svelte +++ b/src/components/Authorship.svelte @@ -6,7 +6,11 @@ import Address from "@app/components/Address.svelte"; import { Profile, ProfileType } from "@app/lib/profile"; - import { formatRadicleId, formatTimestamp } from "@app/lib/utils"; + import { + formatRadicleId, + formatSeedId, + formatTimestamp, + } from "@app/lib/utils"; export let noAvatar = false; export let author: Author; @@ -67,7 +71,7 @@ {:else} - {formatRadicleId(author.id)} + {window.HEARTWOOD ? formatSeedId(author.id) : formatRadicleId(author.id)} {/if}  {caption}  diff --git a/src/components/Form.svelte b/src/components/Form.svelte index 35188d436..c402c498c 100644 --- a/src/components/Form.svelte +++ b/src/components/Form.svelte @@ -20,17 +20,19 @@ const validationExamples: Record = { URL: "https://acme.xyz/", - URN: "eip155:1:0xd1bb21bd5a432d2919c82bcefe1bc7f8cc9207d9", + ID: "eip155:1:0xd1bb21bd5a432d2919c82bcefe1bc7f8cc9207d9", handle: "acme", id: "hydkkcf6k9be5fuszdhpqbctu3q3fuwagj874wx2puia8ti8coygh1", - identity: "rad:git:hnrkqdpm9ub19oc8dccx44echy75hzfsezyio", + identity: window.HEARTWOOD + ? "rad:zKtT7DmF9H34KkvcKj9PHW19WzjT" + : "rad:git:hnrkqdpm9ub19oc8dccx44echy75hzfsezyio", domain: "seed.acme.xyz", address: "0x17a8c096733BD5F87aD43D7A2A4d1C42ab8A2A70", }; const validationTypes: { [index: string]: RegExp } = { URL: /^(https:\/\/|http:\/\/|ipfs:\/\/)\S+/, - URN: /^[a-z]+:[a-zA-Z0-9:-]{1,64}$/, + ID: /^z[a-z]+:[a-zA-Z0-9:-]{1,64}$/, // Github // Username may only contain alphanumeric characters or hyphens. // Username cannot have multiple consecutive hyphens. @@ -43,7 +45,9 @@ handle: /^[a-zA-Z0-9-_]{1,39}$/, address: /^0x[a-zA-Z0-9]{40}$/, id: /^[a-z0-9]+$/, - identity: /^rad:git:[a-z0-9]{37}$/, + identity: window.HEARTWOOD + ? /^rad:[a-z0-9]{28}$/ + : /^rad:git:[a-z0-9]{37}$/, domain: /^[^/:$!_;,@#]+\.[a-z]{2,}$/, }; diff --git a/src/global.d.ts b/src/global.d.ts index 744f264ac..67d3d6d48 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -10,6 +10,8 @@ declare global { PLAYWRIGHT: boolean; HASH_ROUTING: boolean; + HEARTWOOD: boolean; + // APP_CONFIG is set from within Playwright tests at runtime. // To better understand how it works together, have a look at: // tests/support/fixtures.ts diff --git a/src/lib/api.ts b/src/lib/api.ts index 3092ebf09..8a9207be2 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -13,7 +13,11 @@ export class Request { constructor(path: string, api: Host) { this.port = api.port || defaultSeedPort; - this.base = api.host; + if (window.HEARTWOOD) { + this.base = api.host + "/api"; + } else { + this.base = api.host; + } this.path = path.startsWith("/") ? path.slice(1) : path; this.protocol = api.host === "0.0.0.0" ? "http://" : "https://"; } diff --git a/src/lib/diff.ts b/src/lib/diff.ts index 086bbddf6..a2321f2ba 100644 --- a/src/lib/diff.ts +++ b/src/lib/diff.ts @@ -89,6 +89,7 @@ export interface Diff { moved: string[]; copied: string[]; modified: FileDiff[]; + stats: DiffStats; } export interface DiffStats { diff --git a/src/lib/issue.ts b/src/lib/issue.ts index 8e82765a6..25326afd1 100644 --- a/src/lib/issue.ts +++ b/src/lib/issue.ts @@ -12,7 +12,7 @@ export interface IIssue { author: Author; title: string; state: State; - comment: Comment; + comment: Comment; // TODO: Remove this after we have migrated to Heartwood. discussion: Thread[]; tags: Tag[]; timestamp: number; @@ -32,7 +32,8 @@ export interface Comment { body: string; reactions: Record; timestamp: number; - replies: R; + replies: R; // TODO: Remove this after we have migrated to Heartwood. + replyTo: R; } export type Thread = Comment; @@ -57,7 +58,7 @@ export class Issue { author: Author; title: string; state: State; - comment: Comment; + comment: Comment; // TODO: Remove this after we have migrated to Heartwood. discussion: Thread[]; tags: Tag[]; timestamp: number; @@ -67,18 +68,28 @@ export class Issue { this.author = issue.author; this.title = issue.title; this.state = issue.state; - this.comment = issue.comment; + this.comment = issue.comment; // TODO: Remove this after we have migrated to Heartwood. this.discussion = issue.discussion; this.tags = issue.tags; - this.timestamp = issue.timestamp; + if (window.HEARTWOOD) { + this.timestamp = issue.discussion[0].timestamp; + } else { + this.timestamp = issue.timestamp; + } } // Counts the amount of comments and replies in a discussion countComments(): number { - return this.discussion.reduce((acc, comment) => { - if (comment.replies) return acc + comment.replies.length + 1; // We add all replies and 1 forathe comment in this loop. - return acc + 1; // If there are no replies, we simply add 1 for the comment in this loop. - }, 0); + if (window.HEARTWOOD) { + return this.discussion.reduce(acc => { + return acc + 1; // If there are no replies, we simply add 1 for the comment in this loop. + }, 0); + } else { + return this.discussion.reduce((acc, comment) => { + if (comment.replies) return acc + comment.replies.length + 1; // We add all replies and 1 forathe comment in this loop. + return acc + 1; // If there are no replies, we simply add 1 for the comment in this loop. + }, 0); + } } static async getIssues(id: string, host: Host): Promise { diff --git a/src/lib/patch.ts b/src/lib/patch.ts index e3bd5da9c..c6a8fedff 100644 --- a/src/lib/patch.ts +++ b/src/lib/patch.ts @@ -100,10 +100,16 @@ export class Patch implements IPatch { // Counts the amount of comments and replies in a discussion countComments(rev: number): number { - return this.revisions[rev].discussion.reduce((acc, comment) => { - if (comment.replies) return acc + comment.replies.length + 1; // We add all replies and 1 for each comment in this loop. - return acc + 1; // If there are no replies, we simply add 1 for the comment in this loop. - }, 0); + if (window.HEARTWOOD) { + return this.revisions[rev].discussion.reduce(acc => { + return acc + 1; // If there are no replies, we simply add 1 for the comment in this loop. + }, 0); + } else { + return this.revisions[rev].discussion.reduce((acc, comment) => { + if (comment.replies) return acc + comment.replies.length + 1; // We add all replies and 1 for each comment in this loop. + return acc + 1; // If there are no replies, we simply add 1 for the comment in this loop. + }, 0); + } } createTimeline(rev: number) { diff --git a/src/lib/project.ts b/src/lib/project.ts index a52b4f906..19914a2a4 100644 --- a/src/lib/project.ts +++ b/src/lib/project.ts @@ -12,6 +12,7 @@ export type Branches = { [key: string]: string }; export type MaybeBlob = Blob | undefined; export type MaybeTree = Tree | undefined; +// TODO: Remove this after we have migrated to Heartwood. export type Delegate = | { type: "indirect"; @@ -40,38 +41,43 @@ export interface ProjectInfo { name: string; description: string; defaultBranch: string; - delegates: Delegate[]; - remotes: PeerId[]; + delegates: Delegate[]; // TODO: Remove this after we have migrated to Heartwood. + remotes: PeerId[]; // TODO: Remove this after we have migrated to Heartwood. patches?: number; issues?: number; } export interface Tree { path: string; - info: EntryInfo; + info: EntryInfo; // TODO: Remove this after we have migrated to Heartwood. entries: Array; stats: Stats; + name: string; + kind: Kind; + lastCommit: CommitHeader; } +// TODO: Remove "TREE" and "BLOB" after we have migrated to Heartwood. +type Kind = "tree" | "blob" | "TREE" | "BLOB"; + export interface Stats { commits: number; contributors: number; } -export enum ObjectType { - Blob = "BLOB", - Tree = "TREE", -} - +// TODO: Remove this after we have migrated to Heartwood. export interface EntryInfo { name: string; - objectType: ObjectType; + objectType: Kind; lastCommit: CommitHeader; } export interface Entry { path: string; - info: EntryInfo; + info: EntryInfo; // TODO: Remove this after we have migrated to Heartwood. + name: string; + kind: Kind; + lastCommit: CommitHeader; } export interface Blob { @@ -79,7 +85,10 @@ export interface Blob { html?: boolean; content: string; path: string; - info: EntryInfo; + info: EntryInfo; // TODO: Remove this after we have migrated to Heartwood. + name: string; + kind: Kind; + lastCommit: CommitHeader; } export interface Remote { @@ -144,8 +153,8 @@ export class Project implements ProjectInfo { name: string; description: string; defaultBranch: string; - delegates: Delegate[]; - remotes: PeerId[]; + delegates: Delegate[]; // TODO: Remove this after we have migrated to Heartwood. + remotes: PeerId[]; // TODO: Remove this after we have migrated to Heartwood. seed: Seed; peers: Peer[]; branches: Branches; @@ -167,8 +176,8 @@ export class Project implements ProjectInfo { this.name = info.name; this.description = info.description; this.defaultBranch = info.defaultBranch; - this.delegates = info.delegates; - this.remotes = info.remotes; + this.delegates = info.delegates; // TODO: Remove this after we have migrated to Heartwood. + this.remotes = info.remotes; // TODO: Remove this after we have migrated to Heartwood. this.seed = seed; this.peers = peers; this.branches = branches; @@ -192,10 +201,14 @@ export class Project implements ProjectInfo { } static async getInfo(nameOrId: string, host: Host): Promise { - const result = await new Request(`projects/${nameOrId}`, host).get(); - result["id"] = result["urn"]; - delete result["urn"]; - return result; + if (window.HEARTWOOD) { + return await new Request(`projects/${nameOrId}`, host).get(); + } else { + const result = await new Request(`projects/${nameOrId}`, host).get(); + result["id"] = result["urn"]; + delete result["urn"]; + return result; + } } static async getProjects( @@ -209,13 +222,17 @@ export class Project implements ProjectInfo { "per-page": opts?.perPage, page: opts?.page, }; - const results = await new Request("projects", host).get(params); - results.forEach((result: { [x: string]: any }) => { - result["id"] = result["urn"]; - delete result["urn"]; - }); + if (window.HEARTWOOD) { + return await new Request("projects", host).get(params); + } else { + const results = await new Request("projects", host).get(params); + results.forEach((result: { [x: string]: any }) => { + result["id"] = result["urn"]; + delete result["urn"]; + }); - return results; + return results; + } } static async getDelegateProjects( @@ -280,28 +297,31 @@ export class Project implements ProjectInfo { `projects/${this.id}/commits/${commit}`, this.seed.addr, ).get(); - result.stats["insertions"] = result.stats["additions"]; - delete result.stats["additions"]; - result.diff["added"] = result.diff["created"]; - delete result.diff["created"]; - for (const kind of ["added", "deleted", "modified"]) { - for (const file of result.diff[kind]) { - for (const hunk of file.diff.hunks) { - for (const line of hunk.lines) { - if (line["lineNumOld"]) { - line["lineNoOld"] = line["lineNumOld"]; - delete line["lineNumOld"]; - } + if (!window.HEARTWOOD) { + result.stats["insertions"] = result.stats["additions"]; + delete result.stats["additions"]; + result.diff["added"] = result.diff["created"]; + delete result.diff["created"]; - if (line["lineNumNew"]) { - line["lineNoNew"] = line["lineNumNew"]; - delete line["lineNumNew"]; - } + for (const kind of ["added", "deleted", "modified"]) { + for (const file of result.diff[kind]) { + for (const hunk of file.diff.hunks) { + for (const line of hunk.lines) { + if (line["lineNumOld"]) { + line["lineNoOld"] = line["lineNumOld"]; + delete line["lineNumOld"]; + } - if (line["lineNum"]) { - line["lineNo"] = line["lineNum"]; - delete line["lineNum"]; + if (line["lineNumNew"]) { + line["lineNoNew"] = line["lineNumNew"]; + delete line["lineNumNew"]; + } + + if (line["lineNum"]) { + line["lineNo"] = line["lineNum"]; + delete line["lineNum"]; + } } } } @@ -364,12 +384,16 @@ export class Project implements ProjectInfo { const info = await Project.getInfo(id, seed.addr); id = isRadicleId(id) ? id : info.id; - // Older versions of http-api don't include the ID. - if (!info.id) info.id = id; + let peers: Peer[] = []; - const peers: Peer[] = info.delegates - ? await Project.getRemotes(id, seed.addr) - : []; + if (window.HEARTWOOD) { + peers = await Project.getRemotes(id, seed.addr); + } else { + // Older versions of http-api don't include the ID. + if (!info.id) info.id = id; + + peers = info.delegates ? await Project.getRemotes(id, seed.addr) : []; + } let remote: Remote = { heads: info.head ? { [info.defaultBranch]: info.head } : {}, diff --git a/src/lib/registrar.ts b/src/lib/registrar.ts index bec7264de..430478eea 100644 --- a/src/lib/registrar.ts +++ b/src/lib/registrar.ts @@ -90,18 +90,8 @@ export async function getRegistration( getText(resolver, "com.github"), ]); - const [ - address, - avatar, - url, - id, - seedId, - seedHost, - seedGit, - seedApi, - twitter, - github, - ] = meta.filter(isFulfilled).map(r => (r.value ? r.value : undefined)); + const [address, avatar, url, id, seedId, seedHost, seedApi, twitter, github] = + meta.filter(isFulfilled).map(r => (r.value ? r.value : undefined)); const profile: EnsProfile = { name, @@ -119,7 +109,6 @@ export async function getRegistration( profile.seed = new Seed({ host: seedHost, id: seedId, - git: seedGit, addr: seedApi, }); } catch (e: any) { @@ -157,10 +146,9 @@ export async function getSeed( return null; } - const [id, host, git, api] = await Promise.all([ + const [id, host, api] = await Promise.all([ getText(resolver, "eth.radicle.seed.id"), getText(resolver, "eth.radicle.seed.host"), - getText(resolver, "eth.radicle.seed.git"), getText(resolver, "eth.radicle.seed.api"), ]); @@ -170,7 +158,7 @@ export async function getSeed( } try { - return new Seed({ host, id, git, addr: api }); + return new Seed({ host, id, addr: api }); } catch (e: any) { console.debug(e, host, id); return new InvalidSeed(id, host); diff --git a/src/lib/seed.ts b/src/lib/seed.ts index 723e55ee5..306877ab8 100644 --- a/src/lib/seed.ts +++ b/src/lib/seed.ts @@ -23,15 +23,16 @@ export class InvalidSeed { } } -export const defaultSeedPort = 8777; +export const defaultSeedPort = window.HEARTWOOD ? 8080 : 8777; export const defaultNodePort = 8776; +// TODO: Remove this after we have migrated to Heartwood. export const defaultGitPort = 443; export class Seed { valid = true as const; addr: { host: string; port: number | null }; - git: { host: string; port: number | null }; + git: { host: string; port: number | null }; // TODO: Remove this after we have migrated to Heartwood. node: { host: string; id: string; port: number }; version?: string; @@ -40,17 +41,21 @@ export class Seed { constructor(seed: { host: string; id: string; - git?: string | null; + git?: string | null; // TODO: Remove this after we have migrated to Heartwood. addr?: string | null; version?: string | null; }) { assert(isDomain(seed.host), `invalid seed host: ${seed.host}`); - assert(/^[a-z0-9]+$/.test(seed.id), `invalid seed id ${seed.id}`); + if (window.HEARTWOOD) { + assert(/^[a-zA-Z0-9]+$/.test(seed.id), `invalid seed id ${seed.id}`); + } else { + assert(/^[a-z0-9]+$/.test(seed.id), `invalid seed id ${seed.id}`); + } let _seed = null; - let _git = null; + let _git = null; // TODO: Remove this after we have migrated to Heartwood. let _seedPort: number | null = defaultSeedPort; - let _gitPort: number | null = defaultGitPort; + let _gitPort: number | null = defaultGitPort; // TODO: Remove this after we have migrated to Heartwood. if (seed.addr) { try { @@ -73,15 +78,17 @@ export class Seed { assert(isDomain(_seed), `invalid seed host ${_seed}`); } - if (seed.git) { - try { - const url = new URL(seed.git); - _git = url.hostname; - _gitPort = url.port ? Number(url.port) : null; - } catch { - _git = seed.git; + if (window.HEARTWOOD) { + if (seed.git) { + try { + const url = new URL(seed.git); + _git = url.hostname; + _gitPort = url.port ? Number(url.port) : null; + } catch { + _git = seed.git; + } + assert(isDomain(_git), `invalid seed git host ${_git}`); } - assert(isDomain(_git), `invalid seed git host ${_git}`); } this.emoji = getSeedEmoji(seed.host); @@ -89,10 +96,10 @@ export class Seed { // The `_seed` being more specific takes // precedence over the `host`, if available. _seed = _seed ?? seed.host; - _git = _git ?? seed.host; + _git = _git ?? seed.host; // TODO: Remove this after we have migrated to Heartwood. this.addr = { host: _seed, port: _seedPort }; - this.git = { host: _git, port: _gitPort }; + this.git = { host: _git, port: _gitPort }; // TODO: Remove this after we have migrated to Heartwood. this.node = { host: seed.host, id: seed.id, port: defaultNodePort }; if (seed.version) { @@ -121,10 +128,14 @@ export class Seed { ? await proj.Project.getDelegateProjects(id, this.addr, { perPage }) : await proj.Project.getProjects(this.addr, { perPage }); - return result.map((project: proj.ProjectInfo) => ({ - ...project, - id: project.id, - })); + if (window.HEARTWOOD) { + return result; + } else { + return result.map((project: proj.ProjectInfo) => ({ + ...project, + id: project.id, + })); + } } async getStats(): Promise<{ @@ -135,7 +146,11 @@ export class Seed { } static async getNode(host: Host): Promise<{ id: string }> { - return new Request("/peer", host).get(); + if (window.HEARTWOOD) { + return new Request("/node", host).get(); + } else { + return new Request("/peer", host).get(); + } } static async getInfo(host: Host): Promise<{ version: string }> { diff --git a/src/lib/utils.ts b/src/lib/utils.ts index fbdf2f09c..ffc9d62c7 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -105,7 +105,11 @@ export function formatSeedId(id: string): string { export function formatRadicleId(id: string): string { assert(isRadicleId(id)); - return id.substring(0, 14) + "…" + id.substring(id.length - 6, id.length); + if (window.HEARTWOOD) { + return id.substring(0, 10) + "…" + id.substring(id.length - 6, id.length); + } else { + return id.substring(0, 14) + "…" + id.substring(id.length - 6, id.length); + } } export function formatBalance(n: BigNumber, decimals?: number): string { @@ -245,7 +249,11 @@ export const formatTimestamp = ( // Check whether the input is a Radicle ID. export function isRadicleId(input: string): boolean { - return /^rad:[a-z]+:[a-zA-Z0-9]+$/.test(input); + if (window.HEARTWOOD) { + return /^rad:[a-zA-Z0-9]+$/.test(input); + } else { + return /^rad:[a-z]+:[a-zA-Z0-9]+$/.test(input); + } } // Check whether the input is a Radicle Peer ID. @@ -295,7 +303,11 @@ export function formatName(input: string, wallet: Wallet): string { // Parse a Radicle Id. export function parseRadicleId(id: string): string { - return id.replace(/^rad:[a-z]+:/, ""); + if (window.HEARTWOOD) { + return id.replace(/^rad:/, ""); + } else { + return id.replace(/^rad:[a-z]+:/, ""); + } } // Get amount of days passed between two dates without including the end date diff --git a/src/views/projects/Blob.svelte b/src/views/projects/Blob.svelte index f460afab0..79a559024 100644 --- a/src/views/projects/Blob.svelte +++ b/src/views/projects/Blob.svelte @@ -18,7 +18,7 @@ export let line: string | undefined = undefined; const fileExtension = blob.path.split(".").pop() ?? ""; - const lastCommit = blob.info.lastCommit; + const lastCommit = window.HEARTWOOD ? blob.lastCommit : blob.info.lastCommit; const parentDir = blob.path .match(/^.*\/|/) ?.values() @@ -213,7 +213,7 @@ {parentDir} ​ - {blob.info.name} + {window.HEARTWOOD ? blob.name : blob.info.name}
{#if isMarkdown} diff --git a/src/views/projects/Commit.svelte b/src/views/projects/Commit.svelte index 870b04802..21bfb4d31 100644 --- a/src/views/projects/Commit.svelte +++ b/src/views/projects/Commit.svelte @@ -73,5 +73,8 @@ {/if}
- + diff --git a/src/views/projects/Commit/CommitTeaser.svelte b/src/views/projects/Commit/CommitTeaser.svelte index 6ef01ae51..47be7cd24 100644 --- a/src/views/projects/Commit/CommitTeaser.svelte +++ b/src/views/projects/Commit/CommitTeaser.svelte @@ -94,7 +94,7 @@
- {#if commit.context.committer} + {#if !window.HEARTWOOD && commit.context.committer}
diff --git a/src/views/projects/Header.svelte b/src/views/projects/Header.svelte index 3660ad348..4888e5034 100644 --- a/src/views/projects/Header.svelte +++ b/src/views/projects/Header.svelte @@ -98,9 +98,12 @@ {revision} on:branchChanged={event => updateRevision(event.detail)} /> - {#if seed.git.host} + {#if window.HEARTWOOD && seed.addr.host} + + {:else if seed.git.host} {/if} + {#if seed.addr.host}
- + {#if !window.HEARTWOOD} + + {/if} + {#each issue.discussion as comment} - {#if comment.replies} -
- {#each comment.replies as reply} - - {/each} -
+ {#if !window.HEARTWOOD} + {#if comment.replies} +
+ {#each comment.replies as reply} + + {/each} +
+ {/if} {/if} {/each}
diff --git a/src/views/projects/Patch.svelte b/src/views/projects/Patch.svelte index 7b960916d..86c434a6a 100644 --- a/src/views/projects/Patch.svelte +++ b/src/views/projects/Patch.svelte @@ -138,8 +138,10 @@
{:else if activeTab === PatchTab.Diff && revision.changeset} onBrowse(e, revision.oid)} /> {:else if activeTab === PatchTab.Diff} diff --git a/src/views/projects/Patch/PatchTimeline.svelte b/src/views/projects/Patch/PatchTimeline.svelte index eaca11ec1..04dd8aa0e 100644 --- a/src/views/projects/Patch/PatchTimeline.svelte +++ b/src/views/projects/Patch/PatchTimeline.svelte @@ -66,11 +66,13 @@ {:else if element.type === TimelineType.Thread}
-
- {#each element.inner.replies as comment} - - {/each} -
+ {#if !window.HEARTWOOD} +
+ {#each element.inner.replies as comment} + + {/each} +
+ {/if}
{/if} {/each} diff --git a/src/views/projects/Tree.svelte b/src/views/projects/Tree.svelte index 1f86d6c42..eb30a07ce 100644 --- a/src/views/projects/Tree.svelte +++ b/src/views/projects/Tree.svelte @@ -3,8 +3,6 @@ import { createEventDispatcher } from "svelte"; - import { ObjectType } from "@app/lib/project"; - import File from "./Tree/File.svelte"; import Folder from "./Tree/Folder.svelte"; @@ -20,11 +18,11 @@ {#each tree.entries as entry (entry.path)} - {#if entry.info.objectType === ObjectType.Tree} + {#if window.HEARTWOOD ? entry.kind === "tree" : entry.info.objectType === "TREE"} @@ -32,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 e13889437..ca5aa72ef 100644 --- a/src/views/projects/Tree/Folder.svelte +++ b/src/views/projects/Tree/Folder.svelte @@ -2,7 +2,6 @@ import type { MaybeTree } from "@app/lib/project"; import Loading from "@app/components/Loading.svelte"; - import { ObjectType } from "@app/lib/project"; import { createEventDispatcher } from "svelte"; import File from "./File.svelte"; @@ -75,10 +74,10 @@ {:then tree} {#if tree} {#each tree.entries as entry (entry.path)} - {#if entry.info.objectType === ObjectType.Tree} + {#if window.HEARTWOOD ? entry.kind === "tree" : entry.info.objectType === "TREE"} { onSelectFile({ detail: entry.path }); }} /> diff --git a/src/views/registrations/View.svelte b/src/views/registrations/View.svelte index a8ab70635..3134fe663 100644 --- a/src/views/registrations/View.svelte +++ b/src/views/registrations/View.svelte @@ -124,7 +124,9 @@ name: "id", label: "Radicle", validate: "identity", - placeholder: "Radicle ID, eg. rad:git:hnrkqdpm9ub19oc8d…", + placeholder: window.HEARTWOOD + ? "Radicle ID, eg. rad:zKtT7DmF9H34KkvcKj…" + : "Radicle ID, eg. rad:git:hnrkqdpm9ub19oc8d…", description: "The local radicle identity associated with this name.", value: r.profile.id ?? "", editable: true, diff --git a/tests/e2e/project.spec.ts b/tests/e2e/project.spec.ts index 99b79606e..43c5acc9b 100644 --- a/tests/e2e/project.spec.ts +++ b/tests/e2e/project.spec.ts @@ -251,6 +251,10 @@ test("clone modal", async ({ page }) => { }); test("peer and branch switching", async ({ page }) => { + if (process.env.HEARTWOOD) { + test.skip(); + } + await page.goto(projectFixtureUrl); // Alice's peer. @@ -335,6 +339,10 @@ test("peer and branch switching", async ({ page }) => { }); test("only one modal can be open at a time", async ({ page }) => { + if (process.env.HEARTWOOD) { + test.skip(); + } + await page.goto(projectFixtureUrl); await page.getByTitle("Change peer").click(); @@ -366,6 +374,10 @@ test("only one modal can be open at a time", async ({ page }) => { }); test.describe("browser error handling", () => { + if (process.env.HEARTWOOD) { + test.skip(); + } + test("error appears when folder can't be loaded", async ({ page }) => { await page.route( `**/v1/projects/${ridPrefix}${rid}/tree/${aliceMainHead}/markdown/`, diff --git a/tests/e2e/project/commit.spec.ts b/tests/e2e/project/commit.spec.ts index aa36f06c7..07c571310 100644 --- a/tests/e2e/project/commit.spec.ts +++ b/tests/e2e/project/commit.spec.ts @@ -8,6 +8,10 @@ import { const modifiedFileFixture = `${projectFixtureUrl}/remotes/${bobRemote}/commits/2b32f6fe50090ebdb4cd7441e943330da3e6ff04`; test("navigation from commit list", async ({ page }) => { + if (process.env.HEARTWOOD) { + test.skip(); + } + await page.goto(projectFixtureUrl); await page.getByTitle("Change peer").click(); await page.locator("text=bob hyyzz9").click(); @@ -18,6 +22,10 @@ test("navigation from commit list", async ({ page }) => { }); test("relative timestamps", async ({ page }) => { + if (process.env.HEARTWOOD) { + test.skip(); + } + await page.addInitScript(() => { window.initializeTestStubs = () => { window.e2eTestStubs.FakeTimers.install({ @@ -34,6 +42,10 @@ test("relative timestamps", async ({ page }) => { }); test("modified file", async ({ page }) => { + if (process.env.HEARTWOOD) { + test.skip(); + } + await page.goto(modifiedFileFixture); // Commit header. @@ -59,6 +71,10 @@ test("modified file", async ({ page }) => { }); test("created file", async ({ page }) => { + if (process.env.HEARTWOOD) { + test.skip(); + } + await page.goto( `${projectFixtureUrl}/remotes/${bobRemote}/commits/d6318f7f3d9c15b8ac6dd52267c53220d00f0982`, ); @@ -69,6 +85,10 @@ test("created file", async ({ page }) => { }); test("deleted file", async ({ page }) => { + if (process.env.HEARTWOOD) { + test.skip(); + } + await page.goto( `${projectFixtureUrl}/remotes/${bobRemote}/commits/cd13c2d9a8a930d64a82b6134b44d1b872e33662`, ); diff --git a/tests/e2e/project/commits.spec.ts b/tests/e2e/project/commits.spec.ts index 18956b343..74e45818a 100644 --- a/tests/e2e/project/commits.spec.ts +++ b/tests/e2e/project/commits.spec.ts @@ -6,6 +6,10 @@ import { } from "@tests/support/fixtures.js"; test("peer and branch switching", async ({ page }) => { + if (process.env.HEARTWOOD) { + test.skip(); + } + await page.goto(projectFixtureUrl); await page.locator('role=button[name="Commit count"]').click(); @@ -83,6 +87,10 @@ test("peer and branch switching", async ({ page }) => { }); test("verified badge", async ({ page }) => { + if (process.env.HEARTWOOD) { + test.skip(); + } + await page.goto(projectFixtureUrl); await page.locator('role=button[name="Commit count"]').click(); @@ -101,6 +109,10 @@ test("verified badge", async ({ page }) => { }); test("relative timestamps", async ({ page }) => { + if (process.env.HEARTWOOD) { + test.skip(); + } + await page.addInitScript(() => { window.initializeTestStubs = () => { window.e2eTestStubs.FakeTimers.install({ diff --git a/tests/fixtures/seeds/palm-heartwood.tar.bz2 b/tests/fixtures/seeds/palm-heartwood.tar.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..cb2ccada68c12d8852fab4daded3a04274469895 GIT binary patch literal 15745 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 literal 0 HcmV?d00001 diff --git a/tests/support/fixtures.ts b/tests/support/fixtures.ts index addf60083..ffc6453a5 100644 --- a/tests/support/fixtures.ts +++ b/tests/support/fixtures.ts @@ -160,7 +160,11 @@ function log(text: string, label: string, outputLog: Stream.Writable) { } } -export function appConfigWithFixture() { +export const appConfigWithFixture = process.env.HEARTWOOD + ? configFixtureHeartwood + : configFixture; + +export function configFixture() { window.APP_CONFIG = { walletConnect: { bridge: "https://radicle.bridge.walletconnect.org", @@ -181,15 +185,41 @@ export function appConfigWithFixture() { }; } +export function configFixtureHeartwood() { + window.APP_CONFIG = { + walletConnect: { + bridge: "https://radicle.bridge.walletconnect.org", + }, + reactions: [], + seeds: { + pinned: [{ host: "0.0.0.0", emoji: "🚀" }], + }, + projects: { + pinned: [ + { + name: "source-browsing", + id: "rad:zKtT7DmF9H34KkvcKj9PHW19WzjT", + seed: "0.0.0.0", + }, + ], + }, + }; +} + export const aliceMainHead = "fcc929424b82984b7cbff9c01d2e20d9b1249842"; -export const aliceRemote = - "hybg18bc4cu8z9xtj44skxperfdpxpp1wp8zygyzti5kfiggdizfxy"; +export const aliceRemote = process.env.HEARTWOOD + ? "z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi" + : "hybg18bc4cu8z9xtj44skxperfdpxpp1wp8zygyzti5kfiggdizfxy"; + export const bobRemote = "hyyzz9w4ffg16zftjki3enajm4mkqkayb5ch1p6ns3f83np1hqkrp6"; -export const rid = "hnrkdi8be7n4hhqoz9rpzrgd68u9dr3zsxgmy"; -export const ridPrefix = "rad:git:"; +export const rid = process.env.HEARTWOOD + ? "zKtT7DmF9H34KkvcKj9PHW19WzjT" + : "hnrkdi8be7n4hhqoz9rpzrgd68u9dr3zsxgmy"; +export const ridPrefix = process.env.HEARTWOOD ? "rad:" : "rad:git:"; export const projectFixtureUrl = `/seeds/0.0.0.0/${ridPrefix}${rid}`; -export const seedPort = 8777; -export const seedVersion = "0.2.0"; -export const seedRemote = - "hybuytx44z9cfsm5739wecia9j4b7expgc15qkazph59szp57m4d3o"; +export const seedPort = process.env.HEARTWOOD ? 8080 : "8777"; +export const seedVersion = process.env.HEARTWOOD ? "0.1.0" : "0.2.0"; +export const seedRemote = process.env.HEARTWOOD + ? "z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi" + : "hybuytx44z9cfsm5739wecia9j4b7expgc15qkazph59szp57m4d3o"; diff --git a/tests/support/globalSetup.ts b/tests/support/globalSetup.ts index 617dff674..60cca10ee 100644 --- a/tests/support/globalSetup.ts +++ b/tests/support/globalSetup.ts @@ -9,24 +9,30 @@ export default async function globalSetup(_config: FullConfig): Promise { // Assert that the test http-api is running. If it is not running, throw an // error that explains how to run it. async function assertHttpApiRunning(): Promise { - const palmTestFixtureSeedId = seedRemote; - const notRunningMessage = "The http-api server with test fixtures needs to be running.\n" + - "👉 You can start it with `./scripts/run-http-api-with-fixtures`\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"); let peerId: string | undefined = undefined; try { - const response = await fetch(`http://0.0.0.0:${seedPort}`); - const data = await response.json(); - peerId = data.peer.id; + 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; + } } catch (err) { console.error(err); throw new Error(notRunningMessage); } - if (peerId !== palmTestFixtureSeedId) { + if (peerId !== 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/router.test.ts b/tests/unit/router.test.ts index 8f4acf3f3..a6bc3d9b6 100644 --- a/tests/unit/router.test.ts +++ b/tests/unit/router.test.ts @@ -101,11 +101,11 @@ describe("routeToPath", () => { params: { view: { resource: "tree" }, seed: "willow.radicle.garden", - id: "rad:git:hnrkmg77m8tfzj4gi4pa4mbhgysfgzwntjpao", + id: "rad:zKtT7DmF9H34KkvcKj9PHW19WzjT", }, }, output: - "/seeds/willow.radicle.garden/rad:git:hnrkmg77m8tfzj4gi4pa4mbhgysfgzwntjpao/tree", + "/seeds/willow.radicle.garden/rad:zKtT7DmF9H34KkvcKj9PHW19WzjT/tree", description: "Seed Project Route", }, ])("$description", (route: any) => { @@ -219,8 +219,7 @@ describe("pathToRoute", () => { description: "registrations Submit Route", }, { - input: - "/seeds/willow.radicle.garden/rad:git:hnrkmg77m8tfzj4gi4pa4mbhgysfgzwntjpao", + input: "/seeds/willow.radicle.garden/rad:zKtT7DmF9H34KkvcKj9PHW19WzjT", output: { resource: "projects", params: { @@ -228,7 +227,7 @@ describe("pathToRoute", () => { seed: "willow.radicle.garden", profile: undefined, peer: undefined, - id: "rad:git:hnrkmg77m8tfzj4gi4pa4mbhgysfgzwntjpao", + id: "rad:zKtT7DmF9H34KkvcKj9PHW19WzjT", }, }, description: "Seed Project Route", diff --git a/tests/unit/utils.test.ts b/tests/unit/utils.test.ts index 65215fee5..490697355 100644 --- a/tests/unit/utils.test.ts +++ b/tests/unit/utils.test.ts @@ -37,9 +37,15 @@ describe("Format functions", () => { }); test("formatRadicleId", () => { - expect( - utils.formatRadicleId("rad:git:hnrkemobagsicpf9sr95o3g551otspcd84c9o"), - ).toEqual("rad:git:hnrkem…d84c9o"); + 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", () => { @@ -117,7 +123,9 @@ describe("String Assertions", () => { }); test.each([ - { id: "rad:git:hnrkemobagsicpf9sr95o3g551otspcd84c9o", expected: true }, + process.env.HEARTWOOD + ? { id: "rad:zKtT7DmF9H34KkvcKj9PHW19WzjT", expected: true } + : { id: "rad:git:hnrkemobagsicpf9sr95o3g551otspcd84c9o", expected: true }, { id: "0x1234567890123456789012345678901234567890", expected: false }, ])("isRadicleId $id => $expected", ({ id, expected }) => { expect(utils.isRadicleId(id)).toEqual(expected); diff --git a/tests/visual/landingPage.spec.ts b/tests/visual/landingPage.spec.ts index 527e45ba3..b0846fe12 100644 --- a/tests/visual/landingPage.spec.ts +++ b/tests/visual/landingPage.spec.ts @@ -5,6 +5,16 @@ test.use({ }); test("landing page", async ({ page }) => { + await page.addInitScript(() => { + window.initializeTestStubs = () => { + window.e2eTestStubs.FakeTimers.install({ + now: new Date("November 24 2022 12:00:00").valueOf(), + shouldClearNativeTimers: true, + shouldAdvanceTime: false, + }); + }; + }); + await page.addInitScript(appConfigWithFixture); await page.goto("/", { waitUntil: "networkidle" }); await expect(page).toHaveScreenshot(); diff --git a/tests/visual/seed.spec.ts b/tests/visual/seed.spec.ts index 7fa0f49bf..fcfb9218c 100644 --- a/tests/visual/seed.spec.ts +++ b/tests/visual/seed.spec.ts @@ -1,6 +1,16 @@ import { test, expect } from "@tests/support/fixtures.js"; test("seed page", async ({ page }) => { + await page.addInitScript(() => { + window.initializeTestStubs = () => { + window.e2eTestStubs.FakeTimers.install({ + now: new Date("November 24 2022 12:00:00").valueOf(), + shouldClearNativeTimers: true, + shouldAdvanceTime: false, + }); + }; + }); + await page.goto("/seeds/radicle.local", { waitUntil: "networkidle" }); await expect(page).toHaveScreenshot(); }); diff --git a/vite.config.ts b/vite.config.ts index 389b123a7..7165b2151 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -12,6 +12,7 @@ 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