Skip to content

Add unit tests for RemoteSigningService#153

Draft
Dexploarer wants to merge 1 commit intodevelopfrom
test-remote-signing-service-12041147106033532443
Draft

Add unit tests for RemoteSigningService#153
Dexploarer wants to merge 1 commit intodevelopfrom
test-remote-signing-service-12041147106033532443

Conversation

@Dexploarer
Copy link
Owner

This change adds a new test file src/services/remote-signing-service.test.ts to verify the behavior of the RemoteSigningService. This service handles transaction signing requests from sandboxed agents, enforcing security policies and requiring human confirmation for high-value or sensitive operations.

The tests cover:

  1. Policy Enforcement: Verifying that requests compliant with the policy are signed immediately, while those violating the policy (e.g., denylisted contracts) are rejected.
  2. Human Confirmation: Validating the flow where a request triggers a manual approval requirement. This includes:
    • Creating a pending approval.
    • Successfully approving a pending request.
    • Rejecting a pending request.
    • Verifying that expired requests cannot be approved.
  3. Audit Logging: Ensuring that all significant events (submission, approval, rejection, policy updates) are correctly recorded in the audit log.

Due to environment limitations with vitest configuration loading, the tests use a vi shim to run successfully with bun test while maintaining standard Vitest syntax for future compatibility.


PR created automatically by Jules for task 12041147106033532443 started by @Dexploarer

Adds comprehensive unit tests for `RemoteSigningService` covering:
- Policy evaluation and enforcement (allow/deny).
- Human confirmation workflows (pending/approve/reject).
- Audit logging of security-critical events.
- Handling of expired approval requests.

Tests are implemented using `vitest` syntax but shimmed to run via `bun test` to bypass environment-specific module resolution issues.
@google-labs-jules
Copy link

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@coderabbitai
Copy link

coderabbitai bot commented Feb 27, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch test-remote-signing-service-12041147106033532443

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment on lines +145 to +169
it("fails if request expired", async () => {
// Mock Date.now to simulate expiration
vi.useFakeTimers();
const now = Date.now();

const policy: SigningPolicy = {
...createDefaultPolicy(),
requireHumanConfirmation: true,
};
service.updatePolicy(policy);

const request = makeRequest();
await service.submitSigningRequest(request);

// Fast forward past expiration (timeout is 1000ms)
vi.setSystemTime(now + 2000);

const result = await service.approveRequest(request.requestId);

expect(result.success).toBe(false);
expect(result.error).toContain("Approval expired");
expect(service.getPendingApprovals()).toHaveLength(0);

vi.useRealTimers();
});

Choose a reason for hiding this comment

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

Potential test reliability issue due to timer handling

In the test for expired approvals (it("fails if request expired", ...)), vi.useFakeTimers() is used and then reset with vi.useRealTimers() at the end. If an exception occurs before the reset, subsequent tests may be affected by lingering fake timers, leading to unreliable results.

Recommended solution:
Wrap the test logic in a try/finally block to ensure timers are always reset:

it("fails if request expired", async () => {
  vi.useFakeTimers();
  try {
    // ... test logic ...
  } finally {
    vi.useRealTimers();
  }
});

This guarantees cleanup even if an assertion fails or an error is thrown.

@github-actions github-actions bot added the tests label Feb 27, 2026
@gemini-code-assist
Copy link

Summary of Changes

Hello, 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 introduces a new suite of unit tests for the RemoteSigningService. The primary goal is to thoroughly validate the service's behavior in managing transaction signing requests from sandboxed agents, with a strong focus on security, user interaction, and accountability. These tests ensure the robust and correct operation of the service's core functionalities.

Highlights

  • Policy Enforcement: Verified that the service correctly applies signing policies, immediately signing compliant requests and rejecting those that violate rules like denylisted contracts.
  • Human Confirmation Flow: Tested the end-to-end process for requests requiring manual approval, including creation, successful approval, rejection, and handling of expired requests.
  • Audit Logging: Ensured that all critical events, such as request submission, approval, rejection, and policy updates, are accurately recorded in the audit log.
  • Vitest Compatibility: Addressed environment limitations by using a 'vi' shim to enable successful execution with 'bun test' while maintaining standard Vitest syntax.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • src/services/remote-signing-service.test.ts
    • Added comprehensive unit tests for the RemoteSigningService, covering policy enforcement, human confirmation flows, and audit logging.
Activity
  • The pull request was automatically created by Jules for a task initiated by @Dexploarer.
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 pull request adds a comprehensive set of unit tests for the RemoteSigningService. The tests cover policy enforcement, human confirmation flows, and audit logging, which is great. My review focuses on improving the robustness and maintainability of these new tests. I've suggested a few changes: ensuring timer mocks are always cleaned up to prevent test flakiness, and strengthening assertions around audit logging to make the tests more precise and less prone to missing regressions. Overall, this is a solid addition for ensuring the service's reliability.

let service: RemoteSigningService;
let signer: MockSigner;
let auditLog: SandboxAuditLog;
let auditLogSpy: ReturnType<typeof vi.spyOn>;

Choose a reason for hiding this comment

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

medium

To ensure test isolation and prevent fake timers from leaking between tests (which can cause difficult-to-debug failures), it's a best practice to reset timers in an afterEach hook. This guarantees cleanup even if a test fails mid-execution. You can then remove the explicit vi.useRealTimers() calls from individual tests.

  let auditLogSpy: ReturnType<typeof vi.spyOn>;

  afterEach(() => {
    vi.useRealTimers();
  });

Comment on lines +240 to +246
it("logs submission", async () => {
const request = makeRequest();
await service.submitSigningRequest(request);
expect(auditLogSpy).toHaveBeenCalledWith(
expect.objectContaining({ type: "signing_request_submitted" }),
);
});

Choose a reason for hiding this comment

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

medium

The current assertion is weak because a successful submission that is auto-approved should generate two audit log events: signing_request_submitted followed by signing_request_approved. This test only checks for the first event and ignores the second, and doesn't check the total number of calls. This could allow regressions in logging to go unnoticed.

By asserting the exact number of calls and the content of each call in order, the test becomes much more robust. This same pattern of more specific audit log assertions should be applied to other tests in this suite (e.g., for policy rejections, manual approvals, etc.).

    it("logs submission and auto-approval", async () => {
      const request = makeRequest();
      await service.submitSigningRequest(request);

      expect(auditLogSpy).toHaveBeenCalledTimes(2);
      expect(auditLogSpy).toHaveBeenNthCalledWith(
        1,
        expect.objectContaining({ type: "signing_request_submitted" })
      );
      expect(auditLogSpy).toHaveBeenNthCalledWith(
        2,
        expect.objectContaining({ type: "signing_request_approved" })
      );
    });

Comment on lines +250 to +252
expect(auditLogSpy).toHaveBeenCalledWith(
expect.objectContaining({ type: "policy_decision" }),
);

Choose a reason for hiding this comment

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

medium

While this assertion is correct, it could be made more robust by also asserting the number of times the spy was called. This ensures no other unexpected log events were fired during the policy update.

      expect(auditLogSpy).toHaveBeenCalledTimes(1);
      expect(auditLogSpy).toHaveBeenCalledWith(
        expect.objectContaining({ type: "policy_decision" })
      );

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant