Skip to content

Conversation

@theturtle32
Copy link
Owner

Summary

Successfully achieved the 85%+ overall coverage target by adding comprehensive tests for WebSocketRequest and utils.js components.

  • Overall coverage: 85.05% (up from 79.99%, +5.06%)
  • 616 tests passing (up from 559, +57 new tests)
  • All Autobahn protocol tests passing (517 tests, 100% compliance)
  • Zero lint errors

Changes

New Test Files

test/unit/core/request-cookies-origin.test.mjs (40 tests)

  • Cookie validation error cases (array validation, name/value requirements, duplicates)
  • Cookie name and value sanitization vs rejection behavior
  • Cookie path, domain, expires, and maxage validation
  • Secure and HttpOnly flag handling
  • Multiple cookies with mixed attributes
  • Origin headers for WebSocket versions 8 and 13
  • Protocol validation and sanitization

test/unit/core/utils-additional.test.mjs (17 tests)

  • noop function behavior
  • extend function for object property copying
  • eventEmitterListenerCount functionality
  • bufferAllocUnsafe with various sizes
  • bufferFromString with multiple encodings (utf8, hex, base64, unicode)
  • BufferingLogger creation and functionality

Updated Files

TEST_SUITE_MODERNIZATION_PLAN.md

  • Updated status from 80% → 85% complete
  • Updated test counts: 559 → 616 unit tests
  • Updated coverage metrics across all components
  • Marked coverage target as achieved
  • Updated risk assessment to reflect completion

CLAUDE.md

  • Added comprehensive script cheat sheet
  • Organized testing, linting, and coverage commands
  • Added quick reference section for common workflows

Coverage Improvements

Component Before After Change
Overall 79.99% 85.05% +5.06% ✅
WebSocketRequest 69.78% 90.24% +20.46%
WebSocketConnection 78.40% 80.57% +2.17%
utils.js 33.84% 73.84% +40%
Branch Coverage 83.52% 84.72% +1.20%
Function Coverage 78.71% 81.95% +3.24%

Test Results

Test Files:  30 passed (30)
Tests:       616 passed (616)
Duration:    ~8.2 seconds
Coverage:    85.05% overall ✅

Autobahn:    517 tests, 100% pass rate ✅
Lint:        Zero errors ✅

Test Plan

All existing tests continue to pass:

  • ✅ 616 unit and integration tests
  • ✅ 517 Autobahn WebSocket Protocol Compliance tests
  • ✅ eslint validation with zero errors

🤖 Generated with Claude Code

Added comprehensive test coverage for WebSocketRequest and utils.js
to reach the 85%+ overall coverage target.

Changes:
- Added test/unit/core/request-cookies-origin.test.mjs (40 tests)
  - Cookie validation (name, value, path, domain, expires, maxage)
  - Cookie sanitization behavior
  - Secure and HttpOnly flags
  - Origin headers for WebSocket v8/v13
  - Protocol validation

- Added test/unit/core/utils-additional.test.mjs (17 tests)
  - noop, extend, eventEmitterListenerCount
  - bufferAllocUnsafe, bufferFromString with multiple encodings
  - BufferingLogger functionality

- Updated TEST_SUITE_MODERNIZATION_PLAN.md
  - Overall progress: 80% → 85% complete
  - Test count: 559 → 616 passing tests
  - Coverage metrics updated to reflect achievement

- Updated CLAUDE.md with script cheat sheet
  - Comprehensive testing command reference
  - Quick reference for common workflows

Coverage improvements:
- Overall: 79.99% → 85.05% (+5.06%) ✅
- WebSocketRequest: 69.78% → 90.24% (+20.46%)
- WebSocketConnection: 78.40% → 80.57% (+2.17%)
- utils.js: 33.84% → 73.84% (+40%)
- Branch: 83.52% → 84.72%
- Functions: 78.71% → 81.95%

All 616 unit tests passing ✅
All 517 Autobahn protocol tests passing ✅
Zero lint errors ✅

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Copy link
Owner Author

@theturtle32 theturtle32 left a comment

Choose a reason for hiding this comment

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

Please review this PR using Gemini AI code review. Focus on test quality, coverage improvements, and any medium or high priority issues.

