- Instructions:
- 1. Start your fonstr server
- 2. Open this file in a browser
- 3. Click the test buttons below
- 4. Check that requests work without CORS errors
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/test/cors-test.js b/test/cors-test.js
deleted file mode 100644
index 831c930..0000000
--- a/test/cors-test.js
+++ /dev/null
@@ -1,113 +0,0 @@
-/**
- * Basic CORS test using curl to verify headers
- */
-
-import { spawn } from 'child_process'
-
-const SERVER_URL = 'http://localhost:3000'
-const TEST_PUBKEY = '124c0fa99407182ece5a24fad9b7f6674902fc422843d3128d38a0afbee0fdd2'
-
-console.log('CORS Test for DID Endpoints')
-console.log('============================')
-
-function runCurlTest(description, url, method = 'GET') {
- return new Promise((resolve, reject) => {
- console.log(`\n${description}`)
- console.log(`URL: ${url}`)
- console.log(`Method: ${method}`)
-
- const curl = spawn('curl', [
- '-I', // Headers only
- '-X', method,
- '-H', 'Origin: https://example.com', // Simulate cross-origin request
- url
- ])
-
- let output = ''
-
- curl.stdout.on('data', (data) => {
- output += data.toString()
- })
-
- curl.stderr.on('data', (data) => {
- output += data.toString()
- })
-
- curl.on('close', (code) => {
- console.log(`Response Headers:`)
- console.log(output)
-
- // Check for CORS headers
- const hasAccessControlAllowOrigin = output.includes('Access-Control-Allow-Origin')
- const hasAccessControlAllowMethods = output.includes('Access-Control-Allow-Methods')
-
- if (hasAccessControlAllowOrigin && hasAccessControlAllowMethods) {
- console.log('ā CORS headers present')
- resolve(true)
- } else {
- console.log('ā Missing CORS headers')
- resolve(false)
- }
- })
-
- curl.on('error', (err) => {
- console.log(`ā Error: ${err.message}`)
- resolve(false)
- })
- })
-}
-
-async function runTests() {
- console.log('Starting CORS tests...')
- console.log('Make sure your fonstr server is running on port 3000')
-
- const tests = [
- {
- description: 'Test 1: Query Parameter Format - GET',
- url: `${SERVER_URL}/.well-known/did.json?pubkey=${TEST_PUBKEY}`,
- method: 'GET'
- },
- {
- description: 'Test 2: Query Parameter Format - OPTIONS',
- url: `${SERVER_URL}/.well-known/did.json`,
- method: 'OPTIONS'
- },
- {
- description: 'Test 3: Path Parameter Format - GET',
- url: `${SERVER_URL}/.well-known/did/nostr/${TEST_PUBKEY}.json`,
- method: 'GET'
- },
- {
- description: 'Test 4: Path Parameter Format - OPTIONS',
- url: `${SERVER_URL}/.well-known/did/nostr/${TEST_PUBKEY}.json`,
- method: 'OPTIONS'
- },
- {
- description: 'Test 5: Error Response CORS',
- url: `${SERVER_URL}/.well-known/did.json?pubkey=invalid`,
- method: 'GET'
- }
- ]
-
- let passCount = 0
-
- for (const test of tests) {
- const passed = await runCurlTest(test.description, test.url, test.method)
- if (passed) passCount++
-
- // Small delay between tests
- await new Promise(resolve => setTimeout(resolve, 500))
- }
-
- console.log(`\n============================`)
- console.log(`CORS Test Results: ${passCount}/${tests.length} passed`)
-
- if (passCount === tests.length) {
- console.log('š All CORS tests passed!')
- } else {
- console.log('ā ļø Some CORS tests failed. Check server configuration.')
- }
-}
-
-// Run tests
-runTests().catch(console.error)
\ No newline at end of file
diff --git a/test/did-endpoint.test.js b/test/did-endpoint.test.js
deleted file mode 100644
index 81e1049..0000000
--- a/test/did-endpoint.test.js
+++ /dev/null
@@ -1,194 +0,0 @@
-/**
- * Tests for DID endpoint functionality
- */
-
-import { generateDIDDocument, isValidPubkey } from '../lib/did-endpoint.js'
-
-// Test data
-const validPubkey = '124c0fa99407182ece5a24fad9b7f6674902fc422843d3128d38a0afbee0fdd2'
-const invalidPubkeys = [
- '',
- null,
- undefined,
- '123', // Too short
- '124c0fa99407182ece5a24fad9b7f6674902fc422843d3128d38a0afbee0fdd', // 63 chars
- '124c0fa99407182ece5a24fad9b7f6674902fc422843d3128d38a0afbee0fdd22', // 65 chars
- 'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz', // Invalid hex
- '124c0fa99407182ece5a24fad9b7f6674902fc422843d3128d38a0afbee0fdd!', // Invalid char
-]
-
-// Test pubkey validation
-console.log('Testing pubkey validation...')
-console.assert(isValidPubkey(validPubkey) === true, 'Valid pubkey should return true')
-invalidPubkeys.forEach(pubkey => {
- console.assert(isValidPubkey(pubkey) === false, `Invalid pubkey "${pubkey}" should return false`)
-})
-console.log('ā Pubkey validation tests passed')
-
-// Test DID document generation
-console.log('\nTesting DID document generation...')
-const didDoc = generateDIDDocument(validPubkey)
-
-// Check structure
-console.assert(didDoc['@context'] !== undefined, 'DID document should have @context')
-console.assert(Array.isArray(didDoc['@context']), '@context should be an array')
-console.assert(didDoc['@context'].includes('https://w3id.org/did'), '@context should include DID context')
-console.assert(didDoc['@context'].includes('https://w3id.org/nostr/context'), '@context should include Nostr context')
-
-// Check ID
-const expectedDid = `did:nostr:${validPubkey.toLowerCase()}`
-console.assert(didDoc.id === expectedDid, `DID should be ${expectedDid}`)
-
-// Check verification method
-console.assert(Array.isArray(didDoc.verificationMethod), 'verificationMethod should be an array')
-console.assert(didDoc.verificationMethod.length === 1, 'Should have one verification method')
-
-const vm = didDoc.verificationMethod[0]
-console.assert(vm.id === `${expectedDid}#key1`, 'Verification method ID should be correct')
-console.assert(vm.type === 'Multikey', 'Verification method type should be Multikey')
-console.assert(vm.controller === expectedDid, 'Controller should be the DID')
-
-// Check multibase encoding
-const expectedMultibase = 'fe70102' + validPubkey.toLowerCase()
-console.assert(vm.publicKeyMultibase === expectedMultibase, 'publicKeyMultibase should be correctly encoded')
-
-// Check authentication and assertion
-console.assert(Array.isArray(didDoc.authentication), 'authentication should be an array')
-console.assert(didDoc.authentication.includes('#key1'), 'authentication should reference #key1')
-console.assert(Array.isArray(didDoc.assertionMethod), 'assertionMethod should be an array')
-console.assert(didDoc.assertionMethod.includes('#key1'), 'assertionMethod should reference #key1')
-
-console.log('ā DID document generation tests passed')
-
-// Test error handling
-console.log('\nTesting error handling...')
-invalidPubkeys.forEach(pubkey => {
- try {
- generateDIDDocument(pubkey)
- console.assert(false, `Should throw error for invalid pubkey "${pubkey}"`)
- } catch (error) {
- console.assert(error.message.includes('Invalid public key'), 'Error message should mention invalid public key')
- }
-})
-console.log('ā Error handling tests passed')
-
-// Test profile functionality
-console.log('\nTesting profile functionality...')
-
-// Test with valid profile
-const profileData = {
- name: 'Alice',
- about: 'Building the decentralized social web',
- picture: 'https://example.com/alice.jpg',
- nip05: 'alice@example.com',
- lud16: 'alice@getalby.com',
- website: 'https://alice.example.com',
- timestamp: 1737906600
-}
-
-const didDocWithProfile = generateDIDDocument(validPubkey, profileData)
-console.assert(didDocWithProfile.profile !== undefined, 'DID document should have profile field')
-console.assert(didDocWithProfile.profile.name === 'Alice', 'Profile name should match')
-console.assert(didDocWithProfile.profile.about === 'Building the decentralized social web', 'Profile about should match')
-console.assert(didDocWithProfile.profile.picture === 'https://example.com/alice.jpg', 'Profile picture should match')
-console.assert(didDocWithProfile.profile.nip05 === 'alice@example.com', 'Profile nip05 should match')
-console.assert(didDocWithProfile.profile.lud16 === 'alice@getalby.com', 'Profile lud16 should match')
-console.assert(didDocWithProfile.profile.website === 'https://alice.example.com', 'Profile website should match')
-console.assert(didDocWithProfile.profile.timestamp === 1737906600, 'Profile timestamp should match')
-
-// Test with partial profile
-const partialProfile = { name: 'Bob' }
-const didDocPartial = generateDIDDocument(validPubkey, partialProfile)
-console.assert(didDocPartial.profile.name === 'Bob', 'Partial profile name should match')
-console.assert(didDocPartial.profile.about === undefined, 'Partial profile should not have undefined fields')
-
-// Test with empty profile
-const emptyProfile = {}
-const didDocEmpty = generateDIDDocument(validPubkey, emptyProfile)
-console.assert(didDocEmpty.profile === undefined, 'Empty profile should be removed')
-
-// Test with invalid profile data types
-const invalidProfile = { name: 123, about: null, timestamp: 'invalid' }
-const didDocInvalid = generateDIDDocument(validPubkey, invalidProfile)
-console.assert(didDocInvalid.profile === undefined, 'Invalid profile data should result in no profile')
-
-// Test without profile (backward compatibility)
-const didDocNoProfile = generateDIDDocument(validPubkey)
-console.assert(didDocNoProfile.profile === undefined, 'DID document without profile should work')
-
-console.log('ā Profile functionality tests passed')
-
-// Test follows functionality
-console.log('\nTesting follows functionality...')
-
-// Test with valid follows
-const followsData = {
- pubkeys: [
- '32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245',
- '46fcbe3065eaf1ae7811465924e48923363ff3f526bd6f73d7c184147700e3a8'
- ],
- count: 2
-}
-
-const didDocWithFollows = generateDIDDocument(validPubkey, null, followsData)
-console.assert(Array.isArray(didDocWithFollows.follows), 'DID document should have follows array')
-console.assert(didDocWithFollows.follows.length === 2, 'Should have 2 follows')
-console.assert(didDocWithFollows.follows[0].startsWith('did:nostr:'), 'Follows should be DIDs')
-console.assert(didDocWithFollows.followsCount === 2, 'followsCount should match')
-
-// Test with complete DID document (profile + follows)
-const didDocComplete = generateDIDDocument(validPubkey, profileData, followsData)
-console.assert(didDocComplete.profile !== undefined, 'Complete DID should have profile')
-console.assert(Array.isArray(didDocComplete.follows), 'Complete DID should have follows')
-console.assert(didDocComplete.followsCount === 2, 'Complete DID should have followsCount')
-
-// Test with invalid pubkeys in follows (should filter out)
-const invalidFollowsData = {
- pubkeys: [
- '32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245', // valid
- 'invalid-pubkey', // invalid
- '46fcbe3065eaf1ae7811465924e48923363ff3f526bd6f73d7c184147700e3a8' // valid
- ],
- count: 3
-}
-
-const didDocFiltered = generateDIDDocument(validPubkey, null, invalidFollowsData)
-console.assert(didDocFiltered.follows.length === 2, 'Should filter out invalid pubkeys')
-console.assert(didDocFiltered.followsCount === 3, 'followsCount should preserve original count')
-
-// Test with empty follows
-const emptyFollowsData = { pubkeys: [], count: 0 }
-const didDocEmptyFollows = generateDIDDocument(validPubkey, null, emptyFollowsData)
-console.assert(didDocEmptyFollows.follows === undefined, 'Empty follows should be removed')
-console.assert(didDocEmptyFollows.followsCount === undefined, 'Empty followsCount should be removed')
-
-// Test with truncated follows and service endpoint
-const truncatedFollowsData = {
- pubkeys: [
- '32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245',
- '46fcbe3065eaf1ae7811465924e48923363ff3f526bd6f73d7c184147700e3a8'
- ],
- count: 5234,
- truncated: true,
- serviceEndpoint: 'https://api.example.com/did/follows/{did}'
-}
-
-const didDocTruncated = generateDIDDocument(validPubkey, null, truncatedFollowsData)
-console.assert(didDocTruncated.follows.length === 2, 'Should include truncated follows')
-console.assert(didDocTruncated.followsCount === 5234, 'Should show total count')
-console.assert(Array.isArray(didDocTruncated.service), 'Should have service array')
-console.assert(didDocTruncated.service.some(s => s.type === 'FollowsEndpoint'), 'Should have FollowsEndpoint service')
-
-console.log('ā Follows functionality tests passed')
-
-console.log('\nā All tests passed!')
-
-// Output example DID documents
-console.log('\nExample Minimal DID Document:')
-console.log(JSON.stringify(didDoc, null, 2))
-
-console.log('\nExample DID Document with Profile:')
-console.log(JSON.stringify(didDocWithProfile, null, 2))
-
-console.log('\nExample Complete DID Document (Profile + Follows):')
-console.log(JSON.stringify(didDocComplete, null, 2))
\ No newline at end of file
diff --git a/test/integration-test.js b/test/integration-test.js
deleted file mode 100644
index 1f54a00..0000000
--- a/test/integration-test.js
+++ /dev/null
@@ -1,161 +0,0 @@
-/**
- * Integration test for DID endpoint with profile data
- */
-
-import { generateDIDDocument } from '../lib/did-endpoint.js'
-
-// Test the integration logic that would be in index.js
-console.log('Testing DID endpoint integration with profile data...')
-
-const validPubkey = '124c0fa99407182ece5a24fad9b7f6674902fc422843d3128d38a0afbee0fdd2'
-
-// Simulate events array with a kind 0 event (like in relay memory)
-const events = [
- {
- id: 'test-event-id',
- pubkey: validPubkey,
- kind: 0,
- content: JSON.stringify({
- name: 'Alice',
- about: 'Building the decentralized social web',
- picture: 'https://example.com/alice.jpg',
- nip05: 'alice@example.com',
- website: 'https://alice.example.com'
- }),
- created_at: 1737906600,
- tags: [],
- sig: 'fake-signature'
- },
- {
- id: 'contact-list-event',
- pubkey: validPubkey,
- kind: 3,
- content: '',
- created_at: 1737906800,
- tags: [
- ['p', '32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245'],
- ['p', '46fcbe3065eaf1ae7811465924e48923363ff3f526bd6f73d7c184147700e3a8'],
- ['p', '82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2']
- ],
- sig: 'fake-signature'
- },
- {
- id: 'other-event',
- pubkey: 'different-pubkey-000000000000000000000000000000000000000000000000000',
- kind: 1,
- content: 'Hello world',
- created_at: 1737906700,
- tags: [],
- sig: 'fake-signature'
- }
-]
-
-// Simulate the logic from index.js
-function simulateDIDEndpoint(pubkey, events) {
- // Find metadata event (kind 0) for this pubkey
- const metadataEvent = events.find(e =>
- e.kind === 0 && e.pubkey === pubkey
- )
-
- // Parse metadata if available
- let profile = null
- if (metadataEvent) {
- try {
- const metadata = JSON.parse(metadataEvent.content)
- profile = {
- ...metadata,
- timestamp: metadataEvent.created_at
- }
- } catch (e) {
- // Invalid metadata, ignore
- }
- }
-
- // Find most recent contact list event (kind 3) for this pubkey
- const contactListEvents = events.filter(e =>
- e.kind === 3 && e.pubkey === pubkey
- )
- const contactListEvent = contactListEvents.length > 0
- ? contactListEvents.reduce((latest, current) =>
- current.created_at > latest.created_at ? current : latest
- )
- : null
-
- // Parse follows if available
- let follows = null
- if (contactListEvent) {
- try {
- // Extract pubkeys from kind 3 event tags (p tags)
- const followPubkeys = contactListEvent.tags
- .filter(tag => tag[0] === 'p' && tag[1] && /^[0-9a-f]{64}$/i.test(tag[1]))
- .map(tag => tag[1].toLowerCase())
-
- if (followPubkeys.length > 0) {
- follows = {
- pubkeys: followPubkeys,
- count: followPubkeys.length
- }
- }
- } catch (e) {
- // Invalid contact list, ignore
- }
- }
-
- return generateDIDDocument(pubkey, profile, follows)
-}
-
-// Test 1: Pubkey with profile and follows data
-const didComplete = simulateDIDEndpoint(validPubkey, events)
-console.assert(didComplete.profile !== undefined, 'Should have profile when kind 0 event exists')
-console.assert(didComplete.profile.name === 'Alice', 'Profile name should match kind 0 event')
-console.assert(didComplete.profile.timestamp === 1737906600, 'Profile timestamp should match created_at')
-console.assert(Array.isArray(didComplete.follows), 'Should have follows when kind 3 event exists')
-console.assert(didComplete.follows.length === 3, 'Should have 3 follows from kind 3 event')
-console.assert(didComplete.followsCount === 3, 'followsCount should match')
-console.assert(didComplete.follows[0].startsWith('did:nostr:'), 'Follows should be DIDs')
-
-// Test 2: Pubkey without profile data
-const unknownPubkey = '0000000000000000000000000000000000000000000000000000000000000000'
-const didWithoutData = simulateDIDEndpoint(unknownPubkey, events)
-console.assert(didWithoutData.profile === undefined, 'Should not have profile when no kind 0 event exists')
-console.assert(didWithoutData.follows === undefined, 'Should not have follows when no kind 3 event exists')
-
-// Test 3: Pubkey with invalid JSON in kind 0
-const eventsWithInvalidJson = [
- {
- id: 'invalid-event',
- pubkey: validPubkey,
- kind: 0,
- content: 'invalid json',
- created_at: 1737906600,
- tags: [],
- sig: 'fake-signature'
- }
-]
-const didWithInvalidProfile = simulateDIDEndpoint(validPubkey, eventsWithInvalidJson)
-console.assert(didWithInvalidProfile.profile === undefined, 'Should not have profile when JSON is invalid')
-
-// Test 4: Multiple kind 3 events - should use most recent
-const eventsWithMultipleContacts = [
- ...events,
- {
- id: 'older-contact-list',
- pubkey: validPubkey,
- kind: 3,
- content: '',
- created_at: 1737906700, // Earlier timestamp
- tags: [
- ['p', 'aaaa1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245']
- ],
- sig: 'fake-signature'
- }
-]
-
-const didWithMultipleContacts = simulateDIDEndpoint(validPubkey, eventsWithMultipleContacts)
-console.assert(didWithMultipleContacts.follows.length === 3, 'Should use most recent contact list (3 follows, not 1)')
-
-console.log('ā Integration tests passed!')
-
-// Show example output
-console.log('\nExample Complete DID with profile and follows:')
-console.log(JSON.stringify(didComplete, null, 2))
\ No newline at end of file