Skip to content

Commit

Permalink
web-wallet: Add possibility to serve the web wallet from a sub folder
Browse files Browse the repository at this point in the history
Resolves #1362
  • Loading branch information
ascartabelli committed Feb 20, 2024
1 parent 0cc9697 commit 1ec9f93
Show file tree
Hide file tree
Showing 53 changed files with 528 additions and 103 deletions.
2 changes: 2 additions & 0 deletions web-wallet/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Add wallet restore flow tests [#1416]
- Add missing login flow tests [#1423]
- Add possibility to serve the web wallet from a sub folder [#1362]

### Changed

Expand Down Expand Up @@ -95,6 +96,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#1423]: https://github.com/dusk-network/rusk/issues/1423
[#1391]: https://github.com/dusk-network/rusk/issues/1391
[#1417]: https://github.com/dusk-network/rusk/issues/1417
[#1362]: https://github.com/dusk-network/rusk/issues/1362

<!-- VERSIONS -->
[Unreleased]: https://github.com/dusk-network/rusk/tree/master/web-wallet
Expand Down
4 changes: 3 additions & 1 deletion web-wallet/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ The application defines these variables by reading a local `.env` file containin
N.B. the current `0.1.2` version of the library has no option to pick the network and uses the `LOCAL_NODE` only. The current testnet address is set in that variable in the example below:

```
# can be empty string, must start with a slash otherwise, must not end with a slash
VITE_BASE_PATH=""
VITE_CONTRACT_STAKE_DISABLED=false
VITE_CONTRACT_TRANSFER_DISABLED=false
VITE_CURRENT_NODE=${VITE_LOCAL_NODE}
Expand Down Expand Up @@ -67,4 +69,4 @@ To run a local node different steps are needed, so please read the [related sect

## Running a local Rusk node

To run a local node, follow the instructions outlined in the [Rusk's readme](https://github.com/dusk-network/rusk).
To run a local node, follow the instructions outlined in the [Rusk's readme](https://github.com/dusk-network/rusk).
17 changes: 17 additions & 0 deletions web-wallet/src/lib/components/AppAnchor/AppAnchor.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<svelte:options immutable={true}/>

<script>
import { Anchor } from "$lib/dusk/components";
import { addBasePath } from "$lib/navigation";
/** @type {string} */
export let href;
</script>

<Anchor
{...$$restProps}
href={addBasePath(href)}
on:click
>
<slot/>
</Anchor>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<svelte:options immutable={true}/>

<script>
import { AnchorButton } from "$lib/dusk/components";
import { addBasePath } from "$lib/navigation";
/** @type {string} */
export let href;
</script>

<AnchorButton
{...$$restProps}
href={addBasePath(href)}
on:click
/>
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
<script>
import {
AnchorButton,
Button,
Card
} from "$lib/dusk/components";
import { Button, Card } from "$lib/dusk/components";
import { AppAnchorButton } from "$lib/components";
import { mdiAlertOutline } from "@mdi/js";
/** @type {boolean} */
Expand All @@ -18,7 +15,7 @@
you will need to wait for the wallet to sync.
</p>
<div class="flex gap-1 w-100">
<AnchorButton
<AppAnchorButton
className="flex-1"
href="/setup"
text="Back"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

<script>
import {
AnchorButton,
ErrorDetails,
Icon,
Throbber
} from "$lib/dusk/components";
import { mdiCheckDecagramOutline, mdiCloseThick } from "@mdi/js";
import { makeClassName } from "$lib/dusk/string";
import { AppAnchorButton } from "$lib/components";
/** @type {string|undefined} */
export let className = undefined;
Expand Down Expand Up @@ -49,7 +49,7 @@
/>
<span>{successMessage}</span>
<slot name="success-content" {result}/>
<AnchorButton
<AppAnchorButton
href="/dashboard"
on:click={handleGoHomeClick}
variant="tertiary"
Expand All @@ -65,7 +65,7 @@
summary={errorMessage}
/>
<slot name="error-content"/>
<AnchorButton
<AppAnchorButton
href="/dashboard"
on:click={handleGoHomeClick}
variant="tertiary"
Expand Down
4 changes: 2 additions & 2 deletions web-wallet/src/lib/components/Send/Send.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import { duskToLux, luxToDusk } from "$lib/dusk/currency";
import { logo } from "$lib/dusk/icons";
import {
AnchorButton,
Badge,
Button,
Icon,
Expand All @@ -18,6 +17,7 @@
WizardStep
} from "$lib/dusk/components";
import {
AppAnchorButton,
ContractStatusesList,
GasFee,
GasSettings,
Expand Down Expand Up @@ -236,7 +236,7 @@
>
<svelte:fragment slot="success-content" let:result={hash}>
{#if hash}
<AnchorButton
<AppAnchorButton
href={`https://explorer.dusk.network/transactions/transaction?id=${hash}`}
on:click={resetOperation}
text="VIEW ON BLOCK EXPLORER"
Expand Down
10 changes: 5 additions & 5 deletions web-wallet/src/lib/components/Stake/Stake.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
import {
Agreement,
Anchor,
AnchorButton,
Badge,
Button,
Card,
Expand All @@ -23,6 +21,8 @@
} from "$lib/dusk/components";
import {
AppAnchor,
AppAnchorButton,
ContractStatusesList,
GasFee,
GasSettings,
Expand Down Expand Up @@ -162,11 +162,11 @@
iconPath={mdiAlertOutline}
heading="Only stake if you have a node set up!">
<p class="staking-warning">
I understand that I have set up a node properly, as described <Anchor
I understand that I have set up a node properly, as described <AppAnchor
class="staking-warning__step-node-setup-link"
rel="noopener noreferrer"
target="_blank"
href="https://docs.dusk.network/getting-started/node-setup/overview">HERE</Anchor>, and that I will lose funds if I have not done so correctly.</p>
href="https://docs.dusk.network/getting-started/node-setup/overview">HERE</AppAnchor>, and that I will lose funds if I have not done so correctly.</p>

<Agreement
className="staking-warning__agreement"
Expand Down Expand Up @@ -294,7 +294,7 @@
>
<svelte:fragment slot="success-content" let:result={hash}>
{#if hash}
<AnchorButton
<AppAnchorButton
href={`https://explorer.dusk.network/transactions/transaction?id=${hash}`}
on:click={resetOperation}
text="VIEW ON BLOCK EXPLORER"
Expand Down
14 changes: 7 additions & 7 deletions web-wallet/src/lib/components/Transactions/Transactions.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
import { fade } from "svelte/transition";
import { logo } from "$lib/dusk/icons";
import {
Anchor,
AnchorButton,
Badge,
ErrorDetails,
Icon,
Expand All @@ -16,6 +14,9 @@
import { calculateAdaptiveCharCount, middleEllipsis } from "$lib/dusk/string";
import { sortByHeightDesc } from "$lib/transactions";
import AppAnchor from "../AppAnchor/AppAnchor.svelte";
import AppAnchorButton from "../AppAnchorButton/AppAnchorButton.svelte";
/** @type {String} */
export let language;
Expand Down Expand Up @@ -54,14 +55,14 @@
<header class="transactions__header">
<h3 class="h4">Transactions</h3>
{#if limit}
<AnchorButton
<AppAnchorButton
className="transactions__footer-button"
href="/dashboard/transactions"
text="View all transactions"
variant="tertiary"
/>
{:else}
<AnchorButton
<AppAnchorButton
className="transactions__footer-button"
href="/dashboard"
text="Back"
Expand All @@ -81,7 +82,7 @@
<dt class="transactions-list__term">Hash</dt>
<dd class="transactions-list__datum transactions-list__datum--hash">
<samp>
<Anchor
<AppAnchor
href="https://explorer.dusk.network/transactions/transaction?id={transaction.id}"
rel="noopener noreferrer"
target="_blank"
Expand All @@ -90,7 +91,7 @@
transaction.id,
calculateAdaptiveCharCount(screenWidth, 320, 640, 5, 20)
)}
</Anchor>
</AppAnchor>
</samp>
</dd>
{#if transaction.tx_type}
Expand Down Expand Up @@ -140,7 +141,6 @@
{:catch e}
<ErrorDetails summary="Error getting transactions" error={e}/>
{/await}

</article>

<style lang="postcss">
Expand Down
83 changes: 83 additions & 0 deletions web-wallet/src/lib/components/__tests__/AppAnchor.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import {
afterEach,
describe,
expect,
it,
vi
} from "vitest";
import {
cleanup,
fireEvent,
render
} from "@testing-library/svelte";
import { base } from "$app/paths";

import { renderWithSimpleContent } from "$lib/dusk/test-helpers";

import { AppAnchor } from "..";

describe("AppAnchor", () => {
const baseProps = {
className: "foo bar",
href: "/setup",
id: "some-id"
};
const baseOptions = {
props: baseProps,
target: document.body
};

afterEach(cleanup);

it("should render an `Anchor` with the base path prepended to the `href` attribute, if the `href` represents an absolute URL", () => {
const renderA = renderWithSimpleContent(AppAnchor, baseOptions);
const anchorA = renderA.getByRole("link");

expect(renderA.container.firstChild).toMatchSnapshot();
expect(anchorA).toHaveAttribute("href", `${base}${baseProps.href}`);
expect(anchorA).toHaveClass("foo bar");
expect(anchorA).toHaveAttribute("id", baseProps.id);

cleanup();

const renderB = renderWithSimpleContent(
AppAnchor,
{ ...baseOptions, props: { ...baseProps, href: "/" } }
);
const anchorB = renderB.getByRole("link");

expect(anchorB).toHaveAttribute("href", `${base}/`);
expect(anchorB).toHaveClass("foo bar");
expect(anchorB).toHaveAttribute("id", baseProps.id);
});

it("should leave the `Anchor` as it is if the `href` points to a relative path", () => {
const { getByRole } = renderWithSimpleContent(
AppAnchor,
{ ...baseOptions, props: { ...baseProps, href: "foo/bar" } }
);

expect(getByRole("link")).toHaveAttribute("href", "foo/bar");
});

it("should leave the `Anchor` as it is if the `href` points to an external URL", () => {
const href = "http://example.com";
const { getByRole } = renderWithSimpleContent(
AppAnchor,
{ ...baseOptions, props: { ...baseProps, href } }
);

expect(getByRole("link")).toHaveAttribute("href", href);
});

it("should forward the `onclick` event to the `Anchor`", async () => {
const handler = vi.fn();
const { component, getByRole } = render(AppAnchor, { ...baseProps, href: "#" });

component.$on("click", handler);

await fireEvent.click(getByRole("link"));

expect(handler).toHaveBeenCalledTimes(1);
});
});
67 changes: 67 additions & 0 deletions web-wallet/src/lib/components/__tests__/AppAnchorButton.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import {
afterEach,
describe,
expect,
it,
vi
} from "vitest";
import {
cleanup,
fireEvent,
render
} from "@testing-library/svelte";
import { base } from "$app/paths";

import { AppAnchorButton } from "..";

describe("AppAnchorButton", () => {
const baseProps = {
className: "foo bar",
href: "/setup",
id: "some-id"
};

afterEach(cleanup);

it("should render an `AnchorButton` with the base path prepended to the `href` attribute, if the `href` represents an absolute URL", () => {
const { container, getByRole, rerender } = render(AppAnchorButton, baseProps);
const anchorA = getByRole("link");

expect(container.firstChild).toMatchSnapshot();
expect(anchorA).toHaveAttribute("href", `${base}${baseProps.href}`);
expect(anchorA).toHaveClass("foo bar");
expect(anchorA).toHaveAttribute("id", baseProps.id);

rerender({ ...baseProps, href: "/" });

const anchorB = getByRole("link");

expect(anchorB).toHaveAttribute("href", `${base}/`);
expect(anchorB).toHaveClass("foo bar");
expect(anchorB).toHaveAttribute("id", baseProps.id);
});

it("should leave the `AnchorButton` as it is if the `href` points to a relative path", () => {
const { getByRole } = render(AppAnchorButton, { ...baseProps, href: "foo/bar" });

expect(getByRole("link")).toHaveAttribute("href", "foo/bar");
});

it("should leave the `AnchorButton` as it is if the `href` points to an external URL", () => {
const href = "http://example.com";
const { getByRole } = render(AppAnchorButton, { ...baseProps, href });

expect(getByRole("link")).toHaveAttribute("href", href);
});

it("should forward the `onclick` event to the `AnchorButton`", async () => {
const handler = vi.fn();
const { component, getByRole } = render(AppAnchorButton, { ...baseProps, href: "#" });

component.$on("click", handler);

await fireEvent.click(getByRole("link"));

expect(handler).toHaveBeenCalledTimes(1);
});
});
Loading

0 comments on commit 1ec9f93

Please sign in to comment.