move to bun and bun:test and remove jest.

This commit is contained in:
fiatjaf 2023-12-16 14:53:32 -03:00
parent 1357642575
commit 3d541e537e
No known key found for this signature in database
GPG Key ID: BAD43C4BE5C1A3A1
36 changed files with 130 additions and 4356 deletions

View File

@ -139,13 +139,5 @@
"wrap-iife": [2, "any"], "wrap-iife": [2, "any"],
"yield-star-spacing": [2, "both"], "yield-star-spacing": [2, "both"],
"yoda": [0] "yoda": [0]
}, }
"overrides": [
{
"files": ["**/*.test.ts"],
"env": { "jest/globals": true },
"plugins": ["jest"],
"extends": ["plugin:jest/recommended"]
}
]
} }

View File

@ -1,15 +1,10 @@
#!/usr/bin/env node const fs = require('node:fs')
const fs = require('fs')
const esbuild = require('esbuild') const esbuild = require('esbuild')
const { join } = require('path'); const { join } = require('path')
const entryPoints = fs.readdirSync(process.cwd()) const entryPoints = fs
.filter( .readdirSync(process.cwd())
(file) => .filter(file => file.endsWith('.ts') && !file.endsWith('test.ts') && fs.statSync(join(process.cwd(), file)).isFile())
file.endsWith(".ts") && !file.endsWith("test.ts") &&
fs.statSync(join(process.cwd(), file)).isFile()
);
let common = { let common = {
entryPoints, entryPoints,

BIN
bun.lockb Executable file

Binary file not shown.

View File

@ -1,3 +1,5 @@
import { describe, test, expect } from 'bun:test'
import { import {
finishEvent, finishEvent,
serializeEvent, serializeEvent,
@ -12,7 +14,7 @@ import { ShortTextNote } from './kinds.ts'
describe('Event', () => { describe('Event', () => {
describe('finishEvent', () => { describe('finishEvent', () => {
it('should create a signed event from a template', () => { test('should create a signed event from a template', () => {
const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf' const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf'
const publicKey = getPublicKey(privateKey) const publicKey = getPublicKey(privateKey)
@ -36,7 +38,7 @@ describe('Event', () => {
}) })
describe('serializeEvent', () => { describe('serializeEvent', () => {
it('should serialize a valid event object', () => { test('should serialize a valid event object', () => {
const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf' const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf'
const publicKey = getPublicKey(privateKey) const publicKey = getPublicKey(privateKey)
@ -62,7 +64,7 @@ describe('Event', () => {
) )
}) })
it('should throw an error for an invalid event object', () => { test('should throw an error for an invalid event object', () => {
const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf' const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf'
const publicKey = getPublicKey(privateKey) const publicKey = getPublicKey(privateKey)
@ -81,7 +83,7 @@ describe('Event', () => {
}) })
describe('getEventHash', () => { describe('getEventHash', () => {
it('should return the correct event hash', () => { test('should return the correct event hash', () => {
const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf' const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf'
const publicKey = getPublicKey(privateKey) const publicKey = getPublicKey(privateKey)
@ -101,7 +103,7 @@ describe('Event', () => {
}) })
describe('validateEvent', () => { describe('validateEvent', () => {
it('should return true for a valid event object', () => { test('should return true for a valid event object', () => {
const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf' const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf'
const publicKey = getPublicKey(privateKey) const publicKey = getPublicKey(privateKey)
@ -118,7 +120,7 @@ describe('Event', () => {
expect(isValid).toEqual(true) expect(isValid).toEqual(true)
}) })
it('should return false for a non object event', () => { test('should return false for a non object event', () => {
const nonObjectEvent = '' const nonObjectEvent = ''
const isValid = validateEvent(nonObjectEvent) const isValid = validateEvent(nonObjectEvent)
@ -126,7 +128,7 @@ describe('Event', () => {
expect(isValid).toEqual(false) expect(isValid).toEqual(false)
}) })
it('should return false for an event object with missing properties', () => { test('should return false for an event object with missing properties', () => {
const invalidEvent = { const invalidEvent = {
kind: ShortTextNote, kind: ShortTextNote,
tags: [], tags: [],
@ -138,7 +140,7 @@ describe('Event', () => {
expect(isValid).toEqual(false) expect(isValid).toEqual(false)
}) })
it('should return false for an empty object', () => { test('should return false for an empty object', () => {
const emptyObj = {} const emptyObj = {}
const isValid = validateEvent(emptyObj) const isValid = validateEvent(emptyObj)
@ -146,7 +148,7 @@ describe('Event', () => {
expect(isValid).toEqual(false) expect(isValid).toEqual(false)
}) })
it('should return false for an object with invalid properties', () => { test('should return false for an object with invalid properties', () => {
const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf' const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf'
const publicKey = getPublicKey(privateKey) const publicKey = getPublicKey(privateKey)
@ -162,7 +164,7 @@ describe('Event', () => {
expect(isValid).toEqual(false) expect(isValid).toEqual(false)
}) })
it('should return false for an object with an invalid public key', () => { test('should return false for an object with an invalid public key', () => {
const invalidEvent = { const invalidEvent = {
kind: 1, kind: 1,
tags: [], tags: [],
@ -176,7 +178,7 @@ describe('Event', () => {
expect(isValid).toEqual(false) expect(isValid).toEqual(false)
}) })
it('should return false for an object with invalid tags', () => { test('should return false for an object with invalid tags', () => {
const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf' const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf'
const publicKey = getPublicKey(privateKey) const publicKey = getPublicKey(privateKey)
@ -195,7 +197,7 @@ describe('Event', () => {
}) })
describe('verifySignature', () => { describe('verifySignature', () => {
it('should return true for a valid event signature', () => { test('should return true for a valid event signature', () => {
const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf' const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf'
const event = finishEvent( const event = finishEvent(
@ -213,7 +215,7 @@ describe('Event', () => {
expect(isValid).toEqual(true) expect(isValid).toEqual(true)
}) })
it('should return false for an invalid event signature', () => { test('should return false for an invalid event signature', () => {
const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf' const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf'
const { [verifiedSymbol]: _, ...event } = finishEvent( const { [verifiedSymbol]: _, ...event } = finishEvent(
@ -234,7 +236,7 @@ describe('Event', () => {
expect(isValid).toEqual(false) expect(isValid).toEqual(false)
}) })
it('should return false when verifying an event with a different private key', () => { test('should return false when verifying an event with a different private key', () => {
const privateKey1 = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf' const privateKey1 = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf'
const privateKey2 = '5b4a34f4e4b23c63ad55a35e3f84a3b53d96dbf266edf521a8358f71d19cbf67' const privateKey2 = '5b4a34f4e4b23c63ad55a35e3f84a3b53d96dbf266edf521a8358f71d19cbf67'
@ -259,7 +261,7 @@ describe('Event', () => {
expect(isValid).toEqual(false) expect(isValid).toEqual(false)
}) })
it('should return false for an invalid event id', () => { test('should return false for an invalid event id', () => {
const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf' const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf'
const { [verifiedSymbol]: _, ...event } = finishEvent( const { [verifiedSymbol]: _, ...event } = finishEvent(
@ -282,7 +284,7 @@ describe('Event', () => {
}) })
describe('getSignature', () => { describe('getSignature', () => {
it('should produce the correct signature for an event object', () => { test('should produce the correct signature for an event object', () => {
const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf' const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf'
const publicKey = getPublicKey(privateKey) const publicKey = getPublicKey(privateKey)
@ -308,7 +310,7 @@ describe('Event', () => {
expect(isValid).toEqual(true) expect(isValid).toEqual(true)
}) })
it('should not sign an event with different private key', () => { test('should not sign an event with different private key', () => {
const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf' const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf'
const publicKey = getPublicKey(privateKey) const publicKey = getPublicKey(privateKey)

View File

@ -1,3 +1,4 @@
import { test, expect } from 'bun:test'
import { matchEventId, matchEventKind, getSubscriptionId } from './fakejson.ts' import { matchEventId, matchEventKind, getSubscriptionId } from './fakejson.ts'
test('match id', () => { test('match id', () => {

View File

@ -1,9 +1,10 @@
import { describe, test, expect } from 'bun:test'
import { matchFilter, matchFilters, mergeFilters } from './filter.ts' import { matchFilter, matchFilters, mergeFilters } from './filter.ts'
import { buildEvent } from './test-helpers.ts' import { buildEvent } from './test-helpers.ts'
describe('Filter', () => { describe('Filter', () => {
describe('matchFilter', () => { describe('matchFilter', () => {
it('should return true when all filter conditions are met', () => { test('should return true when all filter conditions are met', () => {
const filter = { const filter = {
ids: ['123', '456'], ids: ['123', '456'],
kinds: [1, 2, 3], kinds: [1, 2, 3],
@ -26,7 +27,7 @@ describe('Filter', () => {
expect(result).toEqual(true) expect(result).toEqual(true)
}) })
it('should return false when the event id is not in the filter', () => { test('should return false when the event id is not in the filter', () => {
const filter = { ids: ['123', '456'] } const filter = { ids: ['123', '456'] }
const event = buildEvent({ id: '789' }) const event = buildEvent({ id: '789' })
@ -36,7 +37,7 @@ describe('Filter', () => {
expect(result).toEqual(false) expect(result).toEqual(false)
}) })
it('should return true when the event id starts with a prefix', () => { test('should return true when the event id starts with a prefix', () => {
const filter = { ids: ['22', '00'] } const filter = { ids: ['22', '00'] }
const event = buildEvent({ id: '001' }) const event = buildEvent({ id: '001' })
@ -46,7 +47,7 @@ describe('Filter', () => {
expect(result).toEqual(true) expect(result).toEqual(true)
}) })
it('should return false when the event kind is not in the filter', () => { test('should return false when the event kind is not in the filter', () => {
const filter = { kinds: [1, 2, 3] } const filter = { kinds: [1, 2, 3] }
const event = buildEvent({ kind: 4 }) const event = buildEvent({ kind: 4 })
@ -56,7 +57,7 @@ describe('Filter', () => {
expect(result).toEqual(false) expect(result).toEqual(false)
}) })
it('should return false when the event author is not in the filter', () => { test('should return false when the event author is not in the filter', () => {
const filter = { authors: ['abc', 'def'] } const filter = { authors: ['abc', 'def'] }
const event = buildEvent({ pubkey: 'ghi' }) const event = buildEvent({ pubkey: 'ghi' })
@ -66,7 +67,7 @@ describe('Filter', () => {
expect(result).toEqual(false) expect(result).toEqual(false)
}) })
it('should return false when a tag is not present in the event', () => { test('should return false when a tag is not present in the event', () => {
const filter = { '#tag': ['value1', 'value2'] } const filter = { '#tag': ['value1', 'value2'] }
const event = buildEvent({ tags: [['not_tag', 'value1']] }) const event = buildEvent({ tags: [['not_tag', 'value1']] })
@ -76,7 +77,7 @@ describe('Filter', () => {
expect(result).toEqual(false) expect(result).toEqual(false)
}) })
it('should return false when a tag value is not present in the event', () => { test('should return false when a tag value is not present in the event', () => {
const filter = { '#tag': ['value1', 'value2'] } const filter = { '#tag': ['value1', 'value2'] }
const event = buildEvent({ tags: [['tag', 'value3']] }) const event = buildEvent({ tags: [['tag', 'value3']] })
@ -86,7 +87,7 @@ describe('Filter', () => {
expect(result).toEqual(false) expect(result).toEqual(false)
}) })
it('should return true when filter has tags that is present in the event', () => { test('should return true when filter has tags that is present in the event', () => {
const filter = { '#tag1': ['foo'] } const filter = { '#tag1': ['foo'] }
const event = buildEvent({ const event = buildEvent({
@ -105,7 +106,7 @@ describe('Filter', () => {
expect(result).toEqual(true) expect(result).toEqual(true)
}) })
it('should return false when the event is before the filter since value', () => { test('should return false when the event is before the filter since value', () => {
const filter = { since: 100 } const filter = { since: 100 }
const event = buildEvent({ created_at: 50 }) const event = buildEvent({ created_at: 50 })
@ -115,7 +116,7 @@ describe('Filter', () => {
expect(result).toEqual(false) expect(result).toEqual(false)
}) })
it('should return true when the timestamp of event is equal to the filter since value', () => { test('should return true when the timestamp of event is equal to the filter since value', () => {
const filter = { since: 100 } const filter = { since: 100 }
const event = buildEvent({ created_at: 100 }) const event = buildEvent({ created_at: 100 })
@ -125,7 +126,7 @@ describe('Filter', () => {
expect(result).toEqual(true) expect(result).toEqual(true)
}) })
it('should return false when the event is after the filter until value', () => { test('should return false when the event is after the filter until value', () => {
const filter = { until: 100 } const filter = { until: 100 }
const event = buildEvent({ created_at: 150 }) const event = buildEvent({ created_at: 150 })
@ -135,7 +136,7 @@ describe('Filter', () => {
expect(result).toEqual(false) expect(result).toEqual(false)
}) })
it('should return true when the timestamp of event is equal to the filter until value', () => { test('should return true when the timestamp of event is equal to the filter until value', () => {
const filter = { until: 100 } const filter = { until: 100 }
const event = buildEvent({ created_at: 100 }) const event = buildEvent({ created_at: 100 })
@ -147,7 +148,7 @@ describe('Filter', () => {
}) })
describe('matchFilters', () => { describe('matchFilters', () => {
it('should return true when at least one filter matches the event', () => { test('should return true when at least one filter matches the event', () => {
const filters = [ const filters = [
{ ids: ['123'], kinds: [1], authors: ['abc'] }, { ids: ['123'], kinds: [1], authors: ['abc'] },
{ ids: ['456'], kinds: [2], authors: ['def'] }, { ids: ['456'], kinds: [2], authors: ['def'] },
@ -161,7 +162,7 @@ describe('Filter', () => {
expect(result).toEqual(true) expect(result).toEqual(true)
}) })
it('should return true when at least one prefix matches the event', () => { test('should return true when at least one prefix matches the event', () => {
const filters = [ const filters = [
{ ids: ['1'], kinds: [1], authors: ['a'] }, { ids: ['1'], kinds: [1], authors: ['a'] },
{ ids: ['4'], kinds: [2], authors: ['d'] }, { ids: ['4'], kinds: [2], authors: ['d'] },
@ -175,7 +176,7 @@ describe('Filter', () => {
expect(result).toEqual(true) expect(result).toEqual(true)
}) })
it('should return true when event matches one or more filters and some have limit set', () => { test('should return true when event matches one or more filters and some have limit set', () => {
const filters = [ const filters = [
{ ids: ['123'], limit: 1 }, { ids: ['123'], limit: 1 },
{ kinds: [1], limit: 2 }, { kinds: [1], limit: 2 },
@ -194,7 +195,7 @@ describe('Filter', () => {
expect(result).toEqual(true) expect(result).toEqual(true)
}) })
it('should return false when no filters match the event', () => { test('should return false when no filters match the event', () => {
const filters = [ const filters = [
{ ids: ['123'], kinds: [1], authors: ['abc'] }, { ids: ['123'], kinds: [1], authors: ['abc'] },
{ ids: ['456'], kinds: [2], authors: ['def'] }, { ids: ['456'], kinds: [2], authors: ['def'] },
@ -208,7 +209,7 @@ describe('Filter', () => {
expect(result).toEqual(false) expect(result).toEqual(false)
}) })
it('should return false when event matches none of the filters and some have limit set', () => { test('should return false when event matches none of the filters and some have limit set', () => {
const filters = [ const filters = [
{ ids: ['123'], limit: 1 }, { ids: ['123'], limit: 1 },
{ kinds: [1], limit: 2 }, { kinds: [1], limit: 2 },
@ -228,7 +229,7 @@ describe('Filter', () => {
}) })
describe('mergeFilters', () => { describe('mergeFilters', () => {
it('should merge filters', () => { test('should merge filters', () => {
expect(mergeFilters({ ids: ['a', 'b'], limit: 3 }, { authors: ['x'], ids: ['b', 'c'] })).toEqual({ expect(mergeFilters({ ids: ['a', 'b'], limit: 3 }, { authors: ['x'], ids: ['b', 'c'] })).toEqual({
ids: ['a', 'b', 'c'], ids: ['a', 'b', 'c'],
limit: 3, limit: 3,

View File

@ -1,5 +0,0 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
}

View File

@ -5,13 +5,13 @@ install-dependencies:
build: build:
rm -rf lib rm -rf lib
node build.js bun run build.js
test: test:
jest bun test
test-only file: test-only file:
jest {{file}} bun test {{file}}
emit-types: emit-types:
tsc # see tsconfig.json tsc # see tsconfig.json

View File

@ -1,3 +1,4 @@
import { test, expect } from 'bun:test'
import { generatePrivateKey, getPublicKey } from './keys.ts' import { generatePrivateKey, getPublicKey } from './keys.ts'
test('private key generation', () => { test('private key generation', () => {

View File

@ -1,3 +1,4 @@
import { test, expect } from 'bun:test'
import { classifyKind } from './kinds.ts' import { classifyKind } from './kinds.ts'
test('kind classification', () => { test('kind classification', () => {

View File

@ -1,3 +1,4 @@
import { test, expect } from 'bun:test'
import crypto from 'node:crypto' import crypto from 'node:crypto'
import { encrypt, decrypt } from './nip04.ts' import { encrypt, decrypt } from './nip04.ts'

View File

@ -1,3 +1,4 @@
import { test, expect } from 'bun:test'
import fetch from 'node-fetch' import fetch from 'node-fetch'
import { useFetchImplementation, queryProfile } from './nip05.ts' import { useFetchImplementation, queryProfile } from './nip05.ts'

View File

@ -1,3 +1,4 @@
import { test, expect } from 'bun:test'
import { privateKeyFromSeedWords } from './nip06.ts' import { privateKeyFromSeedWords } from './nip06.ts'
test('generate private key from a mnemonic', async () => { test('generate private key from a mnemonic', async () => {

View File

@ -1,3 +1,4 @@
import { describe, test, expect } from 'bun:test'
import { parse } from './nip10.ts' import { parse } from './nip10.ts'
describe('parse NIP10-referenced events', () => { describe('parse NIP10-referenced events', () => {

View File

@ -1,3 +1,4 @@
import { describe, test, expect } from 'bun:test'
import fetch from 'node-fetch' import fetch from 'node-fetch'
import { useFetchImplementation, fetchRelayInformation } from './nip11' import { useFetchImplementation, fetchRelayInformation } from './nip11'

View File

@ -1,3 +1,4 @@
import { test, expect } from 'bun:test'
import { getPow, minePow } from './nip13.ts' import { getPow, minePow } from './nip13.ts'
test('identifies proof-of-work difficulty', async () => { test('identifies proof-of-work difficulty', async () => {

View File

@ -1,3 +1,4 @@
import { describe, test, expect } from 'bun:test'
import { finishEvent } from './event.ts' import { finishEvent } from './event.ts'
import { getPublicKey } from './keys.ts' import { getPublicKey } from './keys.ts'
import { Repost, ShortTextNote } from './kinds.ts' import { Repost, ShortTextNote } from './kinds.ts'
@ -24,7 +25,7 @@ describe('finishRepostEvent + getRepostedEventPointer + getRepostedEvent', () =>
privateKey, privateKey,
) )
it('should create a signed event from a minimal template', () => { test('should create a signed event from a minimal template', () => {
const template = { const template = {
created_at: 1617932115, created_at: 1617932115,
} }
@ -53,7 +54,7 @@ describe('finishRepostEvent + getRepostedEventPointer + getRepostedEvent', () =>
expect(repostedEventFromContent).toEqual(repostedEvent) expect(repostedEventFromContent).toEqual(repostedEvent)
}) })
it('should create a signed event from a filled template', () => { test('should create a signed event from a filled template', () => {
const template = { const template = {
tags: [['nonstandard', 'tag']], tags: [['nonstandard', 'tag']],
content: '' as const, content: '' as const,
@ -82,12 +83,12 @@ describe('finishRepostEvent + getRepostedEventPointer + getRepostedEvent', () =>
const repostedEventFromContent = getRepostedEvent(event) const repostedEventFromContent = getRepostedEvent(event)
expect(repostedEventFromContent).toEqual(undefined) expect(repostedEventFromContent).toBeUndefined()
}) })
}) })
describe('getRepostedEventPointer', () => { describe('getRepostedEventPointer', () => {
it('should parse an event with only an `e` tag', () => { test('should parse an event with only an `e` tag', () => {
const event = buildEvent({ const event = buildEvent({
kind: Repost, kind: Repost,
tags: [['e', 'reposted event id', relayUrl]], tags: [['e', 'reposted event id', relayUrl]],
@ -96,7 +97,7 @@ describe('getRepostedEventPointer', () => {
const repostedEventPointer = getRepostedEventPointer(event) const repostedEventPointer = getRepostedEventPointer(event)
expect(repostedEventPointer!.id).toEqual('reposted event id') expect(repostedEventPointer!.id).toEqual('reposted event id')
expect(repostedEventPointer!.author).toEqual(undefined) expect(repostedEventPointer!.author).toBeUndefined()
expect(repostedEventPointer!.relays).toEqual([relayUrl]) expect(repostedEventPointer!.relays).toEqual([relayUrl])
}) })
}) })

View File

@ -1,3 +1,4 @@
import { test, expect } from 'bun:test'
import { generatePrivateKey, getPublicKey } from './keys.ts' import { generatePrivateKey, getPublicKey } from './keys.ts'
import { import {
decode, decode,

View File

@ -1,3 +1,4 @@
import { test, expect } from 'bun:test'
import { test as testRegex, parse } from './nip21.ts' import { test as testRegex, parse } from './nip21.ts'
test('test()', () => { test('test()', () => {

View File

@ -1,3 +1,4 @@
import { describe, test, expect } from 'bun:test'
import { finishEvent } from './event.ts' import { finishEvent } from './event.ts'
import { getPublicKey } from './keys.ts' import { getPublicKey } from './keys.ts'
import { Reaction, ShortTextNote } from './kinds.ts' import { Reaction, ShortTextNote } from './kinds.ts'
@ -21,7 +22,7 @@ describe('finishReactionEvent + getReactedEventPointer', () => {
privateKey, privateKey,
) )
it('should create a signed event from a minimal template', () => { test('should create a signed event from a minimal template', () => {
const template = { const template = {
created_at: 1617932115, created_at: 1617932115,
} }
@ -47,7 +48,7 @@ describe('finishReactionEvent + getReactedEventPointer', () => {
expect(reactedEventPointer!.author).toEqual(reactedEvent.pubkey) expect(reactedEventPointer!.author).toEqual(reactedEvent.pubkey)
}) })
it('should create a signed event from a filled template', () => { test('should create a signed event from a filled template', () => {
const template = { const template = {
tags: [['nonstandard', 'tag']], tags: [['nonstandard', 'tag']],
content: '👍', content: '👍',

View File

@ -1,3 +1,4 @@
import { test, expect } from 'bun:test'
import { matchAll, replaceAll } from './nip27.ts' import { matchAll, replaceAll } from './nip27.ts'
test('matchAll', () => { test('matchAll', () => {

View File

@ -1,3 +1,4 @@
import { describe, test, expect } from 'bun:test'
import { getPublicKey } from './keys.ts' import { getPublicKey } from './keys.ts'
import * as Kind from './kinds.ts' import * as Kind from './kinds.ts'
import { import {
@ -20,7 +21,7 @@ describe('NIP-28 Functions', () => {
picture: 'https://example.com/picture.jpg', picture: 'https://example.com/picture.jpg',
} }
it('channelCreateEvent should create an event with given template', () => { test('channelCreateEvent should create an event with given template', () => {
const template = { const template = {
content: channelMetadata, content: channelMetadata,
created_at: 1617932115, created_at: 1617932115,
@ -32,7 +33,7 @@ describe('NIP-28 Functions', () => {
expect(event!.pubkey).toEqual(publicKey) expect(event!.pubkey).toEqual(publicKey)
}) })
it('channelMetadataEvent should create a signed event with given template', () => { test('channelMetadataEvent should create a signed event with given template', () => {
const template = { const template = {
channel_create_event_id: 'channel creation event id', channel_create_event_id: 'channel creation event id',
content: channelMetadata, content: channelMetadata,
@ -48,8 +49,8 @@ describe('NIP-28 Functions', () => {
expect(typeof event!.sig).toEqual('string') expect(typeof event!.sig).toEqual('string')
}) })
it('channelMessageEvent should create a signed message event with given template', () => { test('channelMessageEvent should create a signed message event with given template', () => {
const template = { const template: ChannelMessageEventTemplate = {
channel_create_event_id: 'channel creation event id', channel_create_event_id: 'channel creation event id',
relay_url: 'https://relay.example.com', relay_url: 'https://relay.example.com',
content: 'Hello, world!', content: 'Hello, world!',
@ -65,7 +66,7 @@ describe('NIP-28 Functions', () => {
expect(typeof event.sig).toEqual('string') expect(typeof event.sig).toEqual('string')
}) })
it('channelMessageEvent should create a signed message reply event with given template', () => { test('channelMessageEvent should create a signed message reply event with given template', () => {
const template: ChannelMessageEventTemplate = { const template: ChannelMessageEventTemplate = {
channel_create_event_id: 'channel creation event id', channel_create_event_id: 'channel creation event id',
reply_to_channel_message_event_id: 'channel message event id', reply_to_channel_message_event_id: 'channel message event id',
@ -76,15 +77,25 @@ describe('NIP-28 Functions', () => {
const event = channelMessageEvent(template, privateKey) const event = channelMessageEvent(template, privateKey)
expect(event.kind).toEqual(Kind.ChannelMessage) expect(event.kind).toEqual(Kind.ChannelMessage)
expect(event.tags).toContainEqual(['e', template.channel_create_event_id, template.relay_url, 'root']) expect(event.tags.find(tag => tag[0] === 'e' && tag[1] === template.channel_create_event_id)).toEqual([
expect(event.tags).toContainEqual(['e', template.reply_to_channel_message_event_id, template.relay_url, 'reply']) 'e',
template.channel_create_event_id,
template.relay_url,
'root',
])
expect(event.tags.find(tag => tag[0] === 'e' && tag[1] === template.reply_to_channel_message_event_id)).toEqual([
'e',
template.reply_to_channel_message_event_id as string,
template.relay_url,
'reply',
])
expect(event.content).toEqual(template.content) expect(event.content).toEqual(template.content)
expect(event.pubkey).toEqual(publicKey) expect(event.pubkey).toEqual(publicKey)
expect(typeof event.id).toEqual('string') expect(typeof event.id).toEqual('string')
expect(typeof event.sig).toEqual('string') expect(typeof event.sig).toEqual('string')
}) })
it('channelHideMessageEvent should create a signed event with given template', () => { test('channelHideMessageEvent should create a signed event with given template', () => {
const template = { const template = {
channel_message_event_id: 'channel message event id', channel_message_event_id: 'channel message event id',
content: { reason: 'Inappropriate content' }, content: { reason: 'Inappropriate content' },
@ -100,7 +111,7 @@ describe('NIP-28 Functions', () => {
expect(typeof event!.sig).toEqual('string') expect(typeof event!.sig).toEqual('string')
}) })
it('channelMuteUserEvent should create a signed event with given template', () => { test('channelMuteUserEvent should create a signed event with given template', () => {
const template = { const template = {
content: { reason: 'Spamming' }, content: { reason: 'Spamming' },
created_at: 1617932115, created_at: 1617932115,

View File

@ -1,3 +1,4 @@
import { test, expect } from 'bun:test'
import { matchAll, replaceAll } from './nip30.ts' import { matchAll, replaceAll } from './nip30.ts'
test('matchAll', () => { test('matchAll', () => {

View File

@ -1,3 +1,4 @@
import { test, expect } from 'bun:test'
import fetch from 'node-fetch' import fetch from 'node-fetch'
import { useFetchImplementation, validateGithub } from './nip39.ts' import { useFetchImplementation, validateGithub } from './nip39.ts'

View File

@ -1,3 +1,4 @@
import { test, expect } from 'bun:test'
import 'websocket-polyfill' import 'websocket-polyfill'
import { makeAuthEvent } from './nip42.ts' import { makeAuthEvent } from './nip42.ts'

View File

@ -1,3 +1,4 @@
import { describe, test, expect } from 'bun:test'
import { makeNwcRequestEvent, parseConnectionString } from './nip47' import { makeNwcRequestEvent, parseConnectionString } from './nip47'
import { decrypt } from './nip04.ts' import { decrypt } from './nip04.ts'
import crypto from 'node:crypto' import crypto from 'node:crypto'

View File

@ -1,3 +1,4 @@
import { describe, test, expect, mock } from 'bun:test'
import { finishEvent } from './event.ts' import { finishEvent } from './event.ts'
import { getPublicKey, generatePrivateKey } from './keys.ts' import { getPublicKey, generatePrivateKey } from './keys.ts'
import { getZapEndpoint, makeZapReceipt, makeZapRequest, useFetchImplementation, validateZapRequest } from './nip57.ts' import { getZapEndpoint, makeZapReceipt, makeZapRequest, useFetchImplementation, validateZapRequest } from './nip57.ts'
@ -12,7 +13,7 @@ describe('getZapEndpoint', () => {
}) })
test('returns null if fetch fails', async () => { test('returns null if fetch fails', async () => {
const fetchImplementation = jest.fn(() => Promise.reject(new Error())) const fetchImplementation = mock(() => Promise.reject(new Error()))
useFetchImplementation(fetchImplementation) useFetchImplementation(fetchImplementation)
const metadata = buildEvent({ kind: 0, content: '{"lud16": "name@domain"}' }) const metadata = buildEvent({ kind: 0, content: '{"lud16": "name@domain"}' })
@ -23,7 +24,7 @@ describe('getZapEndpoint', () => {
}) })
test('returns null if the response does not allow Nostr payments', async () => { test('returns null if the response does not allow Nostr payments', async () => {
const fetchImplementation = jest.fn(() => Promise.resolve({ json: () => ({ allowsNostr: false }) })) const fetchImplementation = mock(() => Promise.resolve({ json: () => ({ allowsNostr: false }) }))
useFetchImplementation(fetchImplementation) useFetchImplementation(fetchImplementation)
const metadata = buildEvent({ kind: 0, content: '{"lud16": "name@domain"}' }) const metadata = buildEvent({ kind: 0, content: '{"lud16": "name@domain"}' })
@ -34,7 +35,7 @@ describe('getZapEndpoint', () => {
}) })
test('returns the callback URL if the response allows Nostr payments', async () => { test('returns the callback URL if the response allows Nostr payments', async () => {
const fetchImplementation = jest.fn(() => const fetchImplementation = mock(() =>
Promise.resolve({ Promise.resolve({
json: () => ({ json: () => ({
allowsNostr: true, allowsNostr: true,
@ -94,9 +95,9 @@ describe('makeZapRequest', () => {
['p', 'profile'], ['p', 'profile'],
['amount', '100'], ['amount', '100'],
['relays', 'relay1', 'relay2'], ['relays', 'relay1', 'relay2'],
['e', 'event'],
]), ]),
) )
expect(result.tags).toContainEqual(['e', 'event'])
}) })
}) })
@ -271,10 +272,14 @@ describe('makeZapReceipt', () => {
expect(result.kind).toBe(9735) expect(result.kind).toBe(9735)
expect(result.created_at).toBeCloseTo(paidAt.getTime() / 1000, 0) expect(result.created_at).toBeCloseTo(paidAt.getTime() / 1000, 0)
expect(result.content).toBe('') expect(result.content).toBe('')
expect(result.tags).toContainEqual(['bolt11', bolt11]) expect(result.tags).toEqual(
expect(result.tags).toContainEqual(['description', zapRequest]) expect.arrayContaining([
expect(result.tags).toContainEqual(['p', publicKey]) ['bolt11', bolt11],
expect(result.tags).toContainEqual(['preimage', preimage]) ['description', zapRequest],
['p', publicKey],
['preimage', preimage],
]),
)
}) })
test('returns a valid Zap receipt without a preimage', () => { test('returns a valid Zap receipt without a preimage', () => {
@ -304,9 +309,13 @@ describe('makeZapReceipt', () => {
expect(result.kind).toBe(9735) expect(result.kind).toBe(9735)
expect(result.created_at).toBeCloseTo(paidAt.getTime() / 1000, 0) expect(result.created_at).toBeCloseTo(paidAt.getTime() / 1000, 0)
expect(result.content).toBe('') expect(result.content).toBe('')
expect(result.tags).toContainEqual(['bolt11', bolt11]) expect(result.tags).toEqual(
expect(result.tags).toContainEqual(['description', zapRequest]) expect.arrayContaining([
expect(result.tags).toContainEqual(['p', publicKey]) ['bolt11', bolt11],
expect(result.tags).not.toContain('preimage') ['description', zapRequest],
['p', publicKey],
]),
)
expect(JSON.stringify(result.tags)).not.toContain('preimage')
}) })
}) })

View File

@ -1,3 +1,4 @@
import { describe, test, expect } from 'bun:test'
import { getToken, unpackEventFromToken, validateEvent, validateToken } from './nip98.ts' import { getToken, unpackEventFromToken, validateEvent, validateToken } from './nip98.ts'
import { Event, finishEvent } from './event.ts' import { Event, finishEvent } from './event.ts'
import { generatePrivateKey, getPublicKey } from './keys.ts' import { generatePrivateKey, getPublicKey } from './keys.ts'
@ -60,12 +61,12 @@ describe('getToken', () => {
test('getToken missing loginUrl throws an error', async () => { test('getToken missing loginUrl throws an error', async () => {
const result = getToken('', 'get', e => finishEvent(e, sk)) const result = getToken('', 'get', e => finishEvent(e, sk))
await expect(result).rejects.toThrow(Error) expect(result).rejects.toThrow(Error)
}) })
test('getToken missing httpMethod throws an error', async () => { test('getToken missing httpMethod throws an error', async () => {
const result = getToken('http://test.com', '', e => finishEvent(e, sk)) const result = getToken('http://test.com', '', e => finishEvent(e, sk))
await expect(result).rejects.toThrow(Error) expect(result).rejects.toThrow(Error)
}) })
test('getToken returns token with a valid payload tag when payload is present', async () => { test('getToken returns token with a valid payload tag when payload is present', async () => {
@ -104,26 +105,26 @@ describe('validateToken', () => {
test('validateToken throws an error for invalid token', async () => { test('validateToken throws an error for invalid token', async () => {
const result = validateToken('fake', 'http://test.com', 'get') const result = validateToken('fake', 'http://test.com', 'get')
await expect(result).rejects.toThrow(Error) expect(result).rejects.toThrow(Error)
}) })
test('validateToken throws an error for missing token', async () => { test('validateToken throws an error for missing token', async () => {
const result = validateToken('', 'http://test.com', 'get') const result = validateToken('', 'http://test.com', 'get')
await expect(result).rejects.toThrow(Error) expect(result).rejects.toThrow(Error)
}) })
test('validateToken throws an error for a wrong url', async () => { test('validateToken throws an error for a wrong url', async () => {
const validToken = await getToken('http://test.com', 'get', e => finishEvent(e, sk)) const validToken = await getToken('http://test.com', 'get', e => finishEvent(e, sk))
const result = validateToken(validToken, 'http://wrong-test.com', 'get') const result = validateToken(validToken, 'http://wrong-test.com', 'get')
await expect(result).rejects.toThrow(Error) expect(result).rejects.toThrow(Error)
}) })
test('validateToken throws an error for a wrong method', async () => { test('validateToken throws an error for a wrong method', async () => {
const validToken = await getToken('http://test.com', 'get', e => finishEvent(e, sk)) const validToken = await getToken('http://test.com', 'get', e => finishEvent(e, sk))
const result = validateToken(validToken, 'http://test.com', 'post') const result = validateToken(validToken, 'http://test.com', 'post')
await expect(result).rejects.toThrow(Error) expect(result).rejects.toThrow(Error)
}) })
test('validateEvent returns true for valid decoded token with authorization scheme', async () => { test('validateEvent returns true for valid decoded token with authorization scheme', async () => {
@ -139,7 +140,7 @@ describe('validateToken', () => {
const decodedResult: Event = await unpackEventFromToken(validToken) const decodedResult: Event = await unpackEventFromToken(validToken)
const result = validateEvent(decodedResult, 'http://wrong-test.com', 'get') const result = validateEvent(decodedResult, 'http://wrong-test.com', 'get')
await expect(result).rejects.toThrow(Error) expect(result).rejects.toThrow(Error)
}) })
test('validateEvent throws an error for a wrong method', async () => { test('validateEvent throws an error for a wrong method', async () => {
@ -147,7 +148,7 @@ describe('validateToken', () => {
const decodedResult: Event = await unpackEventFromToken(validToken) const decodedResult: Event = await unpackEventFromToken(validToken)
const result = validateEvent(decodedResult, 'http://test.com', 'post') const result = validateEvent(decodedResult, 'http://test.com', 'post')
await expect(result).rejects.toThrow(Error) expect(result).rejects.toThrow(Error)
}) })
test('validateEvent returns true for valid payload tag hash', async () => { test('validateEvent returns true for valid payload tag hash', async () => {
@ -163,6 +164,6 @@ describe('validateToken', () => {
const decodedResult: Event = await unpackEventFromToken(validToken) const decodedResult: Event = await unpackEventFromToken(validToken)
const result = validateEvent(decodedResult, 'http://test.com', 'post', { test: 'a-different-payload' }) const result = validateEvent(decodedResult, 'http://test.com', 'post', { test: 'a-different-payload' })
await expect(result).rejects.toThrow(Error) expect(result).rejects.toThrow(Error)
}) })
}) })

View File

@ -26,8 +26,6 @@ export async function getToken(
includeAuthorizationScheme: boolean = false, includeAuthorizationScheme: boolean = false,
payload?: Record<string, any>, payload?: Record<string, any>,
): Promise<string> { ): Promise<string> {
if (!loginUrl || !httpMethod) throw new Error('Missing loginUrl or httpMethod')
const event: EventTemplate = { const event: EventTemplate = {
kind: HTTPAuth, kind: HTTPAuth,
tags: [ tags: [

View File

@ -169,29 +169,21 @@
"client", "client",
"nostr" "nostr"
], ],
"scripts": {
"build": "node build && tsc",
"format": "prettier --plugin-search-dir . --write .",
"test": "jest"
},
"devDependencies": { "devDependencies": {
"@types/jest": "^29.5.1",
"@types/node": "^18.13.0", "@types/node": "^18.13.0",
"@types/node-fetch": "^2.6.3", "@types/node-fetch": "^2.6.3",
"@typescript-eslint/eslint-plugin": "^6.5.0", "@typescript-eslint/eslint-plugin": "^6.5.0",
"@typescript-eslint/parser": "^6.5.0", "@typescript-eslint/parser": "^6.5.0",
"bun-types": "^1.0.18",
"esbuild": "0.16.9", "esbuild": "0.16.9",
"esbuild-plugin-alias": "^0.2.1", "esbuild-plugin-alias": "^0.2.1",
"eslint": "^8.56.0", "eslint": "^8.56.0",
"eslint-config-prettier": "^9.0.0", "eslint-config-prettier": "^9.0.0",
"eslint-plugin-babel": "^5.3.1", "eslint-plugin-babel": "^5.3.1",
"eslint-plugin-jest": "^27.2.3",
"esm-loader-typescript": "^1.0.3", "esm-loader-typescript": "^1.0.3",
"events": "^3.3.0", "events": "^3.3.0",
"jest": "^29.5.0",
"node-fetch": "^2.6.9", "node-fetch": "^2.6.9",
"prettier": "^3.0.3", "prettier": "^3.0.3",
"ts-jest": "^29.1.0",
"tsd": "^0.22.0", "tsd": "^0.22.0",
"typescript": "^5.0.4", "typescript": "^5.0.4",
"websocket-polyfill": "^0.0.3" "websocket-polyfill": "^0.0.3"

View File

@ -1,3 +1,4 @@
import { test, expect } from 'bun:test'
import 'websocket-polyfill' import 'websocket-polyfill'
import { finishEvent, type Event } from './event.ts' import { finishEvent, type Event } from './event.ts'

View File

@ -1,3 +1,4 @@
import { test, expect } from 'bun:test'
import { parseReferences } from './references.ts' import { parseReferences } from './references.ts'
import { buildEvent } from './test-helpers.ts' import { buildEvent } from './test-helpers.ts'

View File

@ -1,3 +1,4 @@
import { test, expect } from 'bun:test'
import 'websocket-polyfill' import 'websocket-polyfill'
import { finishEvent } from './event.ts' import { finishEvent } from './event.ts'

View File

@ -12,6 +12,7 @@
"outDir": "lib/types", "outDir": "lib/types",
"resolveJsonModule": true, "resolveJsonModule": true,
"rootDir": ".", "rootDir": ".",
"allowImportingTsExtensions": true "allowImportingTsExtensions": true,
"types": ["bun-types"]
} }
} }

View File

@ -1,3 +1,4 @@
import { describe, test, expect } from 'bun:test'
import { buildEvent } from './test-helpers.ts' import { buildEvent } from './test-helpers.ts'
import { MessageQueue, insertEventIntoAscendingList, insertEventIntoDescendingList } from './utils.ts' import { MessageQueue, insertEventIntoAscendingList, insertEventIntoDescendingList } from './utils.ts'

4245
yarn.lock

File diff suppressed because it is too large Load Diff