filecoin-pin
Version:
IPFS Pinning Service API implementation that pins to Filecoin's PDP service
197 lines (159 loc) • 6.17 kB
text/typescript
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
import { initializeSynapse, getSynapseService, uploadToSynapse, resetSynapseService } from '../../synapse-service.js'
import { createConfig } from '../../config.js'
import { createLogger } from '../../logger.js'
import type { Config } from '../../config.js'
// Mock the Synapse SDK
vi.mock('@filoz/synapse-sdk', async () => await import('../mocks/synapse-sdk.js'))
describe('synapse-service', () => {
let config: Config
let logger: ReturnType<typeof createLogger>
beforeEach(() => {
// Create test config with Synapse enabled
config = {
...createConfig(),
privateKey: '0x0000000000000000000000000000000000000000000000000000000000000001', // Fake test key
rpcUrl: 'wss://wss.calibration.node.glif.io/apigw/lotus/rpc/v1'
}
logger = createLogger(config)
// Reset the service instances
resetSynapseService()
vi.clearAllMocks()
})
afterEach(() => {
vi.clearAllMocks()
})
describe('initializeSynapse', () => {
it('should throw error when private key is not configured', async () => {
config.privateKey = undefined
await expect(initializeSynapse(config, logger))
.rejects.toThrow('PRIVATE_KEY environment variable is required')
})
it('should initialize Synapse when private key is configured', async () => {
const result = await initializeSynapse(config, logger)
expect(result).not.toBeNull()
expect(result?.synapse).toBeDefined()
expect(result?.storage).toBeDefined()
})
it('should log initialization events', async () => {
const infoSpy = vi.spyOn(logger, 'info')
await initializeSynapse(config, logger)
// Check that initialization logs were called
expect(infoSpy).toHaveBeenCalledWith(
expect.objectContaining({
hasPrivateKey: true,
rpcUrl: config.rpcUrl
}),
'Initializing Synapse'
)
expect(infoSpy).toHaveBeenCalledWith(
expect.objectContaining({ event: 'synapse.init' }),
'Initializing Synapse SDK'
)
})
it('should call provider selection callback', async () => {
const callbacks: any[] = []
const originalCreate = (await import('@filoz/synapse-sdk')).Synapse.create
// Capture callbacks
vi.mocked(originalCreate).mockImplementationOnce(async (options) => {
const synapse = await originalCreate(options)
const originalCreateStorage = synapse.createStorage.bind(synapse)
synapse.createStorage = async (opts: any) => {
if (opts?.callbacks?.onProviderSelected != null) {
callbacks.push(opts.callbacks.onProviderSelected)
}
return await originalCreateStorage(opts)
}
return synapse
})
await initializeSynapse(config, logger)
expect(callbacks.length).toBeGreaterThan(0)
})
})
describe('getSynapseService', () => {
it('should return null when not initialized', () => {
// Ensure service is reset
resetSynapseService()
const result = getSynapseService()
expect(result).toBeNull()
})
it('should return service after initialization', async () => {
await initializeSynapse(config, logger)
const result = getSynapseService()
expect(result).not.toBeNull()
expect(result?.synapse).toBeDefined()
expect(result?.storage).toBeDefined()
})
})
describe('uploadToSynapse', () => {
beforeEach(async () => {
await initializeSynapse(config, logger)
})
it('should throw error when service is not initialized', async () => {
// Reset service to ensure it's not initialized
resetSynapseService()
const data = new Uint8Array([1, 2, 3])
await expect(uploadToSynapse(data, 'pin-123', logger))
.rejects.toThrow('Synapse service not initialized')
})
it('should upload data successfully', async () => {
const data = new Uint8Array([1, 2, 3])
const pinId = 'pin-123'
const result = await uploadToSynapse(data, pinId, logger)
expect(result).toHaveProperty('commp')
expect(result).toHaveProperty('rootId')
expect(result).toHaveProperty('proofSetId')
expect(result.commp).toMatch(/^baga6ea4seaq/)
expect(result.proofSetId).toBe('proof-set-123')
})
it('should log upload events', async () => {
const infoSpy = vi.spyOn(logger, 'info')
const data = new Uint8Array([1, 2, 3])
const pinId = 'pin-456'
await uploadToSynapse(data, pinId, logger)
expect(infoSpy).toHaveBeenCalledWith(
expect.objectContaining({
event: 'synapse.upload.start',
pinId,
size: data.length
}),
'Starting Synapse upload'
)
expect(infoSpy).toHaveBeenCalledWith(
expect.objectContaining({
event: 'synapse.upload.complete',
pinId
}),
'Synapse upload completed successfully'
)
})
it('should call upload callbacks', async () => {
let uploadCompleteCallbackCalled = false
let rootAddedCallbackCalled = false
// Mock the storage upload to capture callbacks
const service = getSynapseService()
if ((service?.storage) != null) {
const originalUpload = service.storage.upload.bind(service.storage)
service.storage.upload = async (data: any, callbacks: any) => {
// Override callbacks to track calls
const wrappedCallbacks = {
...callbacks,
onUploadComplete: (commp: string) => {
uploadCompleteCallbackCalled = true
callbacks?.onUploadComplete?.(commp)
},
onRootAdded: () => {
rootAddedCallbackCalled = true
callbacks?.onRootAdded?.()
}
}
return await originalUpload(data, wrappedCallbacks)
}
}
const data = new Uint8Array([1, 2, 3])
await uploadToSynapse(data, 'pin-789', logger)
expect(uploadCompleteCallbackCalled).toBe(true)
expect(rootAddedCallbackCalled).toBe(true)
})
})
})