Skip to content

Conversation

@flychen50
Copy link
Owner

Adds extensive unit tests for bootstrap.js, preferences.js, and zoterocitationcounts.js.

  • Creates new test file test/unit/bootstrap.test.js to test the plugin lifecycle functions.
  • Creates new test file test/unit/preferences.test.js to test the preferences pane UI logic.
  • Adds a new UI Logic test suite to test/unit/zoterocitationcounts.test.js.
  • Adds many new tests for edge cases to improve branch coverage.

This brings line, function, and statement coverage to over 80%.

Adds extensive unit tests for `bootstrap.js`, `preferences.js`, and `zoterocitationcounts.js`.

- Creates new test file `test/unit/bootstrap.test.js` to test the plugin lifecycle functions.
- Creates new test file `test/unit/preferences.test.js` to test the preferences pane UI logic.
- Adds a new UI Logic test suite to `test/unit/zoterocitationcounts.test.js`.
- Adds many new tests for edge cases to improve branch coverage.

This brings line, function, and statement coverage to over 80%.
@claude
Copy link
Contributor

claude bot commented Aug 19, 2025

Claude finished @flychen50's task —— View job


PR Review: Test Coverage Improvements

I've completed my review of this PR which adds extensive unit tests for the Zotero Citation Counts plugin.

Review Tasks:

  • Read and analyze new test files
  • Review test structure and mocking strategies
  • Check edge case coverage and completeness
  • Evaluate potential issues and improvements
  • Provide comprehensive feedback

Overall Assessment

This is a well-structured PR that significantly improves test coverage by adding comprehensive unit tests for the core components. The tests are well-written and follow good testing practices.

Strengths

Excellent Test Architecture

  • Creative bootstrap.js testing: The use of Node.js vm module to test the bootstrap script in isolation is clever and well-executed (bootstrap.test.js:58-71)
  • Comprehensive mocking: All Zotero APIs are properly mocked with appropriate stubs and spies
  • Systematic coverage: Each core function has dedicated test suites with edge cases

Thorough Edge Case Testing

  • Error prioritization testing: Excellent coverage of the complex error hierarchy in _retrieveCitationCount (zoterocitationcounts.test.js:345-457)
  • HTTP status code coverage: Comprehensive testing of different API error scenarios (zoterocitationcounts.test.js:236-282)
  • Data validation: Good coverage of malformed/missing data scenarios

Good Testing Practices

  • Proper test isolation: Each test properly sets up and tears down its environment
  • Sinon integration: Effective use of stubs, spies, and fake timers
  • Async testing: Proper handling of promises and async functions

Areas for Improvement

Code Quality Issues

  1. Inconsistent variable declaration (bootstrap.test.js:11):

    const bootstrapCodeModified = bootstrapCode.replace('let ZoteroCitationCounts, itemObserver;', 'var ZoteroCitationCounts, itemObserver;');

    This string replacement is fragile. Consider a more robust approach or document why this is necessary.

  2. Commented code blocks (zoterocitationcounts.test.js:50-52):

    // ... (keep existing _getDoi, getCitationCount, _setCitationCount, _getArxiv, _getItemMetadataForAdsQuery, UI Logic tests as they are good) ...

    These comments suggest incomplete refactoring. Either include the referenced tests or remove the comments.