@gemini-code-assist
Copy link

Summary of Changes

Hello @theturtle32, 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 project's test suite by achieving the targeted 85%+ overall code coverage. It introduces 57 new, comprehensive tests focusing on the WebSocketRequest component's cookie and origin handling, as well as various utility functions in utils.js. These additions bolster the robustness and reliability of core WebSocket functionalities, ensuring better stability and adherence to protocol standards. The accompanying documentation has also been updated to reflect this progress and provide clearer guidance on testing workflows.

Highlights

  • Achieved 85%+ Test Coverage: The overall test coverage target has been successfully met, increasing from 79.99% to 85.05%.
  • New Test Files Added: 57 new tests were introduced across two new files: "test/unit/core/request-cookies-origin.test.mjs" (40 tests for WebSocketRequest) and "test/unit/core/utils-additional.test.mjs" (17 tests for utils.js).
  • Improved Component Coverage: Significant coverage improvements were made for WebSocketRequest (from 69.78% to 90.24%) and utils.js (from 33.84% to 73.84%).
  • Documentation Updates: The "TEST_SUITE_MODERNIZATION_PLAN.md" was updated to reflect the achieved coverage target and progress in E2E and CI/CD phases, and "CLAUDE.md" was updated with a comprehensive script cheat sheet.
  • Maintained Quality Standards: All 616 unit tests and 517 Autobahn protocol tests are passing, and there are zero lint errors.
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 by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

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 pull request 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

@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 is an excellent pull request that significantly improves the project's test coverage, successfully achieving the 85% target. The 57 new tests for WebSocketRequest and utils.js are comprehensive and well-written, covering many edge cases and error conditions. The updates to the documentation in CLAUDE.md and TEST_SUITE_MODERNIZATION_PLAN.md are also clear and provide great visibility into the project's progress.

I have a few suggestions to further improve the quality and robustness of the new tests, primarily related to using vitest features for parameterized tests, ensuring test environment cleanup, and maintaining code consistency. Overall, this is a fantastic contribution to the project's health and maintainability.

Comment on lines 137 to 165
it('should create a BufferingLogger when debug is enabled', () => {
// Enable debug for this test
const originalDebug = process.env.DEBUG;
process.env.DEBUG = 'test:enabled:*';

// Force require cache clear for debug module
const debugModule = require('debug');
debugModule.enable('test:enabled:*');

const logger = utils.BufferingLogger('test:enabled:logger', 'id456');

expect(typeof logger).toBe('function');
expect(typeof logger.printOutput).toBe('function');

// Test logging functionality
logger('Test message', 'arg1', 'arg2');

// The logger should buffer messages
expect(typeof logger.printOutput).toBe('function');

// Restore original DEBUG setting
if (originalDebug) {
process.env.DEBUG = originalDebug;
debugModule.enable(originalDebug);
} else {
delete process.env.DEBUG;
debugModule.disable();
}
});

Choose a reason for hiding this comment

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

high

This test modifies process.env.DEBUG to test the BufferingLogger. If an assertion within the test fails, the cleanup code at the end will not be executed. This can cause side effects and make other tests in the suite flaky. To ensure the environment is always restored, please wrap the test logic in a try...finally block.

    it('should create a BufferingLogger when debug is enabled', () => {
      const originalDebug = process.env.DEBUG;
      const debugModule = require('debug');
      try {
        process.env.DEBUG = 'test:enabled:*';
        debugModule.enable('test:enabled:*');

        const logger = utils.BufferingLogger('test:enabled:logger', 'id456');

        expect(typeof logger).toBe('function');
        expect(typeof logger.printOutput).toBe('function');

        // Test logging functionality
        logger('Test message', 'arg1', 'arg2');

        // The logger should buffer messages
        expect(typeof logger.printOutput).toBe('function');
      } finally {
        // Restore original DEBUG setting
        if (originalDebug) {
          process.env.DEBUG = originalDebug;
          debugModule.enable(originalDebug);
        } else {
          delete process.env.DEBUG;
          debugModule.disable();
        }
      }
    });

