Skip to content

Commit

Permalink
test(tapd): update unit tests for the latest tapd
Browse files Browse the repository at this point in the history
  • Loading branch information
jamaljsr committed Oct 20, 2023
1 parent 6d26ee8 commit b1b9bc2
Show file tree
Hide file tree
Showing 18 changed files with 172 additions and 78 deletions.
29 changes: 23 additions & 6 deletions src/components/common/RemoveNode.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { CommonNode, Status } from 'shared/types';
import { BitcoindLibrary, DockerLibrary } from 'types';
import { initChartFromNetwork } from 'utils/chart';
import { defaultRepoState } from 'utils/constants';
import { createBitcoindNetworkNode } from 'utils/network';
import { createBitcoindNetworkNode, createLndNetworkNode } from 'utils/network';
import {
getNetwork,
injections,
Expand All @@ -26,6 +26,12 @@ describe('RemoveNode', () => {
nodeType?: CommonNode['type'],
) => {
const network = getNetwork(1, 'test network', status, 2);
// add an extra lightning node to the network without a connected tapd node
const lnd = defaultRepoState.images.LND;
network.nodes.lightning.push(
createLndNetworkNode(network, lnd.latest, lnd.compatibility, testNodeDocker),
);

if (status === Status.Error) {
network.nodes.lightning.forEach(n => (n.errorMsg = 'test-error'));
}
Expand All @@ -43,6 +49,11 @@ describe('RemoveNode', () => {
},
activeId: 1,
},
lightning: {
nodes: {
carol: {},
},
},
};
const { lightning, bitcoin, tap } = network.nodes;
const node = [...lightning, ...bitcoin, ...tap].find(
Expand Down Expand Up @@ -72,28 +83,31 @@ describe('RemoveNode', () => {
it('should remove the node with the network stopped', async () => {
const { getByText, findByText, getByLabelText } = renderComponent(
Status.Stopped,
'bob',
'carol',
);
expect(getByText('Remove')).toBeInTheDocument();
fireEvent.click(getByText('Remove'));
fireEvent.click(await findByText('Yes'));
// wait for the error notification to be displayed
await waitFor(() => getByLabelText('check-circle'));
expect(
getByText('The node bob has been removed from the network'),
getByText('The node carol has been removed from the network'),
).toBeInTheDocument();
expect(dockerServiceMock.removeNode).toBeCalledTimes(0);
});

it('should remove the node with the network started', async () => {
const { getByText, findByText, getByLabelText } = renderComponent(Status.Started);
const { getByText, findByText, getByLabelText } = renderComponent(
Status.Started,
'carol',
);
expect(getByText('Remove')).toBeInTheDocument();
fireEvent.click(getByText('Remove'));
fireEvent.click(await findByText('Yes'));
// wait for the error notification to be displayed
await waitFor(() => getByLabelText('check-circle'));
expect(
getByText('The node alice has been removed from the network'),
getByText('The node carol has been removed from the network'),
).toBeInTheDocument();
expect(dockerServiceMock.removeNode).toBeCalledTimes(1);
});
Expand All @@ -103,7 +117,10 @@ describe('RemoveNode', () => {
// this suppresses those errors from being displayed in test runs
await suppressConsoleErrors(async () => {
dockerServiceMock.removeNode.mockRejectedValue(new Error('test error'));
const { getByText, findByText, getByLabelText } = renderComponent(Status.Started);
const { getByText, findByText, getByLabelText } = renderComponent(
Status.Started,
'carol',
);
expect(getByText('Remove')).toBeInTheDocument();
fireEvent.click(getByText('Remove'));
fireEvent.click(await findByText('Yes'));
Expand Down
41 changes: 37 additions & 4 deletions src/components/designer/NetworkDesigner.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ import { act } from '@testing-library/react';
import { Status } from 'shared/types';
import { themeColors } from 'theme/colors';
import { initChartFromNetwork } from 'utils/chart';
import { getNetwork, renderWithProviders } from 'utils/tests';
import {
getNetwork,
renderWithProviders,
suppressConsoleErrors,
testRepoState,
} from 'utils/tests';
import NetworkDesigner from './NetworkDesigner';

describe('NetworkDesigner Component', () => {
Expand Down Expand Up @@ -198,6 +203,7 @@ describe('NetworkDesigner Component', () => {
).toBeInTheDocument();
fireEvent.click(getByText('Cancel'));
});

it('should display the Send Address modal', async () => {
const { getByText, findByText, store } = renderComponent();
expect(await findByText('backend1')).toBeInTheDocument();
Expand All @@ -219,16 +225,43 @@ describe('NetworkDesigner Component', () => {
});

it('should remove a node from the network', async () => {
const { getByText, findByText, queryByText } = renderComponent();
const { getByText, findByText, queryByText, store } = renderComponent();
// add a new LN node that doesn't have a tap node connected
store.getActions().designer.onCanvasDrop({
config: { snapToGrid: true },
data: { type: 'LND', version: testRepoState.images.LND.latest },
position: { x: 584, y: 343 },
id: 'c815fd9d-bbeb-4263-ad96-00bc488d8d60',
});

expect(await findByText('carol')).toBeInTheDocument();
act(() => {
fireEvent.click(getByText('carol'));
});
fireEvent.click(await findByText('Actions'));
fireEvent.click(await findByText('Remove'));
fireEvent.click(await findByText('Yes'));
await waitForElementToBeRemoved(() => queryByText('Yes'));
expect(queryByText('carol')).toBeNull();
});

it('should not remove an LND node with a connected tapd node', async () => {
const { getByText, findByText } = renderComponent();
expect(await findByText('alice')).toBeInTheDocument();
act(() => {
fireEvent.click(getByText('alice'));
});
fireEvent.click(await findByText('Actions'));
fireEvent.click(await findByText('Remove'));
fireEvent.click(await findByText('Yes'));
await waitForElementToBeRemoved(() => queryByText('Yes'));
expect(queryByText('alice')).toBeNull();

await suppressConsoleErrors(async () => {
expect(
await findByText(
'Cannot remove a Lightning node that has a Taproot Assets node connected to it.',
),
).toBeInTheDocument();
});
});

it('should remove a TAP node from the network', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,12 @@ describe('ChangeTapBackendModal', () => {
it('should display the compatibility warning for older LND node', async () => {
const { getByText, queryByText, changeSelect, store } = await renderComponent();
store.getActions().app.setRepoState(testRepoState);
const tapdLatest = testRepoState.images.tapd.latest;
const compatibleLnd = testRepoState.images.tapd.compatibility![tapdLatest];
const warning =
`alice-tap is running tapd v0.2.3-alpha which is compatible with LND v0.16.0-beta and newer.` +
` dave is running LND v0.7.1-beta so it cannot be used.`;
`alice-tap is running tapd v${tapdLatest} which is ` +
`compatible with LND v${compatibleLnd} and newer. ` +
`dave is running LND v0.7.1-beta so it cannot be used.`;
expect(queryByText(warning)).not.toBeInTheDocument();
expect(getByText('Cancel')).toBeInTheDocument();
changeSelect('LND Node', 'dave');
Expand Down
15 changes: 14 additions & 1 deletion src/components/designer/tap/actions/MintAssetModal.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,15 @@ describe('MintAssetModal', () => {
expect(btn.parentElement).toBeInstanceOf(HTMLButtonElement);
});

it('should update amount when type changes', async () => {
const { getByLabelText, changeSelect } = await renderComponent();
expect(getByLabelText('Amount')).toHaveValue('1,000');
changeSelect('Asset Type', 'Collectible');
expect(getByLabelText('Amount')).toHaveValue('1');
changeSelect('Asset Type', 'Normal');
expect(getByLabelText('Amount')).toHaveValue('1,000');
});

it('should hide modal when cancel is clicked', async () => {
const { getByText, queryByText, store } = await renderComponent();
const btn = getByText('Cancel');
Expand All @@ -99,7 +108,11 @@ describe('MintAssetModal', () => {
Promise.resolve(balances((node.id + 100).toString())),
);
tapServiceMock.mintAsset.mockResolvedValue({
batchKey: Buffer.from('mocked success!'),
pendingBatch: {
batchKey: Buffer.from('mocked success!'),
assets: [],
state: 'BATCH_STATE_FINALIZED',
},
});

lightningServiceMock.getBalances.mockResolvedValue({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ describe('NewAddressModal', () => {
expect(await findByText('Successfully created address')).toBeInTheDocument();
expect(getByDisplayValue('tap1address')).toBeInTheDocument();
const node = network.nodes.tap[0];
expect(tapServiceMock.newAddress).toBeCalledWith(node, 'test-id', 100);
expect(tapServiceMock.newAddress).toBeCalledWith(node, 'test-id', '100');
});

it('should close the modal', async () => {
Expand Down
31 changes: 28 additions & 3 deletions src/components/designer/tap/actions/SendAssetModal.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { initChartFromNetwork } from 'utils/chart';
import {
defaultTapAddress,
defaultTapAsset,
defaultTapBalance,
getNetwork,
injections,
lightningServiceMock,
Expand All @@ -30,7 +31,9 @@ describe('SendAssetModal', () => {
assets: [
defaultTapAsset({ id: 'test1234', name: 'testAsset', amount: '1000' }),
],
balances: [],
balances: [
defaultTapBalance({ id: 'test1234', name: 'testAsset', balance: '1000' }),
],
},
},
},
Expand Down Expand Up @@ -145,21 +148,31 @@ describe('SendAssetModal', () => {
total: '300000',
});
tapServiceMock.decodeAddress.mockResolvedValue(
defaultTapAddress({ id: 'test1234', type: 'NORMAL', amount: '100' }),
defaultTapAddress({
id: 'test1234',
type: 'NORMAL',
amount: '100',
internalKey: 'key1234',
}),
);
});

it('should not display an alert or auto deposit', async () => {
const { queryByText } = await renderComponent();
expect(
queryByText('Insufficient balance on lnd node alice'),
).not.toBeInTheDocument();
expect(queryByText('Deposit enough funds to alice')).not.toBeInTheDocument();
});

it('should send the asset when send is clicked', async () => {
tapServiceMock.decodeAddress.mockResolvedValue(
defaultTapAddress({ id: 'test1234', type: 'NORMAL', amount: '100' }),
);
const { getByLabelText, getByText } = await renderComponent();
tapServiceMock.listBalances.mockResolvedValue([
defaultTapBalance({ id: 'test1234', name: 'testAsset', balance: '1000' }),
]);
const { getByLabelText, getByText, queryByText } = await renderComponent();
const input = getByLabelText('TAP Address');
expect(input).toBeInTheDocument();
fireEvent.change(input, { target: { value: 'tap1address' } });
Expand All @@ -179,6 +192,18 @@ describe('SendAssetModal', () => {
await waitFor(() => {
expect(tapServiceMock.sendAsset).toHaveBeenCalled();
expect(bitcoindServiceMock.mine).toHaveBeenCalled();
expect(tapServiceMock.listBalances).toHaveBeenCalled();
});

// return an updated balance after the sendAsset request
tapServiceMock.listBalances.mockResolvedValue([
defaultTapBalance({ id: 'test1234', name: 'testAsset', balance: '1100' }),
]);

// the modal should close after the senders balance changes
await waitFor(() => {
expect(queryByText('Send')).not.toBeInTheDocument();
expect(getByText("Sent 100 testAsset's to tap1address")).toBeInTheDocument();
});
});
});
Expand Down
2 changes: 1 addition & 1 deletion src/components/designer/tap/actions/SendAssetModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const SendAssetModal: React.FC<Props> = ({ network }) => {
message: l('success', {
amount: decodedAddress?.amount,
assetName,
internalKey: decodedAddress?.internalKey,
addr: ellipseInner(payload.address, 6),
}),
});
hideSendAsset();
Expand Down
5 changes: 1 addition & 4 deletions src/components/nodeImages/ManagedImageModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { usePrefixedTranslation } from 'hooks';
import { useStoreActions } from 'store';
import { ManagedImage } from 'types';
import { dockerConfigs } from 'utils/constants';
import { getDockerCommand } from 'utils/network';
import { CommandVariables } from './';

const Styled = {
Expand Down Expand Up @@ -69,9 +68,7 @@ const ManagedImageModal: React.FC<Props> = ({ image, onClose }) => {
layout="vertical"
hideRequiredMark
colon={false}
initialValues={{
command: getDockerCommand(image.implementation, image.version, image.command),
}}
initialValues={{ command: image.command || config.command }}
onFinish={handleSubmit}
>
<Styled.Summary>{l('summary')}</Styled.Summary>
Expand Down
2 changes: 1 addition & 1 deletion src/i18n/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@
"cmps.designer.tap.actions.SendAssetModal.type": "Type",
"cmps.designer.tap.actions.SendAssetModal.amount": "Amount",
"cmps.designer.tap.actions.SendAssetModal.id": "Asset Id: ",
"cmps.designer.tap.actions.SendAssetModal.success": "Sent {{amount}} {{assetName}}'s to {{internalKey}}",
"cmps.designer.tap.actions.SendAssetModal.success": "Sent {{amount}} {{assetName}}'s to {{addr}}",
"cmps.designer.tap.actions.SendAssetModal.missingAsset": "{{nodeName}} is missing this asset",
"cmps.designer.tap.actions.SendAssetModal.decodingError": "ERROR: Invalid Address",
"cmps.designer.tap.actions.SendAssetModal.submitError": "Error:",
Expand Down
6 changes: 3 additions & 3 deletions src/lib/docker/composeFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
TapdNode,
} from 'shared/types';
import { bitcoinCredentials, dockerConfigs, eclairCredentials } from 'utils/constants';
import { getContainerName, getDockerCommand } from 'utils/network';
import { getContainerName } from 'utils/network';
import { bitcoind, clightning, eclair, lnd, tapd } from './nodeTemplates';

export interface ComposeService {
Expand Down Expand Up @@ -145,7 +145,7 @@ class ComposeFile {
}

addTapd(node: TapdNode, lndBackend: LndNode) {
const { name, version, ports, implementation } = node;
const { name, version, ports } = node;
const { rest, grpc } = ports;
const container = getContainerName(node);
// define the variable substitutions
Expand All @@ -157,7 +157,7 @@ class ComposeFile {
// use the node's custom image or the default for the implementation
const image = node.docker.image || `${dockerConfigs.tapd.imageName}:${version}`;
// use the node's custom command or the default for the implementation
const nodeCommand = getDockerCommand(implementation, version, node.docker.command);
const nodeCommand = node.docker.command || dockerConfigs.tapd.command;
// replace the variables in the command
const command = this.mergeCommand(nodeCommand, variables);
// add the docker service
Expand Down
2 changes: 1 addition & 1 deletion src/lib/tap/tapd/tapProxyClient.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ describe('TapdProxyClient', () => {
const req: TAP.MintAssetRequestPartial = {
asset: {
assetMeta: {
type: TAP.AssetMetaType.MTEA_TYPE_OPAQUE,
type: TAP.AssetMetaType.META_TYPE_OPAQUE,
data: Buffer.from('test data').toString('base64'),
},
name: 'test',
Expand Down
Loading

0 comments on commit b1b9bc2

Please sign in to comment.