Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 17, 2025

Description

Replaces sinon with Vitest's native mocking utilities across the entire codebase. Consolidates testing infrastructure to a single mocking library.

Changes

Test utilities:

  • spy()vi.fn()
  • stub()vi.fn().mockReturnValue() / vi.spyOn()
  • useFakeTimers()vi.useFakeTimers() + vi.setSystemTime()
  • sinon.restore()vi.restoreAllMocks()
  • SinonSpy type → MockInstance

Assertion conversions:

  • .callCounttoHaveBeenCalledTimes()
  • .calledOncetoHaveBeenCalledOnce()
  • .calledtoHaveBeenCalled()
  • .lastCall.args[n].mock.calls[mock.calls.length - 1][n]
  • .lastCall.firstArg.mock.calls[mock.calls.length - 1][0]
  • .firstCall.args[n].mock.calls[0][n]
  • .args[n].mock.calls[n]
  • .resetHistory().mockClear()
  • sinonAssert.callOrder(spy1, spy2)expect(spy1.mock.invocationCallOrder[0]).toBeLessThan(spy2.mock.invocationCallOrder[0])

Dependencies:

  • Removed sinon and @types/sinon from devDependencies

Example

- import { spy } from 'sinon';
+ import { vi } from 'vitest';

- const handleClick = spy();
+ const handleClick = vi.fn();

- expect(handleClick.callCount).to.equal(1);
+ expect(handleClick).toHaveBeenCalledTimes(1);

