Skip to content

Commit ce788eb

Browse files
committed
some more code snippets
1 parent 6e16e06 commit ce788eb

File tree

5 files changed

+779
-0
lines changed

5 files changed

+779
-0
lines changed

docs/snippets/index.md

+5
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,8 @@ Snippets are organized into the following categories:
2626
- [Using Cashu Wallet](./wallet/using-cashu-wallet.md) - Create and use a Cashu wallet for managing e-cash tokens
2727
- [Nutzap Monitor](./wallet/nutzap-monitor.md) - Track and process Cashu tokens sent via Nostr zaps
2828
- [Cashu Deposits](./wallet/cashu-deposits.md) - Fund your Cashu wallet using Lightning invoices
29+
- [Testing](./testing/)
30+
- [Mock Relays](./testing/mock-relays.md) - Create and use mock relays for testing NDK applications
31+
- [Event Generation](./testing/event-generation.md) - Generate test events with different kinds and content
32+
- [Nutzap Testing](./testing/nutzap-testing.md) - Test Cashu token and Nutzap functionality
33+
- [Relay Pool Testing](./testing/relay-pool-testing.md) - Test relay pool behavior and event handling
+201
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
# Event Generation for Testing
2+
3+
This guide shows how to use NDK's test utilities to generate various types of events for testing purposes.
4+
5+
## Basic Event Generation
6+
7+
Use the EventGenerator to create different types of events:
8+
9+
```typescript
10+
import { EventGenerator } from "@nostr-dev-kit/ndk-test-utils";
11+
import { NDK } from "@nostr-dev-kit/ndk";
12+
13+
const ndk = new NDK();
14+
EventGenerator.setNDK(ndk); // Required setup
15+
const generator = new EventGenerator();
16+
17+
// Generate a text note (kind 1)
18+
const textNote = await generator.textNote("Hello World");
19+
20+
// Generate metadata (kind 0)
21+
const metadata = await generator.metadata({
22+
name: "Test User",
23+
about: "Testing NDK",
24+
picture: "https://example.com/avatar.jpg"
25+
});
26+
27+
// Generate contact list (kind 3)
28+
const contacts = await generator.contactList([
29+
"pubkey1",
30+
"pubkey2",
31+
"pubkey3"
32+
]);
33+
```
34+
35+
## Advanced Event Generation
36+
37+
### Custom Event Creation
38+
39+
```typescript
40+
// Create a custom event with specific properties
41+
const customEvent = await generator.createEvent({
42+
kind: 1,
43+
content: "Custom content",
44+
tags: [
45+
["p", "pubkey1"],
46+
["e", "event1"]
47+
]
48+
});
49+
50+
// Create an encrypted direct message
51+
const encryptedDM = await generator.encryptedDM(
52+
"recipient_pubkey",
53+
"Secret message"
54+
);
55+
56+
// Create a reaction event
57+
const reaction = await generator.reaction(
58+
"target_event_id",
59+
"+" // Like reaction
60+
);
61+
```
62+
63+
### Event with Tags
64+
65+
```typescript
66+
// Create an event with multiple tag types
67+
const taggedEvent = await generator.createEvent({
68+
kind: 1,
69+
content: "Tagged content",
70+
tags: [
71+
["p", "pubkey1", "wss://relay.example"],
72+
["e", "event1", "wss://relay.example", "reply"],
73+
["t", "testing"],
74+
["r", "https://example.com"]
75+
]
76+
});
77+
```
78+
79+
### Parametric Events
80+
81+
```typescript
82+
// Generate events with specific parameters
83+
const paramEvent = await generator.createEvent({
84+
kind: 1,
85+
content: "Parametric content",
86+
created_at: Math.floor(Date.now() / 1000),
87+
tags: [],
88+
pubkey: "custom_pubkey" // Override default pubkey
89+
});
90+
91+
// Generate multiple events
92+
const events = await Promise.all([
93+
generator.textNote("First note"),
94+
generator.textNote("Second note"),
95+
generator.textNote("Third note")
96+
]);
97+
```
98+
99+
## Testing Scenarios
100+
101+
### Event Verification
102+
103+
```typescript
104+
// Test event verification
105+
const event = await generator.textNote("Test message");
106+
107+
expect(event.kind).toBe(1);
108+
expect(event.content).toBe("Test message");
109+
expect(event.sig).toBeDefined();
110+
expect(event.id).toBeDefined();
111+
expect(event.pubkey).toBeDefined();
112+
```
113+
114+
### Event Relationships
115+
116+
```typescript
117+
// Create a thread of related events
118+
const rootEvent = await generator.textNote("Root message");
119+
const replyEvent = await generator.createEvent({
120+
kind: 1,
121+
content: "Reply message",
122+
tags: [
123+
["e", rootEvent.id, "", "root"],
124+
["p", rootEvent.pubkey]
125+
]
126+
});
127+
128+
// Create a reaction to the reply
129+
const reactionEvent = await generator.reaction(replyEvent.id, "+");
130+
```
131+
132+
### Testing Event Processing
133+
134+
```typescript
135+
// Test event processing with mock relay
136+
import { RelayMock } from "@nostr-dev-kit/ndk-test-utils";
137+
138+
const relay = new RelayMock("wss://test.relay");
139+
const events = [];
140+
141+
// Subscribe to events
142+
relay.subscribe({
143+
subId: "test",
144+
filters: [{ kinds: [1] }],
145+
eventReceived: (event) => events.push(event)
146+
});
147+
148+
// Generate and simulate events
149+
const event1 = await generator.textNote("First");
150+
const event2 = await generator.textNote("Second");
151+
152+
await relay.simulateEvent(event1);
153+
await relay.simulateEvent(event2);
154+
155+
expect(events).toHaveLength(2);
156+
```
157+
158+
## Best Practices
159+
160+
1. Reset generator before tests:
161+
```typescript
162+
beforeEach(() => {
163+
EventGenerator.setNDK(new NDK());
164+
});
165+
```
166+
167+
2. Use consistent timestamps for deterministic testing:
168+
```typescript
169+
const timestamp = Math.floor(Date.now() / 1000);
170+
const event = await generator.createEvent({
171+
kind: 1,
172+
content: "Test",
173+
created_at: timestamp
174+
});
175+
```
176+
177+
3. Test event validation:
178+
```typescript
179+
const event = await generator.textNote("Test");
180+
expect(event.verify()).resolves.toBe(true);
181+
```
182+
183+
4. Generate related events:
184+
```typescript
185+
// Create a conversation thread
186+
const thread = [];
187+
const root = await generator.textNote("Root");
188+
thread.push(root);
189+
190+
for (let i = 0; i < 3; i++) {
191+
const reply = await generator.createEvent({
192+
kind: 1,
193+
content: `Reply ${i + 1}`,
194+
tags: [
195+
["e", thread[i].id, "", "reply"],
196+
["p", thread[i].pubkey]
197+
]
198+
});
199+
thread.push(reply);
200+
}
201+
```

