Skip to content

Commit

Permalink
Merge branch 'main' into 2024-12-18-dotrain-yaml-order
Browse files Browse the repository at this point in the history
  • Loading branch information
hardyjosh authored Dec 27, 2024
2 parents 3df44b5 + e652f55 commit acf4b72
Show file tree
Hide file tree
Showing 14 changed files with 183 additions and 130 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/tauri-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ jobs:
- run: nix develop .#tauri-shell --command ob-tauri-before-release
working-directory: ./tauri-app
env:
WALLETCONNECT_PROJECT_ID: ${{ secrets.WALLETCONNECT_PROJECT_ID }}
VITE_WALLETCONNECT_PROJECT_ID: ${{ secrets.WALLETCONNECT_PROJECT_ID }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
SENTRY_ORG: rainlang
Expand Down
1 change: 0 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
"svelte.enable-ts-plugin": true,

"rust-analyzer.linkedProjects": ["./Cargo.toml", "tauri-app/src-tauri/Cargo.toml"],

"[rust]": {
"editor.defaultFormatter": "rust-lang.rust-analyzer",
"editor.formatOnSave": true,
Expand Down
2 changes: 1 addition & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@
sentry-cli releases set-commits --auto ''${COMMIT_SHA}
# Overwrite env variables with release values
echo WALLETCONNECT_PROJECT_ID=''${WALLETCONNECT_PROJECT_ID} >> .env
echo VITE_WALLETCONNECT_PROJECT_ID=''${WALLETCONNECT_PROJECT_ID} >> .env
echo SENTRY_AUTH_TOKEN=''${SENTRY_AUTH_TOKEN} >> .env
echo SENTRY_ORG=''${SENTRY_ORG} >> .env
echo SENTRY_PROJECT=''${SENTRY_PROJECT} >> .env
Expand Down

This file was deleted.

67 changes: 40 additions & 27 deletions packages/ui-components/src/__tests__/CodeMirrorRainlang.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render } from '@testing-library/svelte';
import CodeMirrorRainlang from './CodeMirrorRainlang.test.svelte';
import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest';
import { render, waitFor } from '@testing-library/svelte';
import CodeMirrorRainlang from '../lib/components/CodeMirrorRainlang.svelte';
import type { Order } from '@rainlanguage/orderbook/js_api';
import * as orderBookApi from '@rainlanguage/orderbook/js_api';
import { extendOrder } from '@rainlanguage/orderbook/js_api';
import { writable } from 'svelte/store';

// Mock the extendOrder function
Expand All @@ -13,6 +13,15 @@ vi.mock('@rainlanguage/orderbook/js_api', () => ({
}))
}));

vi.mock('codemirror-rainlang', () => ({
RainlangLR: vi.fn()
}));

vi.mock('svelte-codemirror-editor', async () => {
const mockCodeMirror = (await import('../lib/__mocks__/MockComponent.svelte')).default;
return { default: mockCodeMirror };
});

