Browse Source

test(network-view): add remaining unit tests for Network View screen

feat/auto-update
jamaljsr 5 years ago
committed by jamaljsr
parent
commit
42597d8bc3
  1. 42
      src/components/network/BitcoinCard.spec.tsx
  2. 38
      src/components/network/BitcoindCard.tsx
  3. 46
      src/components/network/LndCard.spec.tsx
  4. 40
      src/components/network/LndCard.tsx
  5. 45
      src/components/network/NetworkActions.spec.tsx
  6. 2
      src/components/network/NetworkActions.tsx
  7. 38
      src/components/network/NetworkView.spec.tsx
  8. 24
      src/components/network/NetworkView.tsx
  9. 7
      src/store/models/network.spec.ts
  10. 12
      src/utils/tests.tsx

42
src/components/network/BitcoinCard.spec.tsx

@ -0,0 +1,42 @@
import React from 'react';
import { renderWithProviders } from 'utils/tests';
import { BitcoinNode, Status } from 'types';
import BitcoindCard from './BitcoindCard';
describe('StatusTag Component', () => {
const node: BitcoinNode = {
id: 1,
name: 'test btc',
implementation: 'bitcoind',
status: Status.Stopped,
type: 'bitcoin',
};
const details = [
{ label: 'Block Height', value: '432' },
{ label: 'Wallet Balance', value: '54.00000000' },
{ label: 'Host', value: '159.65.239.204' },
{ label: 'Version', value: 'v0.18.1' },
];
const renderComponent = () => {
return renderWithProviders(<BitcoindCard node={node} details={details} />);
};
it('should render the name', () => {
const { getByText } = renderComponent();
expect(getByText(node.name)).toBeTruthy();
});
it('should render the details', () => {
const { getByText } = renderComponent();
expect(getByText(details[0].label)).toBeTruthy();
expect(getByText(details[0].value)).toBeTruthy();
expect(getByText(details[1].label)).toBeTruthy();
expect(getByText(details[1].value)).toBeTruthy();
expect(getByText(details[2].label)).toBeTruthy();
expect(getByText(details[2].value)).toBeTruthy();
expect(getByText(details[3].label)).toBeTruthy();
expect(getByText(details[3].value)).toBeTruthy();
});
});

38
src/components/network/BitcoindCard.tsx

@ -7,30 +7,22 @@ import logo from 'resources/bitcoin.svg';
interface Props { interface Props {
node: BitcoinNode; node: BitcoinNode;
className?: string; className?: string;
details: { label: string; value: string }[];
} }
const btcDetails = [ const BitcoindCard: React.FC<Props> = ({ node, className, details }) => (
{ label: 'Block Height', value: '432' }, <Card
{ label: 'Wallet Balance', value: '54.00000000' }, title={<StatusBadge status={node.status} text={node.name} />}
{ label: 'Host', value: '159.65.239.204:8443' }, className={className}
{ label: 'Version', value: 'v0.18.1' }, extra={<Avatar src={logo} shape="square" />}
]; actions={[
<Icon type="code" key="code" />,
const BitcoindCard: React.FC<Props> = ({ node, className }) => { <Icon type="file-text" key="logs" />,
return ( <Icon type="ellipsis" key="ellipsis" />,
<Card ]}
title={<StatusBadge status={node.status} text={node.name} />} >
className={className} <DetailsList details={details} />
extra={<Avatar src={logo} shape="square" />} </Card>
actions={[ );
<Icon type="code" key="code" />,
<Icon type="file-text" key="logs" />,
<Icon type="ellipsis" key="ellipsis" />,
]}
>
<DetailsList details={btcDetails} />
</Card>
);
};
export default BitcoindCard; export default BitcoindCard;

46
src/components/network/LndCard.spec.tsx

@ -0,0 +1,46 @@
import React from 'react';
import { renderWithProviders } from 'utils/tests';
import { LightningNode, Status } from 'types';
import LndCard from './LndCard';
describe('StatusTag Component', () => {
const node: LightningNode = {
id: 1,
name: 'test lnd',
implementation: 'LND',
status: Status.Stopped,
type: 'lightning',
backendName: 'bitcoind-1',
};
const details = [
{ label: 'PubKey', value: '0245....5fd47' },
{ label: 'Host', value: '159.65.239.204' },
{ label: 'Synced to Chain', value: 'true' },
{ label: 'Chain Node', value: 'bitcoind1' },
{ label: 'Version', value: 'v0.7.1' },
];
const renderComponent = () => {
return renderWithProviders(<LndCard node={node} details={details} />);
};
it('should render the name', () => {
const { getByText } = renderComponent();
expect(getByText(node.name)).toBeTruthy();
});
it('should render the details', () => {
const { getByText } = renderComponent();
expect(getByText(details[0].label)).toBeTruthy();
expect(getByText(details[0].value)).toBeTruthy();
expect(getByText(details[1].label)).toBeTruthy();
expect(getByText(details[1].value)).toBeTruthy();
expect(getByText(details[2].label)).toBeTruthy();
expect(getByText(details[2].value)).toBeTruthy();
expect(getByText(details[3].label)).toBeTruthy();
expect(getByText(details[3].value)).toBeTruthy();
expect(getByText(details[4].label)).toBeTruthy();
expect(getByText(details[4].value)).toBeTruthy();
});
});

