-
-
Notifications
You must be signed in to change notification settings - Fork 696
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 tests for dashboard script #3344
Merged
+306
−17
Merged
Changes from 14 commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
1e760df
draft PR
vishvamsinh28 7b7bcc7
Merge branch 'master' into dashboardTest
vishvamsinh28 d447661
initial test setup
vishvamsinh28 045150d
tests added
vishvamsinh28 1bf30ea
feqg
vishvamsinh28 3f5d340
Merge branch 'master' into dashboardTest
vishvamsinh28 c61c8a2
Merge branch 'dashboardTest' of https://github.com/vishvamsinh28/webs…
vishvamsinh28 d1fbc8b
95% coverage
vishvamsinh28 a97ce4f
tests updated
vishvamsinh28 9b6d95d
coverage 97%
vishvamsinh28 eeb8b79
coverage 100%
vishvamsinh28 08ba356
fixtures updated
vishvamsinh28 972e0a1
wfgfefg
vishvamsinh28 6ff849e
feewg
vishvamsinh28 abccd7f
fix tests
anshgoyalevil e091f5a
Merge branch 'master' into dashboardTest
anshgoyalevil ed64205
add error catch
anshgoyalevil 2d9dfca
Merge branch 'dashboardTest' of https://github.com/vishvamsinh28/webs…
anshgoyalevil File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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,198 @@ | ||
const { graphql } = require('@octokit/graphql'); | ||
const { promises: fs, mkdirSync, rmSync } = require('fs-extra'); | ||
const { resolve } = require('path'); | ||
const os = require('os'); | ||
const { | ||
getLabel, | ||
monthsSince, | ||
mapGoodFirstIssues, | ||
getHotDiscussions, | ||
getDiscussionByID, | ||
writeToFile, | ||
getDiscussions, | ||
start | ||
} = require('../../scripts/dashboard/build-dashboard'); | ||
|
||
const { | ||
issues, | ||
mockDiscussion, | ||
discussionWithMoreComments, | ||
fullDiscussionDetails, | ||
mockRateLimitResponse | ||
} = require("../fixtures/dashboardData") | ||
|
||
jest.mock('@octokit/graphql'); | ||
|
||
describe('GitHub Discussions Processing', () => { | ||
let tempDir; | ||
let consoleErrorSpy; | ||
let consoleLogSpy; | ||
|
||
beforeAll(() => { | ||
tempDir = resolve(os.tmpdir(), 'test-config'); | ||
mkdirSync(tempDir); | ||
}); | ||
|
||
afterAll(() => { | ||
rmSync(tempDir, { recursive: true, force: true }); | ||
}); | ||
|
||
beforeEach(() => { | ||
jest.clearAllMocks(); | ||
consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => { }); | ||
consoleLogSpy = jest.spyOn(console, 'log').mockImplementation(() => { }); | ||
}); | ||
|
||
afterEach(() => { | ||
consoleErrorSpy.mockRestore(); | ||
consoleLogSpy.mockRestore(); | ||
}); | ||
|
||
it('should fetch additional discussion details when comments have next page', async () => { | ||
graphql.mockResolvedValueOnce(fullDiscussionDetails); | ||
|
||
const result = await getHotDiscussions([discussionWithMoreComments]); | ||
|
||
expect(graphql).toHaveBeenCalledWith( | ||
expect.any(String), | ||
expect.objectContaining({ | ||
id: 'paginated-discussion', | ||
headers: expect.any(Object) | ||
}) | ||
); | ||
|
||
expect(result[0]).toMatchObject({ | ||
id: 'paginated-discussion', | ||
isPR: false, | ||
title: 'Test with Pagination' | ||
}); | ||
|
||
const firstResult = result[0]; | ||
expect(firstResult.score).toBeGreaterThan(0); | ||
}); | ||
|
||
it('should handle rate limit warnings', async () => { | ||
graphql.mockResolvedValueOnce(mockRateLimitResponse); | ||
|
||
await getDiscussions('test-query', 10); | ||
|
||
expect(consoleLogSpy).toHaveBeenCalledWith( | ||
'[WARNING] GitHub GraphQL rateLimit', | ||
'cost = 1', | ||
'limit = 5000', | ||
'remaining = 50', | ||
expect.any(String) | ||
); | ||
}); | ||
|
||
it('should handle pagination', async () => { | ||
const mockFirstResponse = { | ||
search: { | ||
nodes: [mockDiscussion], | ||
pageInfo: { hasNextPage: true, endCursor: 'cursor1' } | ||
}, | ||
rateLimit: { remaining: 1000 } | ||
}; | ||
|
||
const mockSecondResponse = { | ||
search: { | ||
nodes: [{ ...mockDiscussion, id: 'test-id-2' }], | ||
pageInfo: { hasNextPage: false } | ||
}, | ||
rateLimit: { remaining: 1000 } | ||
}; | ||
|
||
graphql | ||
.mockResolvedValueOnce(mockFirstResponse) | ||
.mockResolvedValueOnce(mockSecondResponse); | ||
|
||
const result = await getDiscussions('test-query', 10); | ||
expect(result).toHaveLength(2); | ||
}); | ||
|
||
it('should handle complete failure', async () => { | ||
graphql.mockRejectedValue(new Error('Complete API failure')); | ||
|
||
const filePath = resolve(tempDir, 'error-output.json'); | ||
await start(filePath); | ||
|
||
expect(consoleLogSpy).toHaveBeenCalledWith('There were some issues parsing data from github.'); | ||
}); | ||
|
||
it('should successfully process and write data', async () => { | ||
graphql.mockResolvedValue(mockRateLimitResponse); | ||
|
||
const filePath = resolve(tempDir, 'success-output.json'); | ||
await start(filePath); | ||
|
||
const content = JSON.parse(await fs.readFile(filePath, 'utf-8')); | ||
expect(content).toHaveProperty('hotDiscussions'); | ||
expect(content).toHaveProperty('goodFirstIssues'); | ||
}); | ||
|
||
it('should get labels correctly', () => { | ||
const issue = { | ||
labels: { nodes: [{ name: 'area/bug' }, { name: 'good first issue' }] } | ||
}; | ||
expect(getLabel(issue, 'area/')).toBe('bug'); | ||
expect(getLabel(issue, 'nonexistent/')).toBeUndefined(); | ||
}); | ||
|
||
it('should calculate months since date', () => { | ||
const date = new Date(); | ||
date.setMonth(date.getMonth() - 2); | ||
expect(monthsSince(date)).toBe(2); | ||
}); | ||
|
||
it('should map good first issues', async () => { | ||
|
||
const result = await mapGoodFirstIssues(issues); | ||
expect(result[0]).toMatchObject({ | ||
id: '1', | ||
area: 'docs' | ||
}); | ||
}); | ||
|
||
it('should handle discussion retrieval', async () => { | ||
graphql.mockResolvedValueOnce({ node: mockDiscussion }); | ||
const result = await getDiscussionByID(false, 'test-id'); | ||
expect(result.node).toBeDefined(); | ||
|
||
graphql.mockRejectedValueOnce(new Error('API error')); | ||
await expect(getDiscussionByID(true, 'test-id')).rejects.toThrow(); | ||
}); | ||
|
||
it('should process hot discussions', async () => { | ||
const prDiscussion = { | ||
...mockDiscussion, | ||
__typename: 'PullRequest', | ||
reviews: { | ||
totalCount: 1, | ||
nodes: [{ comments: { totalCount: 1 } }] | ||
} | ||
}; | ||
|
||
const result = await getHotDiscussions([mockDiscussion, prDiscussion]); | ||
expect(result.length).toBeLessThanOrEqual(12); | ||
}); | ||
|
||
it('should write to file', async () => { | ||
const filePath = resolve(tempDir, 'test.json'); | ||
await writeToFile({ test: true }, filePath); | ||
const content = JSON.parse(await fs.readFile(filePath, 'utf-8')); | ||
expect(content).toEqual({ test: true }); | ||
}); | ||
|
||
it('should handle parsing errors in processHotDiscussions', async () => { | ||
const consoleErrorSpy = jest.spyOn(console, 'error'); | ||
|
||
await expect(getHotDiscussions([undefined])).rejects.toThrow(); | ||
|
||
expect(consoleErrorSpy).toHaveBeenCalledWith( | ||
'there was some issues while parsing this item: undefined' | ||
); | ||
|
||
consoleErrorSpy.mockRestore(); | ||
}); | ||
anshgoyalevil marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
}); |
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,81 @@ | ||
const mockDiscussion = { | ||
id: 'test-id', | ||
__typename: 'Issue', | ||
title: 'Test', | ||
author: { login: 'author' }, | ||
resourcePath: '/path', | ||
repository: { name: 'repo' }, | ||
assignees: { totalCount: 0 }, | ||
reactions: { totalCount: 5 }, | ||
comments: { | ||
totalCount: 2, | ||
nodes: [{ reactions: { totalCount: 1 } }], | ||
pageInfo: { hasNextPage: false } | ||
}, | ||
labels: { nodes: [] }, | ||
timelineItems: { updatedAt: new Date().toISOString() } | ||
}; | ||
|
||
const discussionWithMoreComments = { | ||
id: 'paginated-discussion', | ||
__typename: 'Issue', | ||
title: 'Test with Pagination', | ||
author: { login: 'author' }, | ||
resourcePath: '/path', | ||
repository: { name: 'repo' }, | ||
assignees: { totalCount: 0 }, | ||
reactions: { totalCount: 5 }, | ||
comments: { | ||
totalCount: 5, | ||
nodes: [{ reactions: { totalCount: 1 } }], | ||
pageInfo: { hasNextPage: true } | ||
}, | ||
labels: { nodes: [] }, | ||
timelineItems: { updatedAt: new Date().toISOString() } | ||
}; | ||
|
||
const fullDiscussionDetails = { | ||
node: { | ||
...discussionWithMoreComments, | ||
comments: { | ||
totalCount: 5, | ||
nodes: [ | ||
{ reactions: { totalCount: 1 } }, | ||
{ reactions: { totalCount: 2 } }, | ||
{ reactions: { totalCount: 3 } } | ||
], | ||
pageInfo: { hasNextPage: false } | ||
} | ||
} | ||
}; | ||
|
||
const mockRateLimitResponse = { | ||
search: { | ||
nodes: [mockDiscussion], | ||
pageInfo: { hasNextPage: false } | ||
}, | ||
rateLimit: { | ||
cost: 1, | ||
limit: 5000, | ||
remaining: 50, | ||
resetAt: new Date().toISOString() | ||
} | ||
}; | ||
|
||
const issues = [{ | ||
id: '1', | ||
title: 'Test', | ||
assignees: { totalCount: 1 }, | ||
resourcePath: '/path', | ||
repository: { name: 'repo' }, | ||
author: { login: 'author' }, | ||
labels: { nodes: [{ name: 'area/docs' }] } | ||
}]; | ||
|
||
module.exports = { | ||
issues, | ||
mockDiscussion, | ||
discussionWithMoreComments, | ||
fullDiscussionDetails, | ||
mockRateLimitResponse | ||
}; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add error handling to writeToFile function.
The function should handle potential file system errors gracefully.
Add error handling:
📝 Committable suggestion