describe('CodeMirrorRainlang', () => {
beforeEach(() => {
vi.clearAllMocks();
Expand All @@ -21,47 +30,51 @@ describe('CodeMirrorRainlang', () => {
it('should use extendOrder when order prop is provided', () => {
const mockOrder: Order = {} as Order;

const { getByTestId } = render(CodeMirrorRainlang, {
render(CodeMirrorRainlang, {
props: {
props: {
order: mockOrder,
rainlangText: 'original text',
codeMirrorTheme: writable({})
}
order: mockOrder,
codeMirrorTheme: writable({}),
codeMirrorDisabled: false,
codeMirrorStyles: {}
}
});

expect(orderBookApi.extendOrder).toHaveBeenCalledWith(mockOrder);
expect(getByTestId('test-value').textContent).toBe('mocked rainlang text');
expect(extendOrder).toHaveBeenCalledWith(mockOrder);
});

it('should use rainlangText when no order is provided', () => {
const testText = 'test rainlang text';

const { getByTestId } = render(CodeMirrorRainlang, {
render(CodeMirrorRainlang, {
props: {
props: {
rainlangText: testText,
codeMirrorTheme: writable({})
}
order: undefined,
rainlangText: testText,
codeMirrorTheme: writable({}),
codeMirrorDisabled: false,
codeMirrorStyles: {}
}
});

expect(orderBookApi.extendOrder).not.toHaveBeenCalled();
expect(getByTestId('test-value').textContent).toBe(testText);
expect(extendOrder).not.toHaveBeenCalled();
});

it('should pass through disabled prop', () => {
const { getByTestId } = render(CodeMirrorRainlang, {
it('should pass through disabled prop', async () => {
const mockOrder: Order = {} as Order;
const mockExtendedOrder = { order: {} };

(extendOrder as Mock).mockReturnValue(mockExtendedOrder);

const screen = render(CodeMirrorRainlang, {
props: {
props: {
disabled: true,
rainlangText: 'test',
codeMirrorTheme: writable({})
}
order: mockOrder,
codeMirrorTheme: writable({}),
codeMirrorDisabled: false,
codeMirrorStyles: {}
}
});

expect(getByTestId('test-value')).toBeTruthy();
await waitFor(() => {
expect(screen.getByTestId('rainlang-not-included')).toBeInTheDocument();
});
});
});
39 changes: 39 additions & 0 deletions packages/ui-components/src/__tests__/InputToken.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { render, fireEvent } from '@testing-library/svelte';
import InputToken from '../lib/components/input/InputToken.svelte';

describe('InputToken', () => {
it('renders with initial values', () => {
const address = '0xc0D477556c25C9d67E1f57245C7453DA776B51cf';
const decimals = 10;
const { getByTestId } = render(InputToken, { props: { address, decimals } });

const input = getByTestId('token-address').querySelector('input');
expect(input?.value).toBe('0xc0D477556c25C9d67E1f57245C7453DA776B51cf');
const decimalsInput = getByTestId('token-decimals-input').querySelector('input');
expect(decimalsInput?.value).toBe('10');
});

it('shows error for invalid address', async () => {
const address = 'abc';
const decimals = 0;
const { getByTestId, getByText } = render(InputToken, { props: { address, decimals } });

const addressInput = getByTestId('token-address').querySelector('input') as HTMLInputElement;
await fireEvent.input(addressInput, { target: { value: 'invalidAddress' } });

expect(getByText('Invalid Address')).toBeInTheDocument();
});

it('does not show error for valid address', async () => {
const address = '';
const decimals = 0;
const { getByTestId, queryByText } = render(InputToken, { props: { address, decimals } });

const addressInput = getByTestId('token-address').querySelector('input') as HTMLInputElement;
await fireEvent.input(addressInput, {
target: { value: '0xc0D477556c25C9d67E1f57245C7453DA776B51cf' }
});

expect(queryByText('Invalid Address')).toBeNull();
});
});
7 changes: 7 additions & 0 deletions packages/ui-components/src/additional-svelte-typings.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
declare namespace svelteHTML {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface HTMLAttributes<T> {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
'on:complete'?: (event: any) => any;
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,38 @@
<script lang="ts">
import type { Order } from '@rainlanguage/orderbook/js_api';
import { extendOrder } from '@rainlanguage/orderbook/js_api';
import CodeMirror from 'svelte-codemirror-editor';
import { RainlangLR } from 'codemirror-rainlang';
export let order: Order | undefined = undefined;
export let rainlangText: string = '';
export let rainlangText: string | undefined = undefined;
export let codeMirrorTheme;
export let disabled = false;
export let styles = {};
export let codeMirrorDisabled = true;
export let codeMirrorStyles = {};
$: value = order ? extendOrder(order).rainlang : rainlangText;
$: extendedOrder = order ? extendOrder(order) : undefined;
</script>

<slot name="codemirror" {value} {codeMirrorTheme} {disabled} {styles}></slot>
{#if extendedOrder?.rainlang}
<CodeMirror
value={rainlangText || extendedOrder.rainlang}
extensions={[RainlangLR]}
theme={codeMirrorTheme}
readonly={codeMirrorDisabled}
useTab={true}
tabSize={2}
styles={{
'&': {
width: '100%'
},
...codeMirrorStyles
}}
/>
{:else if !extendedOrder?.rainlang && !rainlangText}
<div
class="w-full tracking-tight text-gray-900 dark:text-white"
data-testid="rainlang-not-included"
>
Rain source not included in order meta
</div>
{/if}
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@
import { QKEY_ORDER } from '../../queries/keys';
import CodeMirrorRainlang from '../CodeMirrorRainlang.svelte';
import { queryClient } from '../../stores/queryClient';
import CodeMirror from 'svelte-codemirror-editor';
import { RainlangLR } from 'codemirror-rainlang';
import { getOrder, type Order } from '@rainlanguage/orderbook/js_api';
import { createQuery } from '@tanstack/svelte-query';
import { Button, TabItem, Tabs } from 'flowbite-svelte';
Expand Down Expand Up @@ -157,26 +154,9 @@
<CodeMirrorRainlang
order={data}
codeMirrorTheme={$codeMirrorTheme}
disabled={codeMirrorDisabled}
styles={codeMirrorStyles}
>
<svelte:fragment slot="codemirror" let:value>
<CodeMirror
{value}
extensions={[RainlangLR]}
theme={codeMirrorTheme}
readonly={codeMirrorDisabled}
useTab={true}
tabSize={2}
styles={{
'&': {
width: '100%'
},
...codeMirrorStyles
}}
/>
</svelte:fragment>
</CodeMirrorRainlang>
{codeMirrorDisabled}
{codeMirrorStyles}
></CodeMirrorRainlang>
</div>
</TabItem>
<TabItem title="Trades">
Expand Down
60 changes: 60 additions & 0 deletions packages/ui-components/src/lib/components/input/InputToken.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<script lang="ts">
import { Helper, Input } from 'flowbite-svelte';
import type { InputMask } from 'imask';
import { imask } from '@imask/svelte';
import { isAddress } from 'viem';
let decimalsRaw: string = '';
export let decimals: number | undefined;
export let address: string = '';
$: isAddressValid = address && address.length > 0 && isAddress(address);
$: {
if (decimals !== undefined) {
decimalsRaw = decimals.toString();
}
}
const decimalsMaskOptions = {
mask: Number,
min: 0,
lazy: false,
scale: 0,
thousandsSeparator: '',
radix: '.'
};
function decimalsComplete({ detail }: { detail: InputMask }) {
decimalsRaw = detail.value;
if (detail.unmaskedValue.length === 0) {
decimals = 0;
} else {
decimals = parseInt(detail.unmaskedValue);
}
}
</script>

<div class="flex w-full items-start justify-start space-x-2">
<div class="grow" data-testid="token-address">
<div class="relative flex">
<Input label="Token Address" name="address" required bind:value={address} />
</div>

{#if !isAddressValid && address.length > 0}
<Helper class="mt-2 text-sm" color="red">Invalid Address</Helper>
{/if}

<Helper class="mt-2 text-sm">Token Address</Helper>
</div>
<div class="w-32 grow-0 break-all" data-testid="token-decimals-input">
<input
type="text"
value={decimalsRaw}
class="focus:border-primary-500 focus:ring-primary-500 dark:focus:border-primary-500 dark:focus:ring-primary-500 block w-full rounded-lg border-gray-300 bg-gray-50 p-2.5 text-sm text-gray-900 disabled:cursor-not-allowed disabled:opacity-50 rtl:text-right dark:border-gray-500 dark:bg-gray-600 dark:text-white dark:placeholder-gray-400"
use:imask={decimalsMaskOptions}
on:complete={decimalsComplete}
/>
<Helper class="break-word mt-2 text-sm">Decimals</Helper>
</div>
</div>
1 change: 1 addition & 0 deletions packages/ui-components/src/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export { default as IconSuccess } from './components/IconSuccess.svelte';
export { default as IconTelegram } from './components/IconTelegram.svelte';
export { default as IconWalletConnect } from './components/IconWalletConnect.svelte';
export { default as IconWarning } from './components/IconWarning.svelte';
export { default as InputToken } from './components/input/InputToken.svelte';

//Types
export type { AppStoresInterface } from './types/appStores.ts';
Expand Down
Loading

0 comments on commit acf4b72

Please sign in to comment.