Hive Shim Test Suite
Gherkin-style tests for LocalStorage, IndexedDB, and Hive Keychain
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<!-- Gherkin Editor -->
<div>
<h2 class="text-lg font-semibold mb-3">Feature Definition</h2>
<textarea id="feature" class="w-full h-96 bg-zinc-900 border border-zinc-700 rounded-3xl p-6 font-mono text-sm" spellcheck="false">
Feature: Hive Shim Compatibility
Scenario: LocalStorage should work through the shim
Given the app is loaded through the hive-shim
When I set localStorage item "testKey" to "Hello from shim"
Then localStorage.getItem("testKey") should return "Hello from shim"
Scenario: LocalStorage persistence across reloads
Given localStorage has key "persistTest"
When I reload the app
Then localStorage.getItem("persistTest") should still exist
Scenario: hive_keychain.requestBroadcast should work
Given hive_keychain is available
When I call requestBroadcast with a test operation
Then the operation should be forwarded to the parent shim
Scenario: IndexedDB (Expected to fail currently)
Given the app tries to open an IndexedDB
Then it should either work or gracefully degrade
<!-- Test Runner -->
<div>
<div class="flex justify-between mb-3">
<h2 class="text-lg font-semibold">Test Results</h2>
<button onclick="runTests()"
class="bg-emerald-600 hover:bg-emerald-500 px-6 py-2 rounded-2xl font-medium">
▶️ Run Tests
</button>
</div>
<div id="results" class="bg-zinc-900 border border-zinc-700 rounded-3xl p-6 min-h-[500px] overflow-auto text-sm font-mono"></div>
</div>
</div>
// Simple Gherkin-style test runner
const tests = [];
function addTest(description, fn) {
tests.push({ description, fn, status: 'pending', message: '' });
}
async function runTests() {
const resultsDiv = document.getElementById('results');
resultsDiv.innerHTML = '
Running tests...
';for (let test of tests) {
test.status = 'running';
try {
await test.fn();
test.status = 'passed';
test.message = 'OK';
} catch (err) {
test.status = 'failed';
test.message = err.message || 'Failed';
}
renderResults();
}
}
function renderResults() {
const div = document.getElementById('results');
div.innerHTML = tests.map(t => <div class="mb-4 p-4 rounded-2xl border ${t.status === 'passed' ? 'border-emerald-500 bg-emerald-950' : t.status === 'failed' ? 'border-red-500 bg-red-950' : 'border-zinc-700'}"> <div class="flex justify-between"> <span>${t.description}</span> <span class="${t.status === 'passed' ? 'passed' : t.status === 'failed' ? 'failed' : 'text-zinc-500'}"> ${t.status.toUpperCase()} </span> </div> ${t.message ?
: ''} </div>).join('');}
// ====================== TESTS ======================
addTest("LocalStorage.setItem and getItem", async () => {
localStorage.setItem("shimTestKey", "Hello from shim test");
const value = localStorage.getItem("shimTestKey");
if (value !== "Hello from shim test") throw new Error(Expected 'Hello from shim test', got '${value}');
});
addTest("LocalStorage persistence (same session)", async () => {
const value = localStorage.getItem("shimTestKey");
if (value !== "Hello from shim test") throw new Error("Value did not persist in same session");
});
addTest("hive_keychain is available", () => {
if (!window.hive_keychain) throw new Error("hive_keychain not found");
});
addTest("hive_keychain.requestBroadcast exists", () => {
if (typeof window.hive_keychain.requestBroadcast !== 'function') {
throw new Error("requestBroadcast is not a function");
}
});
addTest("IndexedDB proxy (expected to be limited)", () => {
if (typeof indexedDB === 'undefined' || typeof indexedDB.open !== 'function') {
console.warn("IndexedDB proxy not fully functional yet");
}
});
// Init
window.addEventListener('load', () => {
renderResults();
window.addEventListener("message", (e) => {
if (e.data.type === "hive-shim-context") {
console.log("✅ Running inside hive-shim", e.data);
}
});
});