Skip to content

Commit

Permalink
Merge pull request #852 from Ekep-Obasi/feat/skip-cache-see-latest
Browse files Browse the repository at this point in the history
feat: add skip_cache param when tapping `See Latest` button
  • Loading branch information
Rassl authored Feb 4, 2024
2 parents 04208f8 + 165ee83 commit cdbb36d
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 25 deletions.
70 changes: 70 additions & 0 deletions src/components/App/SideBar/Latest/__test__/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { fireEvent, render, waitFor } from '@testing-library/react'
import * as React from 'react'
import { LatestView } from '..'
import { useDataStore } from '../../../../../stores/useDataStore'
import { useUserStore } from '../../../../../stores/useUserStore'

const mockedUseDataStore = useDataStore as jest.MockedFunction<typeof useDataStore>
const mockedUseUserStore = useUserStore as jest.MockedFunction<typeof useUserStore>

jest.mock('~/stores/useDataStore')
jest.mock('~/stores/useUserStore')

Object.defineProperty(window, 'matchMedia', {
writable: true,
value: jest.fn().mockImplementation((query) => ({
matches: false,
media: query,
onchange: null,
addListener: jest.fn(),
removeListener: jest.fn(),
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
})),
})

describe('LatestView Component', () => {
beforeEach(() => {
jest.clearAllMocks()
mockedUseDataStore.mockReturnValue([jest.fn()])
mockedUseUserStore.mockReturnValue([0, jest.fn(), jest.fn()])
})

test('renders button correctly when new data added', () => {
const { getByText } = render(<LatestView isSearchResult={false} />)
const galleryIcon = document.querySelector('.heading__icon') as Node

expect(getByText('Latest')).toBeInTheDocument()
expect(galleryIcon).toBeInTheDocument()
})

test('does not show the latest button when there are no nodes', () => {
mockedUseUserStore.mockReturnValue([0, jest.fn(), jest.fn()])

const { queryByText } = render(<LatestView isSearchResult={false} />)

expect(queryByText('See Latest (0)')).toBeNull()
})

test('calls latest endpoint with param on button click', async () => {
const fetchDataMock = jest.fn()

mockedUseDataStore.mockReturnValue([fetchDataMock])

const setNodeCountMock = jest.fn()

const setBudgetMock = jest.fn()

mockedUseUserStore.mockReturnValue([5, setNodeCountMock, setBudgetMock])

const { getByText } = render(<LatestView isSearchResult={false} />)

fireEvent.click(getByText('See Latest (5)'))

await waitFor(() => {
expect(fetchDataMock).toHaveBeenCalledWith(setBudgetMock, { skip_cache: 'true' })
expect(setNodeCountMock).toHaveBeenCalledWith('CLEAR')
})
})
})
6 changes: 3 additions & 3 deletions src/components/App/SideBar/Latest/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Button } from '@mui/material'
import { memo } from 'react'
import styled from 'styled-components'
import { Flex } from '~/components/common/Flex'
import BrowseGalleryIcon from '~/components/Icons/BrowseGalleryIcon'
import DownloadIcon from '~/components/Icons/DownloadIcon'
import { Flex } from '~/components/common/Flex'
import { useDataStore } from '~/stores/useDataStore'
import { useUserStore } from '~/stores/useUserStore'
import { colors } from '~/utils/colors'
Expand All @@ -16,14 +16,14 @@ type Props = {
// eslint-disable-next-line no-underscore-dangle
const _View = ({ isSearchResult }: Props) => {
const [nodeCount, setNodeCount, setBudget] = useUserStore((s) => [s.nodeCount, s.setNodeCount, s.setBudget])
const [fetchData] = [useDataStore((s) => s.fetchData)]
const [fetchData] = useDataStore((s) => [s.fetchData])

const getLatest = async () => {
if (nodeCount < 1) {
return
}

await fetchData(setBudget)
await fetchData(setBudget, { skip_cache: 'true' })
setNodeCount('CLEAR')
}

Expand Down
9 changes: 4 additions & 5 deletions src/components/App/SideBar/Relevance/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ export const Relevance = ({ isSearchResult }: Props) => {

const [setSelectedNode, setSelectedTimestamp] = useDataStore((s) => [s.setSelectedNode, s.setSelectedTimestamp])

const [setSidebarOpen] = useAppStore((s) => [s.setSidebarOpen])
const setRelevanceSelected = useAppStore((s) => s.setRelevanceSelected)
const [setSidebarOpen, setRelevanceSelected] = useAppStore((s) => [s.setSidebarOpen, s.setRelevanceSelected])

const [currentPage, setCurrentPage] = useState(0)

Expand All @@ -32,12 +31,12 @@ export const Relevance = ({ isSearchResult }: Props) => {
const startSlice = currentPage * pageSize
const endSlice = startSlice + pageSize

const hasNext = filteredNodes.length - 1 > endSlice
const hasNext = filteredNodes && filteredNodes.length > 0 ? filteredNodes.length - 1 > endSlice : false

const isMobile = useIsMatchBreakpoint('sm', 'down')

const currentNodes = useMemo(
() => [...filteredNodes].sort((a, b) => (b.date || 0) - (a.date || 0)).slice(0, endSlice),
() => filteredNodes && [...filteredNodes].sort((a, b) => (b.date || 0) - (a.date || 0)).slice(0, endSlice),
[filteredNodes, endSlice],
)

Expand All @@ -55,7 +54,7 @@ export const Relevance = ({ isSearchResult }: Props) => {
return (
<>
<ScrollView ref={scrollViewRef} id="search-result-list" shrink={1}>
{currentNodes.map((n, index) => {
{(currentNodes ?? []).map((n, index) => {
const {
image_url: imageUrl,
date,
Expand Down
2 changes: 1 addition & 1 deletion src/components/App/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export const App = () => {
})

const runSearch = useCallback(async () => {
await fetchData(setBudget, searchTerm)
await fetchData(setBudget, { word: searchTerm ?? '' })
setSidebarOpen(true)

if (searchTerm) {
Expand Down
31 changes: 20 additions & 11 deletions src/network/fetchGraphData/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
} from '~/constants'
import { mock } from '~/mocks/getMockGraphData/mockResponse'
import { api } from '~/network/api'
import { FetchNodeParams } from '~/stores/useDataStore'
import {
FetchDataResponse,
FetchSentimentResponse,
Expand Down Expand Up @@ -60,21 +61,29 @@ const shouldIncludeTopics = true
const maxScale = 26

export const fetchGraphData = async (
search: string,
graphStyle: 'split' | 'force' | 'sphere' | 'earth',
setBudget: (value: number | null) => void,
params: FetchNodeParams,
) => {
try {
return getGraphData(search, graphStyle, setBudget)
return getGraphData(graphStyle, setBudget, params)
} catch (e) {
return defaultData
}
}

const fetchNodes = async (search: string, setBudget: (value: number | null) => void): Promise<FetchDataResponse> => {
if (!search) {
const fetchNodes = async (
setBudget: (value: number | null) => void,
params: FetchNodeParams,
): Promise<FetchDataResponse> => {
const args = new URLSearchParams({
...(isDevelopment || isE2E ? { free: 'true' } : {}),
...params,
}).toString()

if (!params.word) {
try {
const response = await api.get<FetchDataResponse>(`/prediction/content/latest`)
const response = await api.get<FetchDataResponse>(`/prediction/content/latest?${args}`)

return response
} catch (e) {
Expand All @@ -85,15 +94,15 @@ const fetchNodes = async (search: string, setBudget: (value: number | null) => v
}

if (isDevelopment || isE2E) {
const response = await api.get<FetchDataResponse>(`/v2/search?word=${search}&free=true`)
const response = await api.get<FetchDataResponse>(`/v2/search?${args}`)

return response
}

const lsatToken = await getLSat()

try {
const response = await api.get<FetchDataResponse>(`/v2/search?word=${search}`, {
const response = await api.get<FetchDataResponse>(`/v2/search?${args}`, {
Authorization: lsatToken,
})

Expand All @@ -103,7 +112,7 @@ const fetchNodes = async (search: string, setBudget: (value: number | null) => v
if (error.status === 402) {
await payLsat(setBudget)

return fetchNodes(search, setBudget)
return fetchNodes(setBudget, params)
}

throw error
Expand Down Expand Up @@ -334,14 +343,14 @@ const generateGuestsMap = (
}

export const getGraphData = async (
searchterm: string,
graphStyle: 'split' | 'force' | 'sphere' | 'earth',
setBudget: (value: number | null) => void,
params: FetchNodeParams,
) => {
try {
const dataInit = await fetchNodes(searchterm, setBudget)
const dataInit = await fetchNodes(setBudget, params)

return formatFetchNodes(dataInit, searchterm, graphStyle)
return formatFetchNodes(dataInit, params?.word || '', graphStyle)
} catch (e) {
console.error(e)

Expand Down
16 changes: 11 additions & 5 deletions src/stores/useDataStore/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@ export type GraphStyle = 'sphere' | 'force' | 'split' | 'earth'

export const graphStyles: GraphStyle[] = ['sphere', 'force', 'split', 'earth']

type DataStore = {
export type FetchNodeParams = {
word?: string
skip_cache?: string
free?: string
}

export type DataStore = {
scrollEventsDisabled: boolean
categoryFilter: NodeType | null
disableCameraRotation: boolean
Expand Down Expand Up @@ -41,7 +47,7 @@ type DataStore = {
setScrollEventsDisabled: (scrollEventsDisabled: boolean) => void
setCategoryFilter: (categoryFilter: NodeType | null) => void
setDisableCameraRotation: (rotation: boolean) => void
fetchData: (setBudget: (value: number | null) => void, search?: string | null) => void
fetchData: (setBudget: (value: number | null) => void, params?: FetchNodeParams) => void
setData: (data: GraphData) => void
setGraphStyle: (graphStyle: GraphStyle) => void
setGraphRadius: (graphRadius?: number | null) => void
Expand Down Expand Up @@ -115,16 +121,16 @@ const defaultData: Omit<

export const useDataStore = create<DataStore>((set, get) => ({
...defaultData,
fetchData: async (setBudget, search) => {
fetchData: async (setBudget, params) => {
if (get().isFetching) {
return
}

set({ isFetching: true, sphinxModalIsOpen: true })

const data = await fetchGraphData(search || '', get().graphStyle, setBudget)
const data = await fetchGraphData(get().graphStyle, setBudget, params ?? {})

if (search) {
if (params?.word) {
await saveSearchTerm()
}

Expand Down

0 comments on commit cdbb36d

Please sign in to comment.