Test Structure Concerns

  1. Skipped test without resolution (zoterocitationcounts.test.js:893):

    // TODO: This test is skipped because of an intractable issue with async functions and sinon.useFakeTimers().
    it.skip('should not wait if rate limit preference is 0', function(done) {

    This indicates incomplete test coverage for an important edge case.

  2. Complex setup in individual tests (zoterocitationcounts.test.js:466-491):
    The progress window mocking setup is repeated and complex. Consider extracting to a shared helper.

Security & Best Practices

  1. Potential test data exposure: Some tests use realistic-looking API keys like 'TEST_NASA_KEY' which is fine for tests, but ensure no real credentials are used.

  2. File system operations: The tests read actual source files which creates coupling between test and source structure. This is generally acceptable but worth noting.

Specific Technical Issues

URL Construction Coverage

The URL builder tests for different APIs are comprehensive, but some edge cases around encoding could be better covered:

// Consider adding tests for special characters in titles/authors
const metadata = { title: 'Test & Title "with quotes"', author: 'O\'Reilly' };

Async Test Handling

Some async tests could benefit from more explicit timeout handling:

it('should handle network timeout gracefully', async function() {
  this.timeout(5000); // Explicit timeout
  // test implementation
});

Performance Considerations

  • The extensive mocking setup is necessary but adds test execution time
  • Consider grouping related tests to share setup where possible
  • The VM context creation for bootstrap tests adds overhead but is justified

Coverage Analysis

Based on the test structure, this PR appears to achieve the stated goal of >80% coverage by:

  • Testing all major functions in zoterocitationcounts.js
  • Covering the complete bootstrap lifecycle
  • Testing UI injection logic in preferences

Recommendations

High Priority

  1. Fix the skipped test or document why it can't be implemented
  2. Remove commented placeholder code and ensure all referenced tests are included
  3. Add explicit timeouts to async tests that could hang

Medium Priority

  1. Extract common test setup into shared helpers
  2. Add more encoding edge cases for URL builders
  3. Consider testing error message localization more thoroughly

Low Priority

  1. Document the bootstrap.js string replacement approach
  2. Consider using test fixtures for complex mock data

Security Assessment

✅ No security concerns identified. The tests properly mock external APIs and don't expose sensitive data.

Conclusion

This is a high-quality PR that significantly improves the project's test coverage. The testing approach is sophisticated and the coverage appears comprehensive. The identified issues are mostly about code organization and completeness rather than fundamental problems.

Recommendation: Approve with suggested improvements

The PR achieves its primary goal of meeting CI coverage requirements while maintaining good test quality. The suggested improvements can be addressed in follow-up PRs if needed.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary of Changes

Hello @flychen50, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the test coverage of the Zotero Citation Counts plugin by introducing new unit tests and expanding existing ones. The primary goal is to meet continuous integration requirements by bringing line, function, and statement coverage to over 80%.

Highlights

  • New Test Suites: Introduces dedicated unit test files for bootstrap.js (plugin lifecycle) and preferences.js (UI logic for preferences).
  • Expanded zoterocitationcounts.js Tests: Adds a new UI Logic test suite and extends existing tests for core functionalities like getCitationCount, _setCitationCount, _getItemMetadataForAdsQuery, and URL generation methods (_semanticScholarUrl, _nasaadsUrl).
  • Improved Edge Case Coverage: Includes numerous new tests to cover various edge cases and branch conditions, ensuring robustness of the codebase.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request significantly increases the test coverage for the project by adding extensive unit tests for bootstrap.js, preferences.js, and zoterocitationcounts.js. The new tests are well-structured and cover many important code paths and edge cases, which is a great improvement for the project's stability.

I've found a couple of minor maintainability issues in the new tests for zoterocitationcounts.js where some test cases have duplicated descriptions. Making these descriptions unique would improve clarity when debugging. Please see the detailed comments.

Comment on lines +668 to +714
it('should construct URL for author and year only to cover branch', function() {
const metadata = { author: 'Smith', year: '2024' };
const result = global.ZoteroCitationCounts._semanticScholarUrl(metadata, 'title_author_year');
expect(result).to.not.include('title');
expect(result).to.include('author%3ASmith');
expect(result).to.include('%2Byear%3A2024'); // Check for the '+' separator
});

it('should construct URL for title and year only to cover branch', function() {
const metadata = { title: 'Test Paper', year: '2024' };
const result = global.ZoteroCitationCounts._semanticScholarUrl(metadata, 'title_author_year');
expect(result).to.include('title%3ATest%2520Paper');
expect(result).to.not.include('author');
expect(result).to.include('%2Byear%3A2024');
});

it('should construct URL for author only to cover branch', function() {
const metadata = { author: 'Smith' };
const result = global.ZoteroCitationCounts._semanticScholarUrl(metadata, 'title_author_year');
expect(result).to.include('author%3ASmith');
expect(result).to.not.include('title');
expect(result).to.not.include('year');
});

it('should construct URL for author and year only to cover branch', function() {
const metadata = { title: null, author: 'Smith', year: '2024' };
const result = global.ZoteroCitationCounts._semanticScholarUrl(metadata, 'title_author_year');
expect(result).to.not.include('title');
expect(result).to.include('author%3ASmith');
expect(result).to.include('%2Byear%3A2024'); // Check for '+'
});

it('should construct URL for title and year only to cover branch', function() {
const metadata = { title: 'Test Paper', author: null, year: '2024' };
const result = global.ZoteroCitationCounts._semanticScholarUrl(metadata, 'title_author_year');
expect(result).to.include('title%3ATest%2520Paper');
expect(result).to.not.include('author');
expect(result).to.include('%2Byear%3A2024'); // Check for '+'
});

it('should construct URL for author only to cover branch', function() {
const metadata = { title: null, author: 'Smith', year: null };
const result = global.ZoteroCitationCounts._semanticScholarUrl(metadata, 'title_author_year');
expect(result).to.not.include('title');
expect(result).to.include('author%3ASmith');
expect(result).to.not.include('year');
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There are multiple tests with identical descriptions (e.g., 'should construct URL for author and year only to cover branch'). While the test cases themselves are valid and cover different scenarios (e.g., missing property vs. null property), using the same description makes it difficult to identify which specific case has failed.

To improve test clarity and maintainability, please provide unique and descriptive names for each test case. For example:

  • 'should construct URL for author and year when title is missing'
  • 'should construct URL for title and year when author is null'
  • 'should construct URL for author only when title and year are missing'

This should be applied to all duplicated test descriptions in this block.

Comment on lines +737 to +767
it('should construct URL for title only to cover branches', function() {
const metadata = { title: 'Test Paper' };
const result = global.ZoteroCitationCounts._nasaadsUrl(metadata, 'title_author_year');
expect(result).to.include('title%3A%22Test%2520Paper%22');
expect(result).to.not.include('author');
expect(result).to.not.include('year');
});

it('should construct URL for author and year only to cover branches', function() {
const metadata = { author: 'Smith', year: '2024' };
const result = global.ZoteroCitationCounts._nasaadsUrl(metadata, 'title_author_year');
expect(result).to.not.include('title');
expect(result).to.include('author%3A%22Smith%22');
expect(result).to.include('year%3A2024');
});

it('should construct URL for title only to cover branches', function() {
const metadata = { title: 'Test Paper', author: null, year: null };
const result = global.ZoteroCitationCounts._nasaadsUrl(metadata, 'title_author_year');
expect(result).to.include('title%3A%22Test%2520Paper%22');
expect(result).to.not.include('author');
expect(result).to.not.include('year');
});

it('should construct URL for author and year only to cover branches', function() {
const metadata = { title: null, author: 'Smith', year: '2024' };
const result = global.ZoteroCitationCounts._nasaadsUrl(metadata, 'title_author_year');
expect(result).to.not.include('title');
expect(result).to.include('author%3A%22Smith%22');
expect(result).to.include('year%3A2024');
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to another comment, there are duplicated test descriptions in this suite (e.g., 'should construct URL for title only to cover branches'). This makes it harder to debug failing tests.

Please update the descriptions to be unique and reflect the specific scenario being tested. For example:

  • 'should construct URL for title only when author and year are missing'
  • 'should construct URL for title only when author and year are null'
  • 'should construct URL for author and year only when title is missing'
  • 'should construct URL for author and year only when title is null'

This will make the test suite easier to understand and maintain.

@flychen50 flychen50 merged commit ab989fb into main Aug 19, 2025
5 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants