composerFocusRequest.test.ts1.8 KBView on GitHub
import { useCedarStore } from '@/modules/cedar-os/src/store/CedarStore';
import { act } from '@testing-library/react';

/**
 * "Enter on the date field lands on Add guests" is a request, not a function call.
 *
 * Committing a date moves the event's block to another column — another WEEK if the date moved
 * that far — and the composer popover is pinned to that block, so it unmounts and a fresh one
 * mounts. Focus called at that moment reaches a ref belonging to the component that just went
 * away. Worse, the two orders differ: within a week the old form is still up when the request
 * is made, across weeks the new one is already mounted. Nothing that lives in the component,
 * or that is only read at mount, can serve both.
 *
 * Keeping the request in the store is what makes it order-independent: it is state, so an
 * instance that was ALREADY mounted re-runs on the change, and one that mounts later reads it
 * on the way in.
 */
describe('composerFocusRequest', () => {
  const store = () => useCedarStore.getState();

  beforeEach(() => {
    act(() => store().requestComposerFocus(null));
  });

  it('starts empty', () => {
    expect(store().composerFocusRequest).toBeNull();
  });

  it('holds the request until it is answered', () => {
    act(() => store().requestComposerFocus('guests'));
    expect(store().composerFocusRequest).toBe('guests');

    // Whichever composer instance is alive answers it, and clears it.
    act(() => store().requestComposerFocus(null));
    expect(store().composerFocusRequest).toBeNull();
  });

  it('is dropped when the calendar resets, so it cannot fire into a later composer', () => {
    act(() => store().requestComposerFocus('guests'));
    act(() => store().resetCalendarState());
    expect(store().composerFocusRequest).toBeNull();
  });
});