-
-
Notifications
You must be signed in to change notification settings - Fork 409
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add API for research search (#3987)
- Loading branch information
Showing
8 changed files
with
437 additions
and
268 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 |
---|---|---|
@@ -0,0 +1,41 @@ | ||
describe('[Research - List Articles]', () => { | ||
const researchPageUrl = '/research' | ||
|
||
beforeEach(() => { | ||
cy.visit(researchPageUrl) | ||
}) | ||
|
||
it('[By Everyone - Lists all research articles]', () => { | ||
cy.step('Verify page loads with research articles') | ||
cy.get('[data-cy=ResearchList]').should('be.visible') | ||
cy.get('[data-cy=ResearchListItem]').should('have.length.greaterThan', 0) | ||
}) | ||
|
||
it('[Search Functionality - Filters articles]', () => { | ||
const searchTerm = 'test' | ||
|
||
cy.step('Type a keyword into the search bar') | ||
cy.get('[data-cy=research-search-box]').clear().type(searchTerm) | ||
|
||
cy.step('Verify filtered results are displayed') | ||
cy.get('[data-cy=ResearchListItem]').should('have.length.at.least', 1) | ||
}) | ||
|
||
it('[Pagination - Displays additional articles]', () => { | ||
cy.step('Verify pagination is visible') | ||
let itemCount | ||
cy.get('[data-cy=ResearchListItem]').then((items) => { | ||
itemCount = items.length | ||
}) | ||
cy.get('[data-cy=loadMoreButton]').should('be.visible') | ||
cy.get('[data-cy=loadMoreButton]').click() | ||
|
||
cy.step('Verify additional articles are loaded') | ||
cy.then(() => { | ||
cy.get('[data-cy=ResearchListItem]').should( | ||
'have.length.greaterThan', | ||
itemCount, | ||
) | ||
}) | ||
}) | ||
}) |
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
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,120 +1,109 @@ | ||
import '@testing-library/jest-dom/vitest' | ||
|
||
import { ResearchStatus } from 'oa-shared' | ||
import { describe, expect, it, vi } from 'vitest' | ||
|
||
import { exportedForTesting } from './research.service' | ||
|
||
const mockWhere = vi.fn() | ||
const mockOrderBy = vi.fn() | ||
const mockLimit = vi.fn() | ||
vi.mock('firebase/firestore', () => ({ | ||
collection: vi.fn(), | ||
query: vi.fn(), | ||
and: vi.fn(), | ||
where: (path, op, value) => mockWhere(path, op, value), | ||
limit: (limit) => mockLimit(limit), | ||
orderBy: (field, direction) => mockOrderBy(field, direction), | ||
})) | ||
|
||
vi.mock('../../stores/databaseV2/endpoints', () => ({ | ||
DB_ENDPOINTS: { | ||
research: 'research', | ||
researchCategories: 'researchCategories', | ||
}, | ||
})) | ||
|
||
vi.mock('../../config/config', () => ({ | ||
getConfigurationOption: vi.fn(), | ||
FIREBASE_CONFIG: { | ||
apiKey: 'AIyChVN', | ||
databaseURL: 'https://test.firebaseio.com', | ||
projectId: 'test', | ||
storageBucket: 'test.appspot.com', | ||
}, | ||
localStorage: vi.fn(), | ||
SITE: 'unit-tests', | ||
})) | ||
|
||
describe('research.search', () => { | ||
it('searches for text', () => { | ||
// prepare | ||
const words = ['test', 'text'] | ||
|
||
// act | ||
exportedForTesting.createSearchQuery(words, '', 'MostRelevant', null) | ||
|
||
// assert | ||
expect(mockWhere).toHaveBeenCalledWith( | ||
'keywords', | ||
'array-contains-any', | ||
words, | ||
) | ||
import { researchService } from './research.service' | ||
|
||
describe('research.service', () => { | ||
describe('search', () => { | ||
it('fetches research articles based on search criteria', async () => { | ||
// Mock successful fetch response | ||
global.fetch = vi.fn().mockResolvedValue({ | ||
json: () => | ||
Promise.resolve({ | ||
items: [{ id: '1', title: 'Sample Research' }], | ||
total: 1, | ||
}), | ||
}) | ||
|
||
// Call search with mock parameters | ||
const result = await researchService.search( | ||
['sample'], | ||
'science', | ||
'Newest', | ||
null, | ||
) | ||
|
||
// Assert results | ||
expect(result).toEqual({ | ||
items: [{ id: '1', title: 'Sample Research' }], | ||
total: 1, | ||
}) | ||
}) | ||
|
||
it('handles errors in search', async () => { | ||
global.fetch = vi.fn().mockRejectedValue('error') | ||
|
||
const result = await researchService.search( | ||
['sample'], | ||
'science', | ||
'Newest', | ||
null, | ||
) | ||
|
||
expect(result).toEqual({ items: [], total: 0 }) | ||
}) | ||
}) | ||
|
||
it('filters by category', () => { | ||
// prepare | ||
const category = 'cat1' | ||
describe('getResearchCategories', () => { | ||
it('fetches research categories', async () => { | ||
global.fetch = vi.fn().mockResolvedValue({ | ||
json: () => | ||
Promise.resolve({ categories: [{ id: 'cat1', name: 'Science' }] }), | ||
}) | ||
|
||
// act | ||
exportedForTesting.createSearchQuery([], category, 'MostRelevant', null) | ||
const result = await researchService.getResearchCategories() | ||
|
||
// assert | ||
expect(mockWhere).toHaveBeenCalledWith( | ||
'researchCategory._id', | ||
'==', | ||
category, | ||
) | ||
}) | ||
expect(result).toEqual([{ id: 'cat1', name: 'Science' }]) | ||
}) | ||
|
||
it('handles errors in fetching research categories', async () => { | ||
global.fetch = vi.fn().mockRejectedValue('error') | ||
|
||
it('should not call orderBy if sorting by most relevant', () => { | ||
// act | ||
exportedForTesting.createSearchQuery(['test'], '', 'MostRelevant', null) | ||
const result = await researchService.getResearchCategories() | ||
|
||
// assert | ||
expect(mockOrderBy).toHaveBeenCalledTimes(0) | ||
expect(result).toEqual([]) | ||
}) | ||
}) | ||
|
||
it('should call orderBy when sorting is not MostRelevant', () => { | ||
// act | ||
exportedForTesting.createSearchQuery(['test'], '', 'Newest', null) | ||
describe('getDraftCount', () => { | ||
it('fetches draft count for a user', async () => { | ||
global.fetch = vi.fn().mockResolvedValue({ | ||
json: () => Promise.resolve({ total: 5 }), | ||
}) | ||
|
||
// assert | ||
expect(mockOrderBy).toHaveBeenLastCalledWith('_created', 'desc') | ||
}) | ||
const result = await researchService.getDraftCount('user123') | ||
|
||
expect(result).toBe(5) | ||
}) | ||
|
||
it('handles errors in fetching draft count', async () => { | ||
global.fetch = vi.fn().mockRejectedValue('error') | ||
|
||
it('should filter by research status', () => { | ||
// act | ||
exportedForTesting.createSearchQuery( | ||
['test'], | ||
'', | ||
'Newest', | ||
ResearchStatus.COMPLETED, | ||
) | ||
|
||
// assert | ||
expect(mockWhere).toHaveBeenCalledWith( | ||
'researchStatus', | ||
'==', | ||
ResearchStatus.COMPLETED, | ||
) | ||
const result = await researchService.getDraftCount('user123') | ||
|
||
expect(result).toBe(0) | ||
}) | ||
}) | ||
|
||
it('should limit results', () => { | ||
// prepare | ||
const take = 12 | ||
|
||
// act | ||
exportedForTesting.createSearchQuery( | ||
['test'], | ||
'', | ||
'Newest', | ||
null, | ||
undefined, | ||
take, | ||
) | ||
|
||
// assert | ||
expect(mockLimit).toHaveBeenLastCalledWith(take) | ||
describe('getDrafts', () => { | ||
it('fetches research drafts for a user', async () => { | ||
global.fetch = vi.fn().mockResolvedValue({ | ||
json: () => | ||
Promise.resolve({ | ||
items: [{ id: 'draft1', title: 'Draft Research' }], | ||
}), | ||
}) | ||
|
||
const result = await researchService.getDrafts('user123') | ||
|
||
expect(result).toEqual([{ id: 'draft1', title: 'Draft Research' }]) | ||
}) | ||
|
||
it('handles errors in fetching drafts', async () => { | ||
global.fetch = vi.fn().mockRejectedValue('error') | ||
|
||
const result = await researchService.getDrafts('user123') | ||
|
||
expect(result).toEqual([]) | ||
}) | ||
}) | ||
}) |
Oops, something went wrong.