- expect(handleClick.lastCall.args[0]).to.equal('value');
+ expect(handleClick.mock.calls[handleClick.mock.calls.length - 1][0]).to.equal('value');

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • iojs.org
    • Triggering command: curl -q --fail --compressed -L -s REDACTED -o - (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

Convert all usages of sinon to Vitest's mocking utilities

Overview

Migrate the entire codebase from sinon to Vitest's built-in mocking utilities to consolidate testing tools and leverage Vitest's native capabilities.

Files to Update

1. Test Utilities

  • test/utils/helperFn.ts

    • Replace import { spy } from 'sinon' with import { vi } from 'vitest'
    • Convert spy() calls to vi.fn() in the spyApi function
  • test/utils/pickers/misc.ts

    • Replace import sinon from 'sinon' with import { vi } from 'vitest'
    • Convert sinon.stub() to vi.fn() in stubMatchMedia function
  • test/utils/setupFakeClock.ts

    • Replace import { useFakeTimers } from 'sinon' with import { vi } from 'vitest'
    • Convert useFakeTimers() calls to vi.useFakeTimers()
    • Update the return type and implementation to use Vitest's FakeTimers API
    • Replace fakeClock.runToLast() with equivalent Vitest method
    • Replace fakeClock.restore() with vi.useRealTimers()
  • test/utils/scheduler/StoreSpy.tsx

    • Replace import { spy as sinonSpy, SinonSpy } from 'sinon' with import { vi, MockInstance } from 'vitest'
    • Convert sinonSpy() to vi.spyOn()
    • Replace SinonSpy type with MockInstance or ReturnType<typeof vi.spyOn>
    • Update cleanup logic from restore() to mockRestore()
  • test/setupVitest.ts

    • Remove import sinon from 'sinon'
    • Replace sinon.restore() in afterEach with vi.restoreAllMocks()
  • test/utils/pickers/assertions.ts

    • Replace SinonSpy type import with Vitest's MockInstance type

2. Component Tests

  • packages/x-internals/src/EventManager/EventManager.test.ts

    • Replace import { spy, assert as sinonAssert } from 'sinon' with import { vi, expect } from 'vitest'
    • Convert spy() calls to vi.fn()
    • Replace sinonAssert.callOrder(listener1, listener2) with manual assertions using mock call order tracking:
      expect(listener1.mock.invocationCallOrder[0]).toBeLessThan(listener2.mock.invocationCallOrder[0])
  • packages/x-data-grid/src/tests/rows.DataGrid.test.tsx

    • Replace import { spy, stub } from 'sinon' with import { vi } from 'vitest'
    • Convert all spy() calls to vi.fn()
    • Convert all stub() calls to vi.fn() or vi.spyOn()
  • packages/x-data-grid/src/tests/keyboard.DataGrid.test.tsx

    • Replace spy imports with vi.fn()
    • Update the valueSetterMock to use vi.fn()
  • packages/x-date-pickers/src/DatePicker/tests/DatePicker.test.tsx

    • Replace import { spy } from 'sinon' with import { vi } from 'vitest'
    • Convert spy() calls to vi.fn()
  • packages/x-scheduler/src/internals/components/event-popover/EventPopover.test.tsx

    • Replace spy import with vi.fn()
    • Update all spy usage to Vitest mocks
  • packages/x-scheduler-headless/src/utils/SchedulerStore/tests/event.SchedulerStore.test.ts

    • Replace import { spy } from 'sinon' with import { vi } from 'vitest'
    • Convert spy() calls to vi.fn()

Key Conversions

Basic Spy/Stub

// Before
import { spy, stub } from 'sinon';
const mySpy = spy();
const myStub = stub().returns(value);

// After
import { vi } from 'vitest';
const mySpy = vi.fn();
const myStub = vi.fn().mockReturnValue(value);

Spying on Methods

// Before
import { spy } from 'sinon';
const spyFn = spy(object, 'methodName');

// After
import { vi } from 'vitest';
const spyFn = vi.spyOn(object, 'methodName');

Fake Timers

// Before
import { useFakeTimers } from 'sinon';
const clock = useFakeTimers({ now: timestamp });
clock.runToLast();
clock.restore();

// After
import { vi } from 'vitest';
vi.useFakeTimers();
vi.setSystemTime(timestamp);
vi.runAllTimers();
vi.useRealTimers();

Call Order Assertions

// Before
import { assert as sinonAssert } from 'sinon';
sinonAssert.callOrder(spy1, spy2);

// After
expect(spy1.mock.invocationCallOrder[0]).toBeLessThan(spy2.mock.invocationCallOrder[0]);

Cleanup

// Before
sinon.restore();

// After
vi.restoreAllMocks();

Dependencies

After the migration, remove sinon from package.json:

  • Remove sinon from devDependencies
  • Remove @types/sinon if present

Testing

Ensure all existing tests pass after the migration. The behavior should remain identical, just using Vitest's native mocking instead of sinon.

Benefits

  • Reduced dependencies: Remove sinon and its types from the project
  • Better integration: Use Vitest's native mocking which is designed to work seamlessly with Vitest
  • Simpler API: Vitest's mocking API is more modern and intuitive
  • Better performance: Native Vitest mocking can be faster than third-party libraries
  • Consistency: All mocking in one place rather than split between sinon and Vitest

This pull request was created as a result of the following prompt from Copilot chat.

Convert all usages of sinon to Vitest's mocking utilities

Overview

Migrate the entire codebase from sinon to Vitest's built-in mocking utilities to consolidate testing tools and leverage Vitest's native capabilities.

Files to Update

1. Test Utilities

  • test/utils/helperFn.ts

    • Replace import { spy } from 'sinon' with import { vi } from 'vitest'
    • Convert spy() calls to vi.fn() in the spyApi function
  • test/utils/pickers/misc.ts

    • Replace import sinon from 'sinon' with import { vi } from 'vitest'
    • Convert sinon.stub() to vi.fn() in stubMatchMedia function
  • test/utils/setupFakeClock.ts

    • Replace import { useFakeTimers } from 'sinon' with import { vi } from 'vitest'
    • Convert useFakeTimers() calls to vi.useFakeTimers()
    • Update the return type and implementation to use Vitest's FakeTimers API
    • Replace fakeClock.runToLast() with equivalent Vitest method
    • Replace fakeClock.restore() with vi.useRealTimers()
  • test/utils/scheduler/StoreSpy.tsx

    • Replace import { spy as sinonSpy, SinonSpy } from 'sinon' with import { vi, MockInstance } from 'vitest'
    • Convert sinonSpy() to vi.spyOn()
    • Replace SinonSpy type with MockInstance or ReturnType<typeof vi.spyOn>
    • Update cleanup logic from restore() to mockRestore()
  • test/setupVitest.ts

    • Remove import sinon from 'sinon'
    • Replace sinon.restore() in afterEach with vi.restoreAllMocks()
  • test/utils/pickers/assertions.ts

    • Replace SinonSpy type import with Vitest's MockInstance type

2. Component Tests

  • packages/x-internals/src/EventManager/EventManager.test.ts

    • Replace import { spy, assert as sinonAssert } from 'sinon' with import { vi, expect } from 'vitest'
    • Convert spy() calls to vi.fn()
    • Replace sinonAssert.callOrder(listener1, listener2) with manual assertions using mock call order tracking:
      expect(listener1.mock.invocationCallOrder[0]).toBeLessThan(listener2.mock.invocationCallOrder[0])
  • packages/x-data-grid/src/tests/rows.DataGrid.test.tsx

    • Replace import { spy, stub } from 'sinon' with import { vi } from 'vitest'
    • Convert all spy() calls to vi.fn()
    • Convert all stub() calls to vi.fn() or vi.spyOn()
  • packages/x-data-grid/src/tests/keyboard.DataGrid.test.tsx

    • Replace spy imports with vi.fn()
    • Update the valueSetterMock to use vi.fn()
  • packages/x-date-pickers/src/DatePicker/tests/DatePicker.test.tsx

    • Replace import { spy } from 'sinon' with import { vi } from 'vitest'
    • Convert spy() calls to vi.fn()
  • packages/x-scheduler/src/internals/components/event-popover/EventPopover.test.tsx

    • Replace spy import with vi.fn()
    • Update all spy usage to Vitest mocks
  • packages/x-scheduler-headless/src/utils/SchedulerStore/tests/event.SchedulerStore.test.ts

    • Replace import { spy } from 'sinon' with import { vi } from 'vitest'
    • Convert spy() calls to vi.fn()

Key Conversions

Basic Spy/Stub

// Before
import { spy, stub } from 'sinon';
const mySpy = spy();
const myStub = stub().returns(value);

// After
import { vi } from 'vitest';
const mySpy = vi.fn();
const myStub = vi.fn().mockReturnValue(value);

Spying on Methods

// Before
import { spy } from 'sinon';
const spyFn = spy(object, 'methodName');

// After
import { vi } from 'vitest';
const spyFn = vi.spyOn(object, 'methodName');

Fake Timers

// Before
import { useFakeTimers } from 'sinon';
const clock = useFakeTimers({ now: timestamp });
clock.runToLast();
clock.restore();

// After
import { vi } from 'vitest';
vi.useFakeTimers();
vi.setSystemTime(timestamp);
vi.runAllTimers();
vi.useRealTimers();

Call Order Assertions

// Before
import { assert as sinonAssert } from 'sinon';
sinonAssert.callOrder(spy1, spy2);

// After
expect(spy1.mock.invocationCallOrder[0]).toBeLessThan(spy2.mock.invocationCallOrder[0]);

Cleanup

// Before
sinon.restore();

// After
vi.restoreAllMocks();

Dependencies

After the migration, remove sinon from package.json:

  • Remove sinon from devDependencies
  • Remove @types/sinon if present

Testing

Ensure all existing tests pass after the migration. The behavior should remain identical, just using Vitest's native mocking instead of sinon.

Benefits

  • Reduced dependencies: Remove sinon and its types from the project
  • Better integration: Use Vitest's native mocking which is designed to work seamlessly with Vitest
  • Simpler API: Vitest's mocking API is more modern and intuitive
  • Better performance: Native Vitest mocking can be faster than third-party libraries
  • Consistency: All mocking in one place rather than split between sinon and Vitest

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Co-authored-by: bernardobelchior <12778398+bernardobelchior@users.noreply.github.com>
@mui-bot
Copy link

mui-bot commented Nov 17, 2025

Deploy preview: https://deploy-preview-20352--material-ui-x.netlify.app/

Bundle size report

Bundle size will be reported once CircleCI build #678097 finishes.

Generated by 🚫 dangerJS against 80d00b9

Copilot AI and others added 4 commits November 17, 2025 09:41
Co-authored-by: bernardobelchior <12778398+bernardobelchior@users.noreply.github.com>
Co-authored-by: bernardobelchior <12778398+bernardobelchior@users.noreply.github.com>
Co-authored-by: bernardobelchior <12778398+bernardobelchior@users.noreply.github.com>
Co-authored-by: bernardobelchior <12778398+bernardobelchior@users.noreply.github.com>
Copilot AI changed the title [WIP] Migrate testing utilities from sinon to Vitest Migrate from sinon to Vitest mocking utilities Nov 17, 2025
Copilot finished work on behalf of bernardobelchior November 17, 2025 09:54
@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged. label Nov 17, 2025
@github-actions
Copy link

This pull request has conflicts, please resolve those before we can evaluate the pull request.

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

Labels

PR: out-of-date The pull request has merge conflicts and can't be merged.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants