import { describe, it, expect, beforeEach } from 'vitest';
import { confettiBurst } from './confetti-burst.js';
import { _resetStage } from '../confetti/confetti-stage.js';
import { mountHost, connectTrait, spyEvent, resetDOM, wait } from '../test-helpers.js';

describe('confetti-burst', () => {
  beforeEach(() => {
    resetDOM();
    _resetStage();
  });

  it('sets data-confetti-burst-active on connect', () => {
    const host = mountHost();
    connectTrait(confettiBurst, host);
    expect(host.hasAttribute('data-confetti-burst-active')).toBe(true);
  });

  it('fires confetti-burst-done even without real layout (happy-dom)', async () => {
    const host = mountHost();
    const spy = spyEvent(host, 'confetti-burst-done');
    connectTrait(confettiBurst, host);
    // happy-dom returns rect = 0,0,0,0 for unattached layout. The
    // trait's graceful-degradation path queues `done` on next tick.
    await wait(50);
    expect(spy.count).toBeGreaterThanOrEqual(1);
  });

  it('disconnect removes the active attribute', () => {
    const host = mountHost();
    const inst = confettiBurst();
    inst.connect(host);
    inst.disconnect(host);
    expect(host.hasAttribute('data-confetti-burst-active')).toBe(false);
  });

  it('host stays unmodified by particle injection', () => {
    const host = mountHost();
    const inst = connectTrait(confettiBurst, host);
    // New contract: particles live in the body-level popover stage,
    // not on the host. The host must not gain children or inline
    // position/cssText hacks (the old canvas-injection path did).
    expect(host.tagName).toBe('DIV');
    expect(host.children.length).toBe(0);
    inst.disconnect(host);
  });
});
