UNPKG

@hyperlane-xyz/utils

Version:

General utilities and types for the Hyperlane network

129 lines 4.21 kB
import { expect } from 'chai'; import { LazyAsync } from './async.js'; describe('LazyAsync', () => { it('initializes on first get', async () => { let calls = 0; const lazy = new LazyAsync(async () => { calls += 1; return 5; }); expect(lazy.isInitialized()).to.equal(false); expect(lazy.peek()).to.equal(undefined); const value = await lazy.get(); expect(value).to.equal(5); expect(calls).to.equal(1); expect(lazy.isInitialized()).to.equal(true); }); it('dedupes concurrent calls', async () => { let calls = 0; let resolve; const lazy = new LazyAsync(() => { calls += 1; return new Promise((res) => { resolve = res; }); }); const p1 = lazy.get(); const p2 = lazy.get(); expect(p1).to.equal(p2); expect(calls).to.equal(1); resolve(7); const value = await p1; expect(value).to.equal(7); }); it('returns cached value on subsequent calls', async () => { let calls = 0; const lazy = new LazyAsync(async () => { calls += 1; return 3; }); const v1 = await lazy.get(); const v2 = await lazy.get(); expect(v1).to.equal(3); expect(v2).to.equal(3); expect(calls).to.equal(1); }); it('retries after error by default', async () => { let calls = 0; const lazy = new LazyAsync(async () => { calls += 1; if (calls === 1) throw new Error('boom'); return 9; }); let err; try { await lazy.get(); } catch (e) { err = e; } expect(err?.message).to.equal('boom'); const value = await lazy.get(); expect(value).to.equal(9); expect(calls).to.equal(2); }); it('reset clears and allows re-init', async () => { let calls = 0; const lazy = new LazyAsync(async () => { calls += 1; return calls; }); const v1 = await lazy.get(); expect(v1).to.equal(1); lazy.reset(); expect(lazy.isInitialized()).to.equal(false); expect(lazy.peek()).to.equal(undefined); const v2 = await lazy.get(); expect(v2).to.equal(2); expect(calls).to.equal(2); }); it('peek does not trigger init', async () => { let calls = 0; const lazy = new LazyAsync(async () => { calls += 1; return 4; }); expect(lazy.peek()).to.equal(undefined); expect(calls).to.equal(0); await lazy.get(); expect(lazy.peek()).to.equal(4); expect(calls).to.equal(1); }); it('reset during in-flight init does not repopulate cache', async () => { let calls = 0; let resolve; const lazy = new LazyAsync(() => { calls += 1; return new Promise((res) => { resolve = res; }); }); // Start first initialization const p1 = lazy.get(); expect(calls).to.equal(1); // Reset while first init is in-flight lazy.reset(); expect(lazy.isInitialized()).to.equal(false); // Start second initialization (should create new promise) const originalResolve = resolve; const p2 = lazy.get(); const resolve2 = resolve; expect(calls).to.equal(2); expect(p1).to.not.equal(p2); // Complete second init first resolve2(200); const v2 = await p2; expect(v2).to.equal(200); expect(lazy.isInitialized()).to.equal(true); expect(lazy.peek()).to.equal(200); // Complete first init (stale) - should NOT overwrite cache originalResolve(100); const v1 = await p1; expect(v1).to.equal(100); // Promise still resolves with its value // But cache should still have second value expect(lazy.peek()).to.equal(200); expect(lazy.isInitialized()).to.equal(true); }); }); //# sourceMappingURL=lazy.test.js.map