format dart files

formats all dart files using `dart format .` from the root project dir

this makes the code style repeatable by new contributors and makes PR review easier
This commit is contained in:
446564
2026-02-04 08:32:35 -08:00
parent 488a286701
commit b34d684e67
66 changed files with 2882 additions and 1848 deletions
+283 -83
View File
@@ -7,30 +7,50 @@ void main() {
group('reactionEmojis', () {
test('should contain all emoji categories', () {
final emojis = ReactionHelper.reactionEmojis;
// Should contain quickEmojis
for (final emoji in EmojiPicker.quickEmojis) {
expect(emojis.contains(emoji), isTrue, reason: 'Missing quick emoji: $emoji');
expect(
emojis.contains(emoji),
isTrue,
reason: 'Missing quick emoji: $emoji',
);
}
// Should contain smileys
for (final emoji in EmojiPicker.smileys) {
expect(emojis.contains(emoji), isTrue, reason: 'Missing smiley: $emoji');
expect(
emojis.contains(emoji),
isTrue,
reason: 'Missing smiley: $emoji',
);
}
// Should contain gestures
for (final emoji in EmojiPicker.gestures) {
expect(emojis.contains(emoji), isTrue, reason: 'Missing gesture: $emoji');
expect(
emojis.contains(emoji),
isTrue,
reason: 'Missing gesture: $emoji',
);
}
// Should contain hearts
for (final emoji in EmojiPicker.hearts) {
expect(emojis.contains(emoji), isTrue, reason: 'Missing heart: $emoji');
expect(
emojis.contains(emoji),
isTrue,
reason: 'Missing heart: $emoji',
);
}
// Should contain objects
for (final emoji in EmojiPicker.objects) {
expect(emojis.contains(emoji), isTrue, reason: 'Missing object: $emoji');
expect(
emojis.contains(emoji),
isTrue,
reason: 'Missing object: $emoji',
);
}
});
@@ -43,7 +63,7 @@ void main() {
test('should return 2-char hex for valid emoji', () {
// First emoji (thumbs up) should be index 0
expect(ReactionHelper.emojiToIndex('👍'), equals('00'));
// Second emoji (heart) should be index 1
expect(ReactionHelper.emojiToIndex('❤️'), equals('01'));
});
@@ -67,7 +87,10 @@ void main() {
});
test('should return null for invalid index', () {
expect(ReactionHelper.indexToEmoji('ff'), isNull); // Index 255, out of range
expect(
ReactionHelper.indexToEmoji('ff'),
isNull,
); // Index 255, out of range
expect(ReactionHelper.indexToEmoji('zz'), isNull); // Invalid hex
expect(ReactionHelper.indexToEmoji(''), isNull); // Empty string
// Note: indexToEmoji parses any valid hex; length validation is done by parseReaction's regex
@@ -86,78 +109,158 @@ void main() {
final emoji = ReactionHelper.reactionEmojis[i];
final index = ReactionHelper.emojiToIndex(emoji);
expect(index, isNotNull, reason: 'emojiToIndex failed for $emoji');
final decoded = ReactionHelper.indexToEmoji(index!);
expect(decoded, equals(emoji), reason: 'Round-trip failed for $emoji (index $index)');
expect(
decoded,
equals(emoji),
reason: 'Round-trip failed for $emoji (index $index)',
);
}
});
});
group('computeReactionHash', () {
test('should return 4-char hex hash', () {
final hash = ReactionHelper.computeReactionHash(1234567890, 'Alice', 'Hello world');
final hash = ReactionHelper.computeReactionHash(
1234567890,
'Alice',
'Hello world',
);
expect(hash, matches(RegExp(r'^[0-9a-f]{4}$')));
});
test('should be deterministic', () {
final hash1 = ReactionHelper.computeReactionHash(1234567890, 'Alice', 'Hello');
final hash2 = ReactionHelper.computeReactionHash(1234567890, 'Alice', 'Hello');
final hash1 = ReactionHelper.computeReactionHash(
1234567890,
'Alice',
'Hello',
);
final hash2 = ReactionHelper.computeReactionHash(
1234567890,
'Alice',
'Hello',
);
expect(hash1, equals(hash2));
});
test('should differ for different inputs', () {
final hash1 = ReactionHelper.computeReactionHash(1234567890, 'Alice', 'Hello');
final hash2 = ReactionHelper.computeReactionHash(1234567890, 'Bob', 'Hello');
final hash3 = ReactionHelper.computeReactionHash(1234567891, 'Alice', 'Hello');
final hash4 = ReactionHelper.computeReactionHash(1234567890, 'Alice', 'World');
final hash1 = ReactionHelper.computeReactionHash(
1234567890,
'Alice',
'Hello',
);
final hash2 = ReactionHelper.computeReactionHash(
1234567890,
'Bob',
'Hello',
);
final hash3 = ReactionHelper.computeReactionHash(
1234567891,
'Alice',
'Hello',
);
final hash4 = ReactionHelper.computeReactionHash(
1234567890,
'Alice',
'World',
);
expect(hash1, isNot(equals(hash2))); // Different sender
expect(hash1, isNot(equals(hash3))); // Different timestamp
expect(hash1, isNot(equals(hash4))); // Different text
});
test('should use first 5 chars of text', () {
final hash1 = ReactionHelper.computeReactionHash(1234567890, 'Alice', 'Hello world');
final hash2 = ReactionHelper.computeReactionHash(1234567890, 'Alice', 'Hello there');
final hash1 = ReactionHelper.computeReactionHash(
1234567890,
'Alice',
'Hello world',
);
final hash2 = ReactionHelper.computeReactionHash(
1234567890,
'Alice',
'Hello there',
);
expect(hash1, equals(hash2)); // Same first 5 chars
});
test('should handle short text', () {
final hash = ReactionHelper.computeReactionHash(1234567890, 'Alice', 'Hi');
final hash = ReactionHelper.computeReactionHash(
1234567890,
'Alice',
'Hi',
);
expect(hash, matches(RegExp(r'^[0-9a-f]{4}$')));
});
test('should handle empty text', () {
final hash = ReactionHelper.computeReactionHash(1234567890, 'Alice', '');
final hash = ReactionHelper.computeReactionHash(
1234567890,
'Alice',
'',
);
expect(hash, matches(RegExp(r'^[0-9a-f]{4}$')));
});
});
group('computeReactionHash with null sender (1:1 chats)', () {
test('should return 4-char hex hash', () {
final hash = ReactionHelper.computeReactionHash(1234567890, null, 'Hello world');
final hash = ReactionHelper.computeReactionHash(
1234567890,
null,
'Hello world',
);
expect(hash, matches(RegExp(r'^[0-9a-f]{4}$')));
});
test('should be deterministic', () {
final hash1 = ReactionHelper.computeReactionHash(1234567890, null, 'Hello');
final hash2 = ReactionHelper.computeReactionHash(1234567890, null, 'Hello');
final hash1 = ReactionHelper.computeReactionHash(
1234567890,
null,
'Hello',
);
final hash2 = ReactionHelper.computeReactionHash(
1234567890,
null,
'Hello',
);
expect(hash1, equals(hash2));
});
test('should differ for different inputs', () {
final hash1 = ReactionHelper.computeReactionHash(1234567890, null, 'Hello');
final hash2 = ReactionHelper.computeReactionHash(1234567891, null, 'Hello');
final hash3 = ReactionHelper.computeReactionHash(1234567890, null, 'World');
final hash1 = ReactionHelper.computeReactionHash(
1234567890,
null,
'Hello',
);
final hash2 = ReactionHelper.computeReactionHash(
1234567891,
null,
'Hello',
);
final hash3 = ReactionHelper.computeReactionHash(
1234567890,
null,
'World',
);
expect(hash1, isNot(equals(hash2))); // Different timestamp
expect(hash1, isNot(equals(hash3))); // Different text
});
test('should differ from hash with sender name', () {
// Null sender hash doesn't include sender, so should differ
final nullSenderHash = ReactionHelper.computeReactionHash(1234567890, null, 'Hello');
final withSenderHash = ReactionHelper.computeReactionHash(1234567890, 'Alice', 'Hello');
final nullSenderHash = ReactionHelper.computeReactionHash(
1234567890,
null,
'Hello',
);
final withSenderHash = ReactionHelper.computeReactionHash(
1234567890,
'Alice',
'Hello',
);
expect(nullSenderHash, isNot(equals(withSenderHash)));
});
@@ -167,13 +270,21 @@ void main() {
// Bob computes hash the same way Alice's app will match it
const timestamp = 1234567890;
const messageText = 'Hello there!';
// Bob (sender of reaction) computes hash with null sender
final bobHash = ReactionHelper.computeReactionHash(timestamp, null, messageText);
final bobHash = ReactionHelper.computeReactionHash(
timestamp,
null,
messageText,
);
// Alice (receiver of reaction) computes hash for her outgoing message
final aliceHash = ReactionHelper.computeReactionHash(timestamp, null, messageText);
final aliceHash = ReactionHelper.computeReactionHash(
timestamp,
null,
messageText,
);
expect(bobHash, equals(aliceHash));
});
});
@@ -188,12 +299,30 @@ void main() {
test('should return null for invalid format', () {
expect(ReactionHelper.parseReaction('invalid'), isNull);
expect(ReactionHelper.parseReaction('r:abc:00'), isNull); // Hash too short
expect(ReactionHelper.parseReaction('r:abcde:00'), isNull); // Hash too long
expect(ReactionHelper.parseReaction('r:a1b2:0'), isNull); // Index too short
expect(ReactionHelper.parseReaction('r:a1b2:000'), isNull); // Index too long
expect(ReactionHelper.parseReaction('R:a1b2:00'), isNull); // Uppercase R
expect(ReactionHelper.parseReaction('r:A1B2:00'), isNull); // Uppercase hash
expect(
ReactionHelper.parseReaction('r:abc:00'),
isNull,
); // Hash too short
expect(
ReactionHelper.parseReaction('r:abcde:00'),
isNull,
); // Hash too long
expect(
ReactionHelper.parseReaction('r:a1b2:0'),
isNull,
); // Index too short
expect(
ReactionHelper.parseReaction('r:a1b2:000'),
isNull,
); // Index too long
expect(
ReactionHelper.parseReaction('R:a1b2:00'),
isNull,
); // Uppercase R
expect(
ReactionHelper.parseReaction('r:A1B2:00'),
isNull,
); // Uppercase hash
expect(ReactionHelper.parseReaction(''), isNull);
});
@@ -220,31 +349,43 @@ void main() {
const emoji = '🎉';
// Compute hash (sender side)
final hash = ReactionHelper.computeReactionHash(timestamp, senderName, messageText);
final hash = ReactionHelper.computeReactionHash(
timestamp,
senderName,
messageText,
);
// Encode emoji (sender side)
final emojiIndex = ReactionHelper.emojiToIndex(emoji);
expect(emojiIndex, isNotNull);
// Build reaction text (sender side)
final reactionText = 'r:$hash:$emojiIndex';
// Parse reaction (receiver side)
final info = ReactionHelper.parseReaction(reactionText);
expect(info, isNotNull);
expect(info!.targetHash, equals(hash));
expect(info.emoji, equals(emoji));
// Verify receiver can match the hash
final receiverHash = ReactionHelper.computeReactionHash(timestamp, senderName, messageText);
final receiverHash = ReactionHelper.computeReactionHash(
timestamp,
senderName,
messageText,
);
expect(receiverHash, equals(info.targetHash));
});
test('reaction text should be 9 bytes', () {
final hash = ReactionHelper.computeReactionHash(1234567890, 'Alice', 'Hello');
final hash = ReactionHelper.computeReactionHash(
1234567890,
'Alice',
'Hello',
);
final index = ReactionHelper.emojiToIndex('👍')!;
final reactionText = 'r:$hash:$index';
// r: (2) + hash (4) + : (1) + index (2) = 9 bytes
expect(reactionText.length, equals(9));
});
@@ -257,7 +398,11 @@ void main() {
const emoji = '👍';
// On Bob's device: message.isOutgoing = false, so senderName = contact.name = Alice
final bobSideHash = ReactionHelper.computeReactionHash(timestamp, aliceName, messageText);
final bobSideHash = ReactionHelper.computeReactionHash(
timestamp,
aliceName,
messageText,
);
final emojiIndex = ReactionHelper.emojiToIndex(emoji)!;
final reactionText = 'r:$bobSideHash:$emojiIndex';
@@ -266,8 +411,12 @@ void main() {
expect(info, isNotNull);
// On Alice's device: message.isOutgoing = true, so senderName = selfName = Alice
final aliceSideHash = ReactionHelper.computeReactionHash(timestamp, aliceName, messageText);
final aliceSideHash = ReactionHelper.computeReactionHash(
timestamp,
aliceName,
messageText,
);
// Hashes should match!
expect(info!.targetHash, equals(aliceSideHash));
expect(info.emoji, equals(emoji));
@@ -281,7 +430,11 @@ void main() {
const emoji = '❤️';
// On Alice's device: message.isOutgoing = false, so senderName = contact.name = Bob
final aliceSideHash = ReactionHelper.computeReactionHash(timestamp, bobName, messageText);
final aliceSideHash = ReactionHelper.computeReactionHash(
timestamp,
bobName,
messageText,
);
final emojiIndex = ReactionHelper.emojiToIndex(emoji)!;
final reactionText = 'r:$aliceSideHash:$emojiIndex';
@@ -290,8 +443,12 @@ void main() {
expect(info, isNotNull);
// On Bob's device: message.isOutgoing = true, so senderName = selfName = Bob
final bobSideHash = ReactionHelper.computeReactionHash(timestamp, bobName, messageText);
final bobSideHash = ReactionHelper.computeReactionHash(
timestamp,
bobName,
messageText,
);
// Hashes should match!
expect(info!.targetHash, equals(bobSideHash));
expect(info.emoji, equals(emoji));
@@ -306,7 +463,11 @@ void main() {
const emoji = '🎉';
// Alice computes hash including sender name (room servers are multi-user)
final aliceHash = ReactionHelper.computeReactionHash(timestamp, charlieName, messageText);
final aliceHash = ReactionHelper.computeReactionHash(
timestamp,
charlieName,
messageText,
);
final emojiIndex = ReactionHelper.emojiToIndex(emoji)!;
final reactionText = 'r:$aliceHash:$emojiIndex';
@@ -319,36 +480,59 @@ void main() {
expect(info, isNotNull);
// Bob computes hash for Charlie's message the same way
final bobHash = ReactionHelper.computeReactionHash(timestamp, charlieName, messageText);
final bobHash = ReactionHelper.computeReactionHash(
timestamp,
charlieName,
messageText,
);
// Hashes should match!
expect(info!.targetHash, equals(bobHash));
expect(info.emoji, equals(emoji));
});
test('room server: hash differs from 1:1 hash for same message content', () {
// Same timestamp and text, but room server includes sender name
const timestamp = 1234567890;
const senderName = 'Dave';
const messageText = 'Hello';
test(
'room server: hash differs from 1:1 hash for same message content',
() {
// Same timestamp and text, but room server includes sender name
const timestamp = 1234567890;
const senderName = 'Dave';
const messageText = 'Hello';
// Room server hash (with sender name)
final roomHash = ReactionHelper.computeReactionHash(timestamp, senderName, messageText);
// 1:1 hash (without sender name)
final directHash = ReactionHelper.computeReactionHash(timestamp, null, messageText);
// Room server hash (with sender name)
final roomHash = ReactionHelper.computeReactionHash(
timestamp,
senderName,
messageText,
);
// They should be different!
expect(roomHash, isNot(equals(directHash)));
});
// 1:1 hash (without sender name)
final directHash = ReactionHelper.computeReactionHash(
timestamp,
null,
messageText,
);
// They should be different!
expect(roomHash, isNot(equals(directHash)));
},
);
test('room server: different senders produce different hashes', () {
// Two users send the exact same message at the same time in a room
const timestamp = 1234567890;
const messageText = 'Hello';
final aliceHash = ReactionHelper.computeReactionHash(timestamp, 'Alice', messageText);
final bobHash = ReactionHelper.computeReactionHash(timestamp, 'Bob', messageText);
final aliceHash = ReactionHelper.computeReactionHash(
timestamp,
'Alice',
messageText,
);
final bobHash = ReactionHelper.computeReactionHash(
timestamp,
'Bob',
messageText,
);
// Different senders = different hashes (even with same content)
expect(aliceHash, isNot(equals(bobHash)));
@@ -363,7 +547,11 @@ void main() {
const emoji = '👍';
// Bob computes hash for Alice's message
final bobHash = ReactionHelper.computeReactionHash(timestamp, aliceName, messageText);
final bobHash = ReactionHelper.computeReactionHash(
timestamp,
aliceName,
messageText,
);
final emojiIndex = ReactionHelper.emojiToIndex(emoji)!;
final reactionText = 'r:$bobHash:$emojiIndex';
@@ -372,8 +560,12 @@ void main() {
expect(info, isNotNull);
// Alice computes hash using her selfName
final aliceHash = ReactionHelper.computeReactionHash(timestamp, aliceName, messageText);
final aliceHash = ReactionHelper.computeReactionHash(
timestamp,
aliceName,
messageText,
);
// Hashes should match!
expect(info!.targetHash, equals(aliceHash));
});
@@ -386,7 +578,11 @@ void main() {
const emoji = '🔥';
// Compute hash with sender name
final hash = ReactionHelper.computeReactionHash(timestamp, senderName, messageText);
final hash = ReactionHelper.computeReactionHash(
timestamp,
senderName,
messageText,
);
final emojiIndex = ReactionHelper.emojiToIndex(emoji)!;
final reactionText = 'r:$hash:$emojiIndex';
@@ -396,7 +592,11 @@ void main() {
expect(info!.emoji, equals(emoji));
// Another user computes the same hash
final otherUserHash = ReactionHelper.computeReactionHash(timestamp, senderName, messageText);
final otherUserHash = ReactionHelper.computeReactionHash(
timestamp,
senderName,
messageText,
);
expect(info.targetHash, equals(otherUserHash));
});
});