40
src/components/network/LndCard.tsx

@ -7,32 +7,22 @@ import lnd from 'resources/lnd.png';
interface Props { interface Props {
node: LightningNode; node: LightningNode;
className?: string; className?: string;
details: { label: string; value: string }[];
} }
const lndDetails = [ const LndCard: React.FC<Props> = ({ node, details, className }) => (
{ label: 'PubKey', value: '0245....5fd47' }, <Card
{ label: 'Host', value: '159.65.239.204:9735' }, title={<StatusBadge status={node.status} text={node.name} />}
{ label: 'Channels', value: '2' }, className={className}
{ label: 'Synced to Chain', value: 'true' }, extra={<Avatar src={lnd} shape="square" />}
{ label: 'Chain Node', value: 'bitcoind1' }, actions={[
{ label: 'Version', value: 'v0.7.1' }, <Icon type="code" key="code" />,
]; <Icon type="file-text" key="logs" />,
<Icon type="ellipsis" key="ellipsis" />,
const LndCard: React.FC<Props> = ({ node, className }) => { ]}
return ( >
<Card <DetailsList details={details} />
title={<StatusBadge status={node.status} text={node.name} />} </Card>
className={className} );
extra={<Avatar src={lnd} shape="square" />}
actions={[
<Icon type="code" key="code" />,
<Icon type="file-text" key="logs" />,
<Icon type="ellipsis" key="ellipsis" />,
]}
>
<DetailsList details={lndDetails} />
</Card>
);
};
export default LndCard; export default LndCard;

45
src/components/network/NetworkActions.spec.tsx

@ -0,0 +1,45 @@
import React from 'react';
import { renderWithProviders } from 'utils/tests';
import { Status } from 'types';
import NetworkActions from './NetworkActions';
describe('NetworkActions Component', () => {
const renderComponent = (status: Status) => {
return renderWithProviders(<NetworkActions status={status} />);
};
it('should render the Starting status', () => {
const { getByText } = renderComponent(Status.Starting);
expect(getByText('Starting')).toBeTruthy();
// button should be loading
expect(getByText('Starting').parentElement).toHaveClass('ant-btn-loading');
});
it('should render the Started status', () => {
const { getByText } = renderComponent(Status.Started);
expect(getByText('Stop')).toBeTruthy();
// button should not be loading
expect(getByText('Stop').parentElement).not.toHaveClass('ant-btn-loading');
});
it('should render the Stopping status', () => {
const { getByText } = renderComponent(Status.Stopping);
expect(getByText('Stopping')).toBeTruthy();
// button should be loading
expect(getByText('Stopping').parentElement).toHaveClass('ant-btn-loading');
});
it('should render the Stopped status', () => {
const { getByText } = renderComponent(Status.Stopped);
expect(getByText('Start')).toBeTruthy();
// button should be loading
expect(getByText('Start').parentElement).not.toHaveClass('ant-btn-loading');
});
it('should render the Error status', () => {
const { getByText } = renderComponent(Status.Error);
expect(getByText('Restart')).toBeTruthy();
// button should be loading
expect(getByText('Restart').parentElement).not.toHaveClass('ant-btn-loading');
});
});

2
src/components/network/NetworkActions.tsx

@ -35,7 +35,7 @@ const config: {
icon: 'play-circle', icon: 'play-circle',
}, },
[Status.Error]: { [Status.Error]: {
label: 'Stop', label: 'Restart',
type: 'danger', type: 'danger',
icon: 'warning', icon: 'warning',
}, },

38
src/components/network/NetworkView.spec.tsx