Comment on lines 486 to 514
it('should reject protocol with separator character', () => {
const separators = ['(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}'];

separators.forEach(sep => {
const newSocket = new MockSocket();
newSocket.remoteAddress = '127.0.0.1';

const newHttpRequest = {
url: '/',
headers: {
'host': 'localhost',
'upgrade': 'websocket',
'connection': 'Upgrade',
'sec-websocket-version': '13',
'sec-websocket-key': 'dGhlIHNhbXBsZSBub25jZQ==',
'sec-websocket-protocol': `test${sep}protocol`
}
};

const newRequest = new WebSocketRequest(newSocket, newHttpRequest, { maxReceivedFrameSize: 0x10000 });
newRequest.readHandshake();

expect(() => {
newRequest.accept(`test${sep}protocol`, null, null);
}).toThrow(/Illegal character.* in subprotocol/);

newSocket.removeAllListeners();
});
});

Choose a reason for hiding this comment

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

medium

This test iterates through a list of separators within a single it block. If one of the separators causes a test failure, it can be difficult to identify which one failed. Consider refactoring this to use it.each to create a separate test case for each separator. This improves test reporting and makes debugging easier.

    it.each(['(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}'])('should reject protocol with separator character: %s', (sep) => {
      const newSocket = new MockSocket();
      newSocket.remoteAddress = '127.0.0.1';

      const newHttpRequest = {
        url: '/',
        headers: {
          'host': 'localhost',
          'upgrade': 'websocket',
          'connection': 'Upgrade',
          'sec-websocket-version': '13',
          'sec-websocket-key': 'dGhlIHNhbXBsZSBub25jZQ==',
          'sec-websocket-protocol': `test${sep}protocol`
        }
      };

      const newRequest = new WebSocketRequest(newSocket, newHttpRequest, { maxReceivedFrameSize: 0x10000 });
      newRequest.readHandshake();

      expect(() => {
        newRequest.accept(`test${sep}protocol`, null, null);
      }).toThrow(/Illegal character.* in subprotocol/);

      newSocket.removeAllListeners();
    });

Comment on lines 45 to 67
describe('eventEmitterListenerCount', () => {
it('should return listener count for an event', () => {
const EventEmitter = require('events').EventEmitter;
const emitter = new EventEmitter();

const listener1 = () => {};
const listener2 = () => {};

emitter.on('test', listener1);
emitter.on('test', listener2);

const count = utils.eventEmitterListenerCount(emitter, 'test');
expect(count).toBe(2);
});

it('should return 0 for event with no listeners', () => {
const EventEmitter = require('events').EventEmitter;
const emitter = new EventEmitter();

const count = utils.eventEmitterListenerCount(emitter, 'nonexistent');
expect(count).toBe(0);
});
});

Choose a reason for hiding this comment

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

medium

The EventEmitter is being required twice inside this describe block (lines 47 and 61). To improve code clarity and adhere to ES module conventions used in this project, it's better to import it once at the top of the file.

Here's how you could refactor it:

// At the top of the file (e.g. line 7)
import { EventEmitter } from 'events';

// ... later in the file
describe('eventEmitterListenerCount', () => {
  it('should return listener count for an event', () => {
    const emitter = new EventEmitter();
    // ...
  });

  it('should return 0 for event with no listeners', () => {
    const emitter = new EventEmitter();
    // ...
  });
});

Fixed all high and medium priority issues from the code review:

1. HIGH PRIORITY: Added try-finally block to BufferingLogger test
   - Ensures process.env.DEBUG is always restored even if test fails
   - Prevents flaky tests and side effects on other tests

2. MEDIUM PRIORITY: Refactored separator character test to use it.each
   - Changed from forEach loop to it.each for better test reporting
   - Now creates 17 individual test cases instead of 1 combined test
   - Makes it easier to identify which separator character fails
   - Increased test count from 616 to 632 total tests

3. MEDIUM PRIORITY: Fixed EventEmitter imports
   - Moved EventEmitter import to top of file
   - Removed duplicate require() calls
   - Better code organization and ES module conventions

All 632 tests passing ✅

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@theturtle32 theturtle32 merged commit e12b5d9 into v2 Oct 6, 2025
1 check passed
@theturtle32 theturtle32 deleted the coverage-improvement-85-percent branch October 6, 2025 06:09
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