-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Since we now plan to support more than 1 feeds manager/job distributor, we want to have a home page where it shows a list of registered feeds managers JIRA: https://smartcontract-it.atlassian.net/browse/OPCORE-858
- Loading branch information
1 parent
cfd4ce8
commit d74af46
Showing
9 changed files
with
367 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,26 @@ | ||
import { gql, useQuery } from '@apollo/client' | ||
import { gql, QueryHookOptions, useQuery } from '@apollo/client' | ||
|
||
export const FEEDS_MANAGERS_QUERY = gql` | ||
fragment FetchFeedsManagersPayload_ResultsFields on FeedsManager { | ||
__typename | ||
id | ||
name | ||
uri | ||
publicKey | ||
isConnectionActive | ||
createdAt | ||
} | ||
query FetchFeedsManagers { | ||
feedsManagers { | ||
results { | ||
__typename | ||
id | ||
name | ||
uri | ||
publicKey | ||
isConnectionActive | ||
createdAt | ||
...FetchFeedsManagersPayload_ResultsFields | ||
} | ||
} | ||
} | ||
` | ||
|
||
export const useFeedsManagersQuery = () => { | ||
return useQuery<FetchFeedsManagers, FetchFeedsManagersVariables>( | ||
FEEDS_MANAGERS_QUERY, | ||
) | ||
export const useFeedsManagersQuery = ( | ||
options?: QueryHookOptions<FetchFeedsManagers>, | ||
) => { | ||
return useQuery<FetchFeedsManagers>(FEEDS_MANAGERS_QUERY, options) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import React from 'react' | ||
import green from '@material-ui/core/colors/green' | ||
import red from '@material-ui/core/colors/red' | ||
import { createStyles, WithStyles, withStyles } from '@material-ui/core/styles' | ||
import Typography from '@material-ui/core/Typography' | ||
import CancelIcon from '@material-ui/icons/Cancel' | ||
import CheckCircleIcon from '@material-ui/icons/CheckCircle' | ||
|
||
const connectionStatusStyles = () => { | ||
return createStyles({ | ||
root: { | ||
display: 'flex', | ||
}, | ||
connectedIcon: { | ||
color: green[500], | ||
}, | ||
disconnectedIcon: { | ||
color: red[500], | ||
}, | ||
text: { | ||
marginLeft: 4, | ||
}, | ||
}) | ||
} | ||
|
||
interface ConnectionStatusProps | ||
extends WithStyles<typeof connectionStatusStyles> { | ||
isConnected: boolean | ||
} | ||
|
||
export const ConnectionStatus = withStyles(connectionStatusStyles)( | ||
({ isConnected, classes }: ConnectionStatusProps) => { | ||
return ( | ||
<div className={classes.root}> | ||
{isConnected ? ( | ||
<CheckCircleIcon fontSize="small" className={classes.connectedIcon} /> | ||
) : ( | ||
<CancelIcon fontSize="small" className={classes.disconnectedIcon} /> | ||
)} | ||
|
||
<Typography variant="body1" inline className={classes.text}> | ||
{isConnected ? 'Connected' : 'Disconnected'} | ||
</Typography> | ||
</div> | ||
) | ||
}, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import React from 'react' | ||
|
||
import { withStyles, WithStyles } from '@material-ui/core/styles' | ||
import TableCell from '@material-ui/core/TableCell' | ||
import TableRow from '@material-ui/core/TableRow' | ||
|
||
import Link from 'components/Link' | ||
import { tableStyles } from 'components/Table' | ||
import { CopyIconButton } from 'src/components/Copy/CopyIconButton' | ||
import { shortenHex } from 'src/utils/shortenHex' | ||
import { ConnectionStatus } from '../FeedsManager/ConnectionStatus' | ||
|
||
interface Props extends WithStyles<typeof tableStyles> { | ||
jobDistributor: FetchFeedsManagersPayload_ResultsFields | ||
} | ||
|
||
export const JobDistributorsRow = withStyles(tableStyles)( | ||
({ jobDistributor, classes }: Props) => { | ||
return ( | ||
<TableRow className={classes.row} hover> | ||
<TableCell className={classes.cell} component="th" scope="row"> | ||
<Link | ||
className={classes.link} | ||
href={`/job_distributors/${jobDistributor.id}`} | ||
> | ||
{jobDistributor.name} | ||
</Link> | ||
</TableCell> | ||
<TableCell> | ||
<ConnectionStatus isConnected={jobDistributor.isConnectionActive} /> | ||
</TableCell> | ||
<TableCell> | ||
{shortenHex(jobDistributor.publicKey, { start: 6, end: 6 })} | ||
<CopyIconButton data={jobDistributor.publicKey} /> | ||
</TableCell> | ||
<TableCell>{jobDistributor.uri}</TableCell> | ||
</TableRow> | ||
) | ||
}, | ||
) |
74 changes: 74 additions & 0 deletions
74
src/screens/JobDistributors/JobDistributorsScreen.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import React from 'react' | ||
|
||
import { MockedProvider, MockedResponse } from '@apollo/client/testing' | ||
import { GraphQLError } from 'graphql' | ||
import { Route } from 'react-router-dom' | ||
import { renderWithRouter, screen, within } from 'test-utils' | ||
|
||
import { FEEDS_MANAGERS_QUERY } from 'src/hooks/queries/useFeedsManagersQuery' | ||
import { buildFeedsManager } from 'support/factories/gql/fetchFeedsManagers' | ||
import { waitForLoading } from 'support/test-helpers/wait' | ||
import { JobDistributorsScreen } from './JobDistributorsScreen' | ||
|
||
const { findAllByRole, findByText } = screen | ||
|
||
function renderComponent(mocks: MockedResponse[]) { | ||
renderWithRouter( | ||
<> | ||
<Route exact path="/job_distributors"> | ||
<MockedProvider mocks={mocks} addTypename={false}> | ||
<JobDistributorsScreen /> | ||
</MockedProvider> | ||
</Route> | ||
</>, | ||
{ initialEntries: ['/job_distributors'] }, | ||
) | ||
} | ||
|
||
describe('JobDistributorsScreen', () => { | ||
it('should render the list of job distributors', async () => { | ||
const mocks: MockedResponse[] = [ | ||
{ | ||
request: { | ||
query: FEEDS_MANAGERS_QUERY, | ||
}, | ||
result: { | ||
data: { | ||
feedsManagers: { | ||
results: [buildFeedsManager()], | ||
}, | ||
}, | ||
}, | ||
}, | ||
] | ||
|
||
renderComponent(mocks) | ||
|
||
await waitForLoading() | ||
|
||
const rows = await findAllByRole('row') | ||
|
||
// header counts as a row | ||
expect(rows).toHaveLength(2) | ||
expect( | ||
within(rows[1]).getByText('Chainlink Feeds Manager'), | ||
).toBeInTheDocument() | ||
}) | ||
|
||
it('should renders GQL errors', async () => { | ||
const mocks: MockedResponse[] = [ | ||
{ | ||
request: { | ||
query: FEEDS_MANAGERS_QUERY, | ||
}, | ||
result: { | ||
errors: [new GraphQLError('Error!')], | ||
}, | ||
}, | ||
] | ||
|
||
renderComponent(mocks) | ||
|
||
expect(await findByText('Error: Error!')).toBeInTheDocument() | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import React from 'react' | ||
|
||
import { GraphqlErrorHandler } from 'src/components/ErrorHandler/GraphqlErrorHandler' | ||
import { Loading } from 'src/components/Feedback/Loading' | ||
import { useFeedsManagersQuery } from 'src/hooks/queries/useFeedsManagersQuery' | ||
import { JobDistributorsView } from './JobDistributorsView' | ||
|
||
export const JobDistributorsScreen = () => { | ||
const { data, loading, error } = useFeedsManagersQuery({ | ||
fetchPolicy: 'cache-and-network', | ||
}) | ||
|
||
if (loading) { | ||
return <Loading /> | ||
} | ||
|
||
if (error) { | ||
return <GraphqlErrorHandler error={error} /> | ||
} | ||
|
||
return ( | ||
<JobDistributorsView jobDistributors={data?.feedsManagers.results ?? []} /> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import React from 'react' | ||
|
||
import userEvent from '@testing-library/user-event' | ||
import { Route, Switch } from 'react-router-dom' | ||
|
||
import { buildFeedsManager } from 'support/factories/gql/fetchFeedsManagers' | ||
import { renderWithRouter, screen, within } from 'support/test-utils' | ||
import { JobDistributorsView } from './JobDistributorsView' | ||
|
||
const { getAllByRole, getByRole, getByText, findByText } = screen | ||
|
||
function renderComponent( | ||
mockData: ReadonlyArray<FetchFeedsManagersPayload_ResultsFields>, | ||
) { | ||
renderWithRouter( | ||
<Switch> | ||
<Route exact path="/job_distributors"> | ||
<JobDistributorsView jobDistributors={mockData} />, | ||
</Route> | ||
<Route exact path="/job_distributors/new"> | ||
New Job Distributor Page | ||
</Route> | ||
<Route exact path="/job_distributors/1"> | ||
Edit Job Distributor Page | ||
</Route> | ||
</Switch>, | ||
{ initialEntries: ['/job_distributors'] }, | ||
) | ||
} | ||
|
||
describe('JobDistributorsView', () => { | ||
test('should render the list of job distributors', () => { | ||
renderComponent([ | ||
buildFeedsManager(), | ||
buildFeedsManager({ | ||
name: 'Job Distributor 2', | ||
id: '2', | ||
isConnectionActive: true, | ||
}), | ||
]) | ||
|
||
expect(getByRole('heading')).toHaveTextContent('Job Distributors') | ||
|
||
// header row counts as 1 row too | ||
const rows = getAllByRole('row') | ||
expect(rows).toHaveLength(3) | ||
|
||
expect(getByText('Name')).toBeInTheDocument() | ||
expect(getByText('Status')).toBeInTheDocument() | ||
expect(getByText('CSA Public Key')).toBeInTheDocument() | ||
expect(getByText('RPC URL')).toBeInTheDocument() | ||
|
||
expect( | ||
within(rows[1]).getByText('Chainlink Feeds Manager'), | ||
).toBeInTheDocument() | ||
expect(within(rows[1]).getByText('Disconnected')).toBeInTheDocument() | ||
expect(within(rows[1]).getByText('localhost:8080')).toBeInTheDocument() | ||
|
||
expect(within(rows[2]).getByText('Job Distributor 2')).toBeInTheDocument() | ||
expect(within(rows[2]).getByText('Connected')).toBeInTheDocument() | ||
expect(within(rows[2]).getByText('localhost:8080')).toBeInTheDocument() | ||
}) | ||
|
||
test('should navigate to create new job distributor page when new button is clicked', async () => { | ||
renderComponent([buildFeedsManager()]) | ||
|
||
userEvent.click(getByText(/New Job Distributor/i)) | ||
|
||
expect(await findByText('New Job Distributor Page')).toBeInTheDocument() | ||
}) | ||
|
||
test('should show placeholder message when there are no job distributors', async () => { | ||
renderComponent([]) | ||
|
||
expect( | ||
await findByText('Job Distributors have not been registered'), | ||
).toBeInTheDocument() | ||
}) | ||
|
||
test('should navigate to detail job distributor page when row is clicked', async () => { | ||
renderComponent([buildFeedsManager()]) | ||
|
||
userEvent.click(getByText(/chainlink feeds manager/i)) | ||
|
||
expect(await findByText('Edit Job Distributor Page')).toBeInTheDocument() | ||
}) | ||
}) |
Oops, something went wrong.