Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add enable and disable feed manager queries #92

Merged
merged 5 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/eight-parents-leave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@smartcontractkit/operator-ui': minor
---

#added Enable and Disable Feeds Manager mutations
1 change: 1 addition & 0 deletions src/hooks/queries/useFeedsManagerWithProposalsQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export const FEEDS_MANAGER_FIELDS = gql`
uri
publicKey
isConnectionActive
disabledAt
chainConfigs {
...FeedsManager_ChainConfigFields
}
Expand Down
1 change: 1 addition & 0 deletions src/hooks/queries/useFeedsManagersQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const FEEDS_MANAGERS_QUERY = gql`
publicKey
isConnectionActive
createdAt
disabledAt
}
query FetchFeedsManagers {
feedsManagers {
Expand Down
60 changes: 55 additions & 5 deletions src/screens/FeedsManager/FeedsManagerCard.test.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
import * as React from 'react'

import userEvent from '@testing-library/user-event'
import { Route } from 'react-router-dom'
import { renderWithRouter, screen } from 'support/test-utils'
import userEvent from '@testing-library/user-event'

import { FeedsManagerCard } from './FeedsManagerCard'
import { buildFeedsManagerFields } from 'support/factories/gql/fetchFeedsManagersWithProposals'
import { shortenHex } from 'src/utils/shortenHex'
import { buildFeedsManagerFields } from 'support/factories/gql/fetchFeedsManagersWithProposals'
import { FeedsManagerCard } from './FeedsManagerCard'

const { getByRole, queryByText } = screen

function renderComponent(manager: FeedsManagerFields) {
function renderComponent(
manager: FeedsManagerFields,
onEnable = () => {},
onDisable = () => {},
) {
renderWithRouter(
<>
<Route path="/">
<FeedsManagerCard manager={manager} />
<FeedsManagerCard
manager={manager}
onDisable={onDisable}
onEnable={onEnable}
/>
</Route>
<Route path={`/job_distributors/${manager.id}/edit`}>
Redirect Success
Expand All @@ -33,6 +41,19 @@ describe('FeedsManagerCard', () => {
expect(queryByText(mgr.uri)).toBeInTheDocument()
expect(queryByText(shortenHex(mgr.publicKey))).toBeInTheDocument()
expect(queryByText('Disconnected')).toBeInTheDocument()
expect(queryByText('Disabled')).toBeInTheDocument()
})

it('renders an enabled Feeds Manager', () => {
const mgr = buildFeedsManagerFields({ disabledAt: null })

renderComponent(mgr)

expect(queryByText(mgr.name)).toBeInTheDocument()
expect(queryByText(mgr.uri)).toBeInTheDocument()
expect(queryByText(shortenHex(mgr.publicKey))).toBeInTheDocument()
expect(queryByText('Disconnected')).toBeInTheDocument()
expect(queryByText('Enabled')).toBeInTheDocument()
})

it('renders a connected boostrapper Feeds Manager', () => {
Expand All @@ -48,6 +69,7 @@ describe('FeedsManagerCard', () => {
expect(queryByText(shortenHex(mgr.publicKey))).toBeInTheDocument()
expect(queryByText('Flux Monitor')).toBeNull()
expect(queryByText('Connected')).toBeInTheDocument()
expect(queryByText('Disabled')).toBeInTheDocument()
})

it('navigates to edit', () => {
Expand All @@ -58,4 +80,32 @@ describe('FeedsManagerCard', () => {

expect(queryByText('Redirect Success')).toBeInTheDocument()
})

it('calls onEnable when enable menu item is clicked', () => {
const onEnableMock = jest.fn()
const onDisableMock = jest.fn()

const mgr = buildFeedsManagerFields({ disabledAt: new Date() })

renderComponent(mgr, onEnableMock, onDisableMock)

userEvent.click(screen.getByRole('button', { name: /open-menu/i }))
userEvent.click(screen.getByRole('menuitem', { name: /enable/i }))

expect(onEnableMock).toHaveBeenCalledTimes(1)
})

it('calls onDisable when disable menu item is clicked', () => {
const onEnableMock = jest.fn()
const onDisableMock = jest.fn()

const mgr = buildFeedsManagerFields({ disabledAt: null })
renderComponent(mgr, onEnableMock, onDisableMock)

userEvent.click(screen.getByRole('button', { name: /open-menu/i }))

userEvent.click(screen.getByRole('menuitem', { name: /disable/i }))

expect(onDisableMock).toHaveBeenCalledTimes(1)
})
})
44 changes: 41 additions & 3 deletions src/screens/FeedsManager/FeedsManagerCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import IconButton from '@material-ui/core/IconButton'
import ListItemIcon from '@material-ui/core/ListItemIcon'
import ListItemText from '@material-ui/core/ListItemText'
import Menu from '@material-ui/core/Menu'
import MenuItem from '@material-ui/core/MenuItem'
import EditIcon from '@material-ui/icons/Edit'
import MoreVertIcon from '@material-ui/icons/MoreVert'
import ToggleOffIcon from '@material-ui/icons/ToggleOff'
import ToggleOnIcon from '@material-ui/icons/ToggleOn'

import {
DetailsCard,
Expand All @@ -16,13 +19,15 @@ import {
import { CopyIconButton } from 'src/components/Copy/CopyIconButton'
import { MenuItemLink } from 'src/components/MenuItemLink'
import { shortenHex } from 'src/utils/shortenHex'
import { ConnectionStatus } from './ConnectionStatus'
import { StatusIndicator } from './StatusIndicator'

interface Props {
manager: FeedsManagerFields
onEnable: () => void
onDisable: () => void
}

export const FeedsManagerCard = ({ manager }: Props) => {
export const FeedsManagerCard = ({ manager, onEnable, onDisable }: Props) => {
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null)

const handleOpen = (event: React.MouseEvent<HTMLButtonElement>) => {
Expand All @@ -33,6 +38,15 @@ export const FeedsManagerCard = ({ manager }: Props) => {
setAnchorEl(null)
}

const handleToggleEnabled = () => {
if (manager.disabledAt) {
onEnable()
} else {
onDisable()
}
handleClose()
}

return (
<DetailsCard
actions={
Expand All @@ -51,14 +65,38 @@ export const FeedsManagerCard = ({ manager }: Props) => {
</ListItemIcon>
<ListItemText>Edit</ListItemText>
</MenuItemLink>
<MenuItem onClick={handleToggleEnabled}>
<ListItemIcon>
{manager.disabledAt ? (
<ToggleOnIcon style={{ color: 'green' }} />
) : (
<ToggleOffIcon style={{ color: 'gray' }} />
)}
</ListItemIcon>
<ListItemText>
{manager.disabledAt ? 'Enable' : 'Disable'}
</ListItemText>
</MenuItem>
</Menu>
</div>
}
>
<Grid container>
<Grid item xs={12} sm={6} md={3}>
<DetailsCardItemTitle title="Connection Status" />
<StatusIndicator
isActive={manager.isConnectionActive}
activeText="Connected"
inactiveText="Disconnected"
/>
</Grid>
<Grid item xs={12} sm={6} md={3}>
<DetailsCardItemTitle title="Status" />
<ConnectionStatus isConnected={manager.isConnectionActive} />
<StatusIndicator
isActive={!manager.disabledAt}
activeText="Enabled"
inactiveText="Disabled"
/>
</Grid>
<Grid item xs={12} sm={6} md={3}>
<DetailsCardItemTitle title="Name" />
Expand Down
74 changes: 68 additions & 6 deletions src/screens/FeedsManager/FeedsManagerScreen.test.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
import * as React from 'react'

import { MockedProvider, MockedResponse } from '@apollo/client/testing'
import { GraphQLError } from 'graphql'
import { Route, Switch } from 'react-router-dom'
import { renderWithRouter, screen } from 'support/test-utils'
import { MockedProvider, MockedResponse } from '@apollo/client/testing'
import { renderWithRouter, screen, waitFor } from 'support/test-utils'

import { FeedsManagerScreen } from './FeedsManagerScreen'
import { buildFeedsManagerResultFields } from 'support/factories/gql/fetchFeedsManagersWithProposals'
import userEvent from '@testing-library/user-event'
import { FEEDS_MANAGER_WITH_PROPOSALS_QUERY } from 'src/hooks/queries/useFeedsManagerWithProposalsQuery'

const { findByText, findByTestId } = screen
import { buildFeedsManager } from 'support/factories/gql/fetchFeedsManagers'
import { buildFeedsManagerResultFields } from 'support/factories/gql/fetchFeedsManagersWithProposals'
import {
ENABLE_FEEDS_MANAGER_MUTATION,
FeedsManagerScreen,
} from './FeedsManagerScreen'

const {
findByText,
findByTestId,
getByRole,
getByText,
getAllByRole,
queryByText,
} = screen

function renderComponent(mocks: MockedResponse[]) {
renderWithRouter(
Expand Down Expand Up @@ -52,6 +64,56 @@ describe('FeedsManagerScreen', () => {
expect(await findByText('Job Proposals')).toBeInTheDocument()
})

it('should enable a feed', async () => {
const id = '1'
const mocks: MockedResponse[] = [
{
request: {
query: FEEDS_MANAGER_WITH_PROPOSALS_QUERY,
variables: { id },
},
result: {
data: {
feedsManager: buildFeedsManagerResultFields(),
},
},
},
{
request: {
query: ENABLE_FEEDS_MANAGER_MUTATION,
variables: { id },
},
result: {
data: {
enableFeedsManager: {
feedsManager: buildFeedsManager({
disabledAt: null,
}),
__typename: 'EnableFeedsManagerSuccess',
},
},
},
},
]

renderComponent(mocks)

expect(await findByText('Job Distributors')).toBeInTheDocument()
expect(await findByText('Job Proposals')).toBeInTheDocument()
expect(await findByText('Disabled')).toBeInTheDocument()
expect(await queryByText('Enabled')).not.toBeInTheDocument()

const openMenuButtons = await getAllByRole('button', {
name: /open-menu/i,
})
userEvent.click(openMenuButtons[0])
userEvent.click(await getByRole('menuitem', { name: /enable/i }))
await waitFor(() => {
expect(getByText('Enabled')).toBeInTheDocument()
})
expect(await queryByText('Disabled')).not.toBeInTheDocument()
})

it('should render not found page when a manager is not found', async () => {
const mocks: MockedResponse[] = [
{
Expand Down
Loading
Loading