import { test, afterEach } from 'node:test';
import assert from 'node:assert/strict';
import { checkIndexedDBSupport } from './featureCheck';

// `checkIndexedDBSupport` resolves by talking to the global `indexedDB`. There
// is no real IndexedDB in this Node test environment, so each case installs a
// minimal stub on `globalThis.indexedDB` and restores it afterwards.
type OpenRequest = {
  onsuccess?: () => void;
  onerror?: () => void;
};

const originalIndexedDB = (globalThis as { indexedDB?: unknown }).indexedDB;

afterEach(() => {
  (globalThis as { indexedDB?: unknown }).indexedDB = originalIndexedDB;
});

const installIndexedDB = (impl: unknown) => {
  (globalThis as { indexedDB?: unknown }).indexedDB = impl;
};

test('resolves true when the open request fires onsuccess', async () => {
  let deleted = false;
  installIndexedDB({
    open: (): OpenRequest => {
      const req: OpenRequest = {};
      // fire async, mimicking the real event loop
      queueMicrotask(() => req.onsuccess?.());
      return req;
    },
    deleteDatabase: () => {
      deleted = true;
    },
  });

  assert.equal(await checkIndexedDBSupport(), true);
  assert.equal(deleted, true);
});

test('resolves false when the open request fires onerror', async () => {
  installIndexedDB({
    open: (): OpenRequest => {
      const req: OpenRequest = {};
      queueMicrotask(() => req.onerror?.());
      return req;
    },
    deleteDatabase: () => {},
  });

  assert.equal(await checkIndexedDBSupport(), false);
});

test('resolves false when indexedDB.open throws synchronously', async () => {
  installIndexedDB({
    open: () => {
      throw new Error('blocked');
    },
    deleteDatabase: () => {},
  });

  assert.equal(await checkIndexedDBSupport(), false);
});
