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

PORTALS-3308 - What's in Portals Component (GoalsV2) #1399

Draft
wants to merge 17 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 15 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React from 'react'
import { render, screen, fireEvent } from '@testing-library/react'
import '@testing-library/jest-dom'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import GoalsV2Desktop from './GoalsV2.Desktop'

const mockProps = {
asset: 'https://example.com/asset.jpg',
link: 'https://example.com',
countSql: 'SELECT COUNT(*) FROM syn12345',
title: 'Test Title',
summary: 'Test Summary',
}

const queryClient = new QueryClient()

describe('GoalsV2Desktop', () => {
test('renders the component with the correct props', () => {
render(
<QueryClientProvider client={queryClient}>
<GoalsV2Desktop {...mockProps} />
</QueryClientProvider>,
)

const image = screen.getByRole('img')
expect(image).toHaveAttribute('src', mockProps.asset)
expect(image).toHaveAttribute('alt', mockProps.title)

const title = screen.getByText(mockProps.title)
expect(title).toBeInTheDocument()
})

test('opens the link when the card is clicked', () => {
window.open = jest.fn()

render(
<QueryClientProvider client={queryClient}>
<GoalsV2Desktop {...mockProps} />
</QueryClientProvider>,
)

const card = screen.getByRole('button', { name: /Test Title/i })
fireEvent.click(card)

expect(window.open).toHaveBeenCalledWith(mockProps.link)
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React from 'react'
import { GoalsV2DataProps } from './GoalsV2'
import QueryCount from '../QueryCount/QueryCount'
import IconButton from '@mui/material/IconButton'
import NavigateNextIcon from '@mui/icons-material/NavigateNext'
import { Typography } from '@mui/material'
import { Card, CardActionArea, CardContent, CardMedia } from '@mui/material'

export default function GoalsV2Desktop({
asset,
link,
countSql,
title,
}: GoalsV2DataProps) {
return (
<Card
sx={{
width: 200,
height: 'auto',
backgroundColor: 'transparent',
borderColor: 'transparent',
boxShadow: 'none',
}}
>
<CardActionArea onClick={() => window.open(link)}>
<CardMedia
component="img"
sx={{ height: 150, width: '100%', paddingX: 2, overflow: 'visible' }}
image={asset}
alt={title}
/>
<CardContent
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<Typography variant="h6" component="strong" sx={{ marginRight: 1 }}>
{countSql && (
<QueryCount parens={false} query={{ sql: countSql }} />
)}
</Typography>
<Typography variant="body1">{title}</Typography>
<IconButton sx={{ color: '#5BA998' }}>
<NavigateNextIcon />
</IconButton>
</CardContent>
</CardActionArea>
</Card>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react'
import { GoalsV2DataProps } from './GoalsV2'
import ExpandableContent from '../home_page/ExpandableContent'
import QueryCount from '../QueryCount/QueryCount'
import { Button } from '@mui/material'

export default function GoalsV2Mobile({
link,
summary,
countSql,
title,
}: GoalsV2DataProps) {
const titleElement = (
<div className="GoalsV2__Mobile__Header">
{countSql && (
<span className="GoalsV2__Mobile__Header__Count">
<QueryCount parens={false} query={{ sql: countSql }} />
</span>
)}
<span className="GoalsV2__Mobile__Header__Title"> {title} </span>
</div>
)
const content = (
<div className="GoalsV2__Mobile__Content">
<p>{summary}</p>
<Button
variant="contained"
color="secondary"
className="GoalsV2__Mobile__Content__Link"
href={link}
>
Explore
</Button>
</div>
)
return <ExpandableContent title={titleElement} content={content} />
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Meta, StoryObj } from '@storybook/react'
import Goals from './GoalsV2'

const meta = {
title: 'Home Page/GoalsV2',
component: Goals,
parameters: {
chromatic: { viewports: [600, 1200] },
},
} satisfies Meta
export default meta
type Story = StoryObj<typeof meta>

export const Demo: Story = {
args: {
entityId: 'syn22315959',
},
}
114 changes: 114 additions & 0 deletions packages/synapse-react-client/src/components/GoalsV2/GoalsV2.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import React from 'react'
import { render, screen, waitFor } from '@testing-library/react'
import '@testing-library/jest-dom'
import { rest } from 'msw'
import { setupServer } from 'msw/node'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import GoalsV2 from './GoalsV2'
import {
SynapseContextProvider,
SynapseContextType,
} from '../../utils/context/SynapseContext'

const mockSynapseContext: Partial<SynapseContextType> = {
accessToken: 'mockAccessToken',
Fixed Show fixed Hide fixed
isInExperimentalMode: false,
utcTime: false,
withErrorBoundary: false,
downloadCartPageUrl: '/DownloadCart',
appId: undefined,
}

const queryClient = new QueryClient()

const server = setupServer(
rest.post(
'https://repo-prod.prod.sagebase.org/repo/v1/entity/:entityId/table/query/async/start',
(req, res, ctx) => {
return res(
ctx.json<{ token: string }>({
token: 'mockToken',
}),
)
},
),
rest.get(
'https://repo-prod.prod.sagebase.org/repo/v1/entity/:entityId/table/query/async/get/:token',
(req, res, ctx) => {
return res(
ctx.json({
queryResult: {
queryResults: {
rows: [
{
values: [
'syn22315959',
'SELECT COUNT(*) FROM syn22315959',
'Sample Title',
'Sample Summary',
'https://example.com',
'12345',
],
},
],
},
},
}),
)
},
),
)

beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
afterAll(() => server.close())

describe('GoalsV2', () => {
test('renders the component with provided props', async () => {
render(
<QueryClientProvider client={queryClient}>
<SynapseContextProvider synapseContext={mockSynapseContext}>
<GoalsV2 entityId="syn22315959" />
</SynapseContextProvider>
</QueryClientProvider>,
)

await waitFor(() => {
expect(screen.getByText("What's in the Portal?")).toBeInTheDocument()
})
})

// test('displays error message on fetch failure', async () => {
// server.use(
// rest.get('https://repo-prod.prod.sagebase.org/repo/v1/entity/:entityId/table/query/async/get/:token', (req, res, ctx) => {
// return res(ctx.status(500), ctx.json({ message: 'Internal Server Error' }))
// })
// )

// render(
// <QueryClientProvider client={queryClient}>
// <SynapseContextProvider synapseContext={mockSynapseContext}>
// <GoalsV2 entityId="syn22315959" />
// </SynapseContextProvider>
// </QueryClientProvider>
// )

// await waitFor(() => {
// expect(screen.getByText('Error: Internal Server Error')).toBeInTheDocument()
// })
// })

test('displays assets when fetch is successful', async () => {
render(
<QueryClientProvider client={queryClient}>
<SynapseContextProvider synapseContext={mockSynapseContext}>
<GoalsV2 entityId="syn22315959" />
</SynapseContextProvider>
</QueryClientProvider>,
)

await waitFor(() => {
expect(screen.getByText("What's in the Portal?")).toBeInTheDocument()
})
})
})
Loading
Loading