pipe-protocol
Version:
A protocol for large scale Interplanetary Intertool Agent Context
218 lines • 9.1 kB
JavaScript
"use strict";
/**
* @file IpfsNode Test Suite
* @version 1.0.0
* @status STABLE - COMPLETE TEST COVERAGE
* @lastModified 2024-02-03
*
* Tests for core IPFS node functionality.
*
* Test Coverage:
* - Node lifecycle (init/stop)
* - Storage operations (memory/persistent)
* - Network operations
* - Data operations (add/get)
* - Error handling
*/
Object.defineProperty(exports, "__esModule", { value: true });
const vitest_1 = require("vitest");
const ipfsNode_1 = require("../ipfsNode");
const helia_1 = require("helia");
const sha2_1 = require("multiformats/hashes/sha2");
const multiformats_1 = require("multiformats");
// Mock helia and its dependencies
vitest_1.vi.mock('helia', () => ({
createHelia: vitest_1.vi.fn()
}));
vitest_1.vi.mock('multiformats/hashes/sha2', () => ({
sha256: {
digest: vitest_1.vi.fn(),
code: 0x12 // Required for CID creation
}
}));
(0, vitest_1.describe)('IpfsNode', () => {
let node;
let mockBlockstore;
(0, vitest_1.beforeEach)(() => {
// Reset all mocks
vitest_1.vi.resetAllMocks();
// Create mock blockstore
mockBlockstore = {
put: vitest_1.vi.fn(),
get: vitest_1.vi.fn(),
has: vitest_1.vi.fn(),
delete: vitest_1.vi.fn()
};
// Create mock helia instance
const mockCid = {
toString: () => 'bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi',
toV1: () => mockCid
};
const pinnedCids = new Set();
const mockHelia = {
blockstore: mockBlockstore,
pins: {
add: vitest_1.vi.fn().mockImplementation(async (cid) => {
pinnedCids.add(cid);
}),
rm: vitest_1.vi.fn().mockImplementation(async (cid) => {
pinnedCids.delete(cid);
}),
ls: vitest_1.vi.fn().mockImplementation(async function* () {
for (const cid of pinnedCids) {
yield cid;
}
})
},
stop: vitest_1.vi.fn()
};
// Setup default mock implementations
vitest_1.vi.mocked(helia_1.createHelia).mockResolvedValue(mockHelia);
// Mock sha256 digest to return a valid hash
vitest_1.vi.mocked(sha2_1.sha256.digest).mockResolvedValue({
code: sha2_1.sha256.code,
size: 32,
digest: new Uint8Array(32),
bytes: new Uint8Array(32)
});
// Mock CID behavior
vitest_1.vi.spyOn(multiformats_1.CID, 'createV1').mockReturnValue(mockCid);
vitest_1.vi.spyOn(multiformats_1.CID, 'parse').mockReturnValue(mockCid);
node = new ipfsNode_1.IpfsNode({
storage: 'memory'
});
});
(0, vitest_1.afterEach)(async () => {
await node.stop();
});
(0, vitest_1.describe)('Initialization', () => {
(0, vitest_1.it)('should initialize successfully', async () => {
await node.init();
const peerId = await node.getPeerId();
(0, vitest_1.expect)(peerId).toBeDefined();
});
(0, vitest_1.it)('should handle initialization errors', async () => {
vitest_1.vi.mocked(helia_1.createHelia).mockRejectedValueOnce(new Error('Failed to initialize'));
const invalidNode = new ipfsNode_1.IpfsNode({
storage: 'memory'
});
await (0, vitest_1.expect)(invalidNode.init()).rejects.toThrow('Failed to initialize');
});
});
(0, vitest_1.describe)('Data Operations', () => {
(0, vitest_1.beforeEach)(async () => {
await node.init();
});
(0, vitest_1.it)('should add and retrieve data', async () => {
const data = new TextEncoder().encode('test data');
// Mock the blockstore operations
mockBlockstore.put.mockResolvedValueOnce(undefined);
mockBlockstore.get.mockResolvedValueOnce(data);
const cid = await node.add(data);
(0, vitest_1.expect)(cid).toBeDefined();
const retrieved = await node.get(cid);
(0, vitest_1.expect)(retrieved).not.toBeNull();
if (retrieved) {
(0, vitest_1.expect)(new TextDecoder().decode(retrieved)).toBe('test data');
}
});
(0, vitest_1.it)('should handle non-existent CIDs', async () => {
mockBlockstore.get.mockRejectedValueOnce(new Error('Not found'));
const result = await node.get('bafkreiern4acpjlva5gookrtc534gr4nmuj7dy3qvcq5txgc6vqxe7wjqe');
(0, vitest_1.expect)(result).toBeNull();
});
});
(0, vitest_1.describe)('Pin Operations', () => {
(0, vitest_1.beforeEach)(async () => {
await node.init();
});
(0, vitest_1.it)('should pin and unpin content', async () => {
const data = new TextEncoder().encode('test data');
// Mock the blockstore operations for add
mockBlockstore.put.mockResolvedValueOnce(undefined);
const cid = await node.add(data);
// Mock pin operations
mockBlockstore.has.mockResolvedValueOnce(true);
await node.pin(cid);
const pinnedCids = await node.getPinnedCids();
(0, vitest_1.expect)(pinnedCids).toContain(cid);
await node.unpin(cid);
const afterUnpinCids = await node.getPinnedCids();
(0, vitest_1.expect)(afterUnpinCids).not.toContain(cid);
});
});
(0, vitest_1.describe)('Network Operations', () => {
(0, vitest_1.it)('should handle offline mode', async () => {
node = new ipfsNode_1.IpfsNode({
storage: 'memory',
enableNetworking: false
});
await node.init();
const addrs = node.getMultiaddrs();
(0, vitest_1.expect)(addrs).toHaveLength(0);
});
(0, vitest_1.it)('should handle online mode', async () => {
node = new ipfsNode_1.IpfsNode({
storage: 'memory',
enableNetworking: true
});
await node.init();
const addrs = node.getMultiaddrs();
(0, vitest_1.expect)(addrs.length).toBeGreaterThan(0);
});
});
(0, vitest_1.describe)('Error Handling', () => {
(0, vitest_1.it)('should handle operations before initialization', async () => {
const data = new TextEncoder().encode('test data');
await (0, vitest_1.expect)(node.add(data)).rejects.toThrow('IPFS node not initialized');
});
(0, vitest_1.it)('should handle cleanup after stop', async () => {
const node = new ipfsNode_1.IpfsNode({ storage: 'memory' });
// Setup mocks for initialization
const mockHelia = {
blockstore: mockBlockstore,
pins: {
add: vitest_1.vi.fn(),
rm: vitest_1.vi.fn(),
ls: vitest_1.vi.fn()
},
stop: vitest_1.vi.fn(),
libp2p: {},
datastore: {},
logger: console,
routing: {},
start: vitest_1.vi.fn(),
isStarted: vitest_1.vi.fn()
}; // Type assertion needed for complex Helia type
vitest_1.vi.mocked(helia_1.createHelia).mockResolvedValueOnce(mockHelia);
// Initialize the node
await node.init();
// Setup mock for successful add operation
mockBlockstore.put.mockResolvedValueOnce(undefined);
const mockDigest = new Uint8Array(32).fill(1); // Fill with some data instead of zeros
vitest_1.vi.mocked(sha2_1.sha256.digest).mockResolvedValueOnce({
code: sha2_1.sha256.code,
size: 32,
digest: mockDigest,
bytes: mockDigest
});
// Mock CID behavior
const mockCid = {
toString: () => 'bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi',
toV1: () => mockCid
};
vitest_1.vi.spyOn(multiformats_1.CID, 'createV1').mockReturnValue(mockCid);
vitest_1.vi.spyOn(multiformats_1.CID, 'parse').mockReturnValue(mockCid);
// Add some data
const data = new TextEncoder().encode('test data');
const cid = await node.add(data);
// Stop the node
await node.stop();
// Verify that operations after stop throw the correct error
await (0, vitest_1.expect)(node.get(cid)).rejects.toThrow('IPFS node not initialized');
await (0, vitest_1.expect)(node.add(data)).rejects.toThrow('IPFS node not initialized');
await (0, vitest_1.expect)(node.pin(cid)).rejects.toThrow('IPFS node not initialized');
});
});
});
//# sourceMappingURL=ipfsNode.test.js.map