@ -0,0 +1,38 @@
import React from 'react';
import { Route } from 'react-router';
import { renderWithProviders, getNetwork } from 'utils/tests';
import NetworkView from './NetworkView';
describe('NetworkView Component', () => {
const renderComponent = (route = '/network/1') => {
const initialState = {
network: {
networks: [getNetwork(1, 'test network')],
},
};
// NetworkView needs to be rendered by the router due to
// RouteComponentProps not being easily mockable
const cmp = <Route path="/network/:id" component={NetworkView} />;
return renderWithProviders(cmp, { initialState, route });
};
it('should not render if the network is not found', () => {
const { queryByText } = renderComponent('/network/99');
expect(queryByText('test network')).toBeNull();
});
it('should render the name', () => {
const { getByText } = renderComponent();
expect(getByText('test network')).toBeTruthy();
});
it('should render correct # of LND nodes', () => {
const { queryAllByText } = renderComponent();
expect(queryAllByText(/lnd-\d/)).toHaveLength(2);
});
it('should render correct # of bitcoind nodes', () => {
const { queryAllByText } = renderComponent();
expect(queryAllByText(/bitcoind-\d/)).toHaveLength(1);
});
});

24
src/components/network/NetworkView.tsx

@ -12,6 +12,22 @@ interface MatchParams {
id?: string; id?: string;
} }
const btcDetails = [
{ label: 'Block Height', value: '432' },
{ label: 'Wallet Balance', value: '54.00000000' },
{ label: 'Host', value: '159.65.239.204' },
{ label: 'Version', value: 'v0.18.1' },
];
const lndDetails = [
{ label: 'PubKey', value: '0245....5fd47' },
{ label: 'Host', value: '159.65.239.204' },
{ label: 'Channels', value: '2' },
{ label: 'Synced to Chain', value: 'true' },
{ label: 'Chain Node', value: 'bitcoind1' },
{ label: 'Version', value: 'v0.7.1' },
];
const NetworkView: React.FC<RouteComponentProps<MatchParams>> = ({ match }) => { const NetworkView: React.FC<RouteComponentProps<MatchParams>> = ({ match }) => {
const network = useStoreState(s => s.network.networkById(match.params.id)); const network = useStoreState(s => s.network.networkById(match.params.id));
if (!network) { if (!network) {
@ -32,16 +48,16 @@ const NetworkView: React.FC<RouteComponentProps<MatchParams>> = ({ match }) => {
<Divider>Lightning Nodes</Divider> <Divider>Lightning Nodes</Divider>
<Row gutter={16} data-tid="ln-nodes"> <Row gutter={16} data-tid="ln-nodes">
{lightning.map(node => ( {lightning.map(node => (
<Col key={node.id} span={8}> <Col key={node.id} span={12}>
<LndCard node={node} className={styles.card} /> <LndCard node={node} details={lndDetails} className={styles.card} />
</Col> </Col>
))} ))}
</Row> </Row>
<Divider>Bitcoin Nodes</Divider> <Divider>Bitcoin Nodes</Divider>
<Row gutter={16} data-tid="btc-nodes"> <Row gutter={16} data-tid="btc-nodes">
{bitcoin.map(node => ( {bitcoin.map(node => (
<Col key={node.id} span={8}> <Col key={node.id} span={12}>
<BitcoindCard node={node} className={styles.card} /> <BitcoindCard node={node} details={btcDetails} className={styles.card} />
</Col> </Col>
))} ))}
</Row> </Row>

7
src/store/models/network.spec.ts

@ -92,4 +92,11 @@ describe('counter model', () => {
expect(network.id).toBe(1); expect(network.id).toBe(1);
expect(network.name).toBe('test'); expect(network.name).toBe('test');
}); });
it('should fail to fetch a node with invalid id', () => {
store.getActions().add(addNetworkArgs);
expect(store.getState().networkById((null as unknown) as string)).toBeUndefined();
expect(store.getState().networkById('asdf')).toBeUndefined();
expect(store.getState().networkById('99')).toBeUndefined();
});
}); });

12
src/utils/tests.tsx

@ -14,8 +14,8 @@ export const getNetwork = (networkId?: number, name?: string): Network => ({
nodes: { nodes: {
bitcoin: [ bitcoin: [
{ {
id: 0, id: 1,
name: 'bitcoind1', name: 'bitcoind-1',
type: 'bitcoin', type: 'bitcoin',
implementation: 'bitcoind', implementation: 'bitcoind',
status: Status.Stopped, status: Status.Stopped,
@ -23,16 +23,16 @@ export const getNetwork = (networkId?: number, name?: string): Network => ({
], ],
lightning: [ lightning: [
{ {
id: 0, id: 1,
name: 'alice', name: 'lnd-1',
type: 'lightning', type: 'lightning',
implementation: 'LND', implementation: 'LND',
status: Status.Stopped, status: Status.Stopped,
backendName: 'bitcoind1', backendName: 'bitcoind1',
}, },
{ {
id: 0, id: 2,
name: 'bob', name: 'lnd-2',
type: 'lightning', type: 'lightning',
implementation: 'LND', implementation: 'LND',
status: Status.Stopped, status: Status.Stopped,

Loading…
Cancel
Save