You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

307 lines
8.7 KiB

import 'package:flutter_test/flutter_test.dart';
import 'package:app_boilerplate/data/nostr/nostr_service.dart';
import 'package:app_boilerplate/data/nostr/models/nostr_keypair.dart';
import 'package:app_boilerplate/data/nostr/models/nostr_event.dart';
import 'package:app_boilerplate/data/nostr/models/nostr_relay.dart';
import 'dart:async';
import 'dart:convert';
void main() {
group('NostrService - Keypair Generation', () {
/// Tests that keypair generation creates valid keypairs.
test('generateKeyPair - success', () {
// Arrange
final service = NostrService();
// Act
final keypair = service.generateKeyPair();
// Assert
expect(keypair.privateKey, isNotEmpty);
expect(keypair.publicKey, isNotEmpty);
expect(keypair.privateKey.length, equals(64)); // 32 bytes = 64 hex chars
expect(keypair.publicKey.length, equals(64)); // 32 bytes = 64 hex chars
});
/// Tests that each generated keypair is unique.
test('generateKeyPair - generates unique keypairs', () {
// Arrange
final service = NostrService();
// Act
final keypair1 = service.generateKeyPair();
final keypair2 = service.generateKeyPair();
// Assert
expect(keypair1.privateKey, isNot(equals(keypair2.privateKey)));
expect(keypair1.publicKey, isNot(equals(keypair2.publicKey)));
});
/// Tests keypair JSON serialization.
test('NostrKeyPair - JSON serialization', () {
// Arrange
final keypair = NostrKeyPair.generate();
// Act
final json = keypair.toJson();
final restored = NostrKeyPair.fromJson(json);
// Assert
expect(restored.privateKey, equals(keypair.privateKey));
expect(restored.publicKey, equals(keypair.publicKey));
});
});
group('NostrService - Relay Management', () {
/// Tests adding a relay.
test('addRelay - success', () {
// Arrange
final service = NostrService();
// Act
service.addRelay('wss://relay.example.com');
// Assert
final relays = service.getRelays();
expect(relays.length, equals(1));
expect(relays[0].url, equals('wss://relay.example.com'));
});
/// Tests adding multiple relays.
test('addRelay - multiple relays', () {
// Arrange
final service = NostrService();
// Act
service.addRelay('wss://relay1.example.com');
service.addRelay('wss://relay2.example.com');
service.addRelay('wss://relay3.example.com');
// Assert
final relays = service.getRelays();
expect(relays.length, equals(3));
});
/// Tests that duplicate relays are not added.
test('addRelay - prevents duplicates', () {
// Arrange
final service = NostrService();
// Act
service.addRelay('wss://relay.example.com');
service.addRelay('wss://relay.example.com');
// Assert
final relays = service.getRelays();
expect(relays.length, equals(1));
});
/// Tests removing a relay.
test('removeRelay - success', () {
// Arrange
final service = NostrService();
service.addRelay('wss://relay.example.com');
// Act
service.removeRelay('wss://relay.example.com');
// Assert
final relays = service.getRelays();
expect(relays.length, equals(0));
});
});
group('NostrService - Event Creation', () {
/// Tests creating a Nostr event.
test('NostrEvent.create - success', () {
// Arrange
final keypair = NostrKeyPair.generate();
final content = 'Test event content';
// Act
final event = NostrEvent.create(
content: content,
privateKey: keypair.privateKey,
);
// Assert
expect(event.content, equals(content));
expect(event.pubkey, isNotEmpty);
expect(event.id, isNotEmpty);
expect(event.sig, isNotEmpty);
expect(event.kind, equals(1)); // Default kind
expect(event.createdAt, greaterThan(0));
});
/// Tests creating event with custom kind.
test('NostrEvent.create - custom kind', () {
// Arrange
final keypair = NostrKeyPair.generate();
// Act
final event = NostrEvent.create(
content: 'Metadata',
kind: 0,
privateKey: keypair.privateKey,
);
// Assert
expect(event.kind, equals(0));
});
/// Tests creating event with tags.
test('NostrEvent.create - with tags', () {
// Arrange
final keypair = NostrKeyPair.generate();
final tags = [
['t', 'tag1'],
['p', 'pubkey123'],
];
// Act
final event = NostrEvent.create(
content: 'Tagged content',
privateKey: keypair.privateKey,
tags: tags,
);
// Assert
expect(event.tags.length, equals(2));
expect(event.tags[0], equals(['t', 'tag1']));
});
/// Tests event JSON serialization.
test('NostrEvent - JSON serialization', () {
// Arrange
final keypair = NostrKeyPair.generate();
final event = NostrEvent.create(
content: 'Test',
privateKey: keypair.privateKey,
);
// Act
final json = event.toJson();
final restored = NostrEvent.fromJson(json);
// Assert
expect(restored.id, equals(event.id));
expect(restored.content, equals(event.content));
expect(restored.kind, equals(event.kind));
});
});
group('NostrService - Metadata Sync', () {
/// Tests syncing metadata to relays.
test('syncMetadata - success', () async {
// Arrange
final service = NostrService();
final keypair = NostrKeyPair.generate();
final metadata = {
'name': 'Test User',
'about': 'Test description',
};
// Mock relay connection (without actual WebSocket)
// Note: In a real test, you'd mock the WebSocket channel
// For now, we test that the event is created correctly
// Act
try {
final event = await service.syncMetadata(
metadata: metadata,
privateKey: keypair.privateKey,
);
// Assert - event should be created
expect(event, isNotNull);
expect(event.content, contains('Test User'));
expect(event.kind, equals(0)); // Metadata kind
} catch (e) {
// Expected to fail without real relay connection
expect(e, isA<NostrException>());
}
});
/// Tests syncing metadata with custom kind.
test('syncMetadata - custom kind', () async {
// Arrange
final service = NostrService();
final keypair = NostrKeyPair.generate();
final metadata = {'key': 'value'};
// Act
try {
final event = await service.syncMetadata(
metadata: metadata,
privateKey: keypair.privateKey,
kind: 30000, // Custom kind
);
// Assert
expect(event.kind, equals(30000));
} catch (e) {
// Expected to fail without real relay connection
expect(e, isA<NostrException>());
}
});
});
group('NostrService - Error Handling', () {
/// Tests error handling when publishing without relay connection.
test('publishEvent - fails when not connected', () async {
// Arrange
final service = NostrService();
final keypair = NostrKeyPair.generate();
final event = NostrEvent.create(
content: 'Test',
privateKey: keypair.privateKey,
);
// Act & Assert
expect(
() => service.publishEvent(event, 'wss://relay.example.com'),
throwsA(isA<NostrException>()),
);
});
/// Tests error handling when publishing to all relays without connections.
test('publishEventToAllRelays - handles disconnected relays', () async {
// Arrange
final service = NostrService();
service.addRelay('wss://relay1.example.com');
service.addRelay('wss://relay2.example.com');
final keypair = NostrKeyPair.generate();
final event = NostrEvent.create(
content: 'Test',
privateKey: keypair.privateKey,
);
// Act
final results = await service.publishEventToAllRelays(event);
// Assert - all should fail since not connected
expect(results.length, equals(2));
expect(results['wss://relay1.example.com'], isFalse);
expect(results['wss://relay2.example.com'], isFalse);
});
});
group('NostrService - Cleanup', () {
/// Tests that dispose cleans up resources.
test('dispose - cleans up resources', () {
// Arrange
final service = NostrService();
service.addRelay('wss://relay1.example.com');
service.addRelay('wss://relay2.example.com');
// Act
service.dispose();
// Assert
final relays = service.getRelays();
expect(relays.length, equals(0));
});
});
}

Powered by TurnKey Linux.