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

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

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

  it('disconnect clears active', () => {
    const host = mountHost();
    const inst = connectTrait(confetti, host);
    inst.disconnect(host);
    expect(host.hasAttribute('data-confetti-active')).toBe(false);
  });

  it('no canvas: graceful degradation in happy-dom', () => {
    // Old contract: this trait used a host-scoped <canvas>. New
    // contract: it pushes <span> particles into the body-level
    // popover stage (no canvas anywhere). The test name is kept for
    // continuity — the assertion is the same: connect must not throw
    // in environments without real layout (rect = 0,0,0,0 in
    // happy-dom; viewportCenterOf returns null and the trait skips
    // particle spawning gracefully).
    const host = mountHost();
    expect(() => connectTrait(confetti, host)).not.toThrow();
  });

  it('does not append particles inside the host (stage is body-level)', () => {
    const host = mountHost();
    const inst = connectTrait(confetti, host);
    // The old implementation appended a <canvas> child to the host.
    // The new implementation must leave the host's children alone —
    // every particle belongs to the body-level popover stage.
    expect(host.children.length).toBe(0);
    inst.disconnect(host);
  });
});