docs/snippets/testing/mock-relays.md

+170
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
# Mock Relays for Testing
2+
3+
This guide demonstrates how to use NDK's test utilities to create and work with mock relays in your tests.
4+
5+
## Installation
6+
7+
First, install the test utilities package:
8+
9+
```bash
10+
pnpm add --save-dev @nostr-dev-kit/ndk-test-utils
11+
```
12+
13+
## Basic Mock Relay Usage
14+
15+
Create and use a basic mock relay:
16+
17+
```typescript
18+
import { RelayMock } from "@nostr-dev-kit/ndk-test-utils";
19+
import { NDK } from "@nostr-dev-kit/ndk";
20+
21+
describe("Mock Relay Tests", () => {
22+
let relayMock: RelayMock;
23+
let ndk: NDK;
24+
25+
beforeEach(() => {
26+
// Create a new NDK instance
27+
ndk = new NDK();
28+
29+
// Create a mock relay
30+
relayMock = new RelayMock("wss://test.relay", {
31+
simulateDisconnect: false, // Don't randomly disconnect
32+
connectionDelay: 100, // Simulate 100ms connection delay
33+
autoConnect: true // Auto-connect when used
34+
});
35+
});
36+
37+
it("should handle events", async () => {
38+
// Connect to the mock relay
39+
await relayMock.connect();
40+
41+
// Create a subscription
42+
const sub = relayMock.subscribe({
43+
subId: "test-sub",
44+
filters: [{ kinds: [1] }] // Subscribe to text notes
45+
});
46+
47+
// Simulate receiving an event
48+
const event = {
49+
kind: 1,
50+
content: "Hello World",
51+
// ... other event fields
52+
};
53+
await relayMock.simulateEvent(event);
54+
55+
// Clean up
56+
await relayMock.disconnect();
57+
});
58+
});
59+
```
60+
61+
## Advanced Mock Relay Features
62+
63+
### Simulating Network Conditions
64+
65+
```typescript
66+
// Create a flaky relay that randomly disconnects
67+
const flakyRelay = new RelayMock("wss://flaky.relay", {
68+
simulateDisconnect: true,
69+
disconnectChance: 0.3, // 30% chance to disconnect on operations
70+
connectionDelay: 500 // 500ms connection delay
71+
});
72+
73+
// Test reconnection behavior
74+
await flakyRelay.connect();
75+
await flakyRelay.simulateDisconnect(); // Force a disconnect
76+
await flakyRelay.connect(); // Should reconnect
77+
```
78+
79+
### Testing Event Publishing
80+
81+
```typescript
82+
import { RelayMock, EventGenerator } from "@nostr-dev-kit/ndk-test-utils";
83+
84+
// Create an event generator
85+
const generator = new EventGenerator();
86+
87+
// Generate a test event
88+
const textNote = await generator.textNote("Test message");
89+
90+
// Publish and verify
91+
const publishSpy = vitest.spyOn(relayMock, 'publish');
92+
await relayMock.publish(textNote);
93+
94+
expect(publishSpy).toHaveBeenCalledWith(textNote);
95+
```
96+
97+
### Simulating Relay Messages
98+
99+
```typescript
100+
// Simulate various relay messages
101+
relayMock.simulateNotice("Server restarting in 5 minutes");
102+
relayMock.simulateEOSE("subscription-id");
103+
relayMock.simulateOK("event-id", true, "success");
104+
105+
// Simulate raw messages
106+
relayMock.simulateReceiveMessage('["AUTH", "challenge"]');
107+
```
108+
109+
## Testing Multiple Relays
110+
111+
Use RelayPoolMock to test multiple relay scenarios:
112+
113+
```typescript
114+
import { RelayPoolMock } from "@nostr-dev-kit/ndk-test-utils";
115+
116+
// Create a mock relay pool
117+
const poolMock = new RelayPoolMock();
118+
119+
// Add multiple relays
120+
poolMock.addRelay("wss://relay1.test");
121+
poolMock.addRelay("wss://relay2.test");
122+
123+
// Get specific relay mock
124+
const relay1 = poolMock.getRelay("wss://relay1.test");
125+
const relay2 = poolMock.getRelay("wss://relay2.test");
126+
127+
// Test event propagation across relays
128+
const event = await generator.textNote("Test across relays");
129+
await relay1.simulateEvent(event); // Simulate event on first relay
130+
await relay2.simulateEvent(event); // Simulate same event on second relay
131+
```
132+
133+
## Best Practices
134+
135+
1. Always clean up relays after tests:
136+
```typescript
137+
afterEach(async () => {
138+
await relayMock.disconnect();
139+
});
140+
```
141+
142+
2. Reset event generators between tests:
143+
```typescript
144+
beforeEach(() => {
145+
EventGenerator.setNDK(ndk); // Reset with fresh NDK instance
146+
});
147+
```
148+
149+
3. Use realistic delays to simulate network conditions:
150+
```typescript
151+
const relay = new RelayMock("wss://test.relay", {
152+
connectionDelay: 100, // Connection time
153+
operationDelay: 50, // Time for operations
154+
disconnectDelay: 75 // Disconnection time
155+
});
156+
```
157+
158+
4. Test error scenarios:
159+
```typescript
160+
// Test failed connections
161+
const failingRelay = new RelayMock("wss://failing.relay", {
162+
simulateConnectionError: true
163+
});
164+
165+
try {
166+
await failingRelay.connect();
167+
} catch (error) {
168+
expect(error).toBeDefined();
169+
}
170+
```

0 commit comments

Comments
 (0)