Files
cls 9dfa06ffee
Docker image / Build (linux/amd64) (push) Has been cancelled
Docker image / Build (linux/arm64) (push) Has been cancelled
Docker image / Merge release multi-arch manifest (push) Has been cancelled
Docker image / Merge debug multi-arch manifest (push) Has been cancelled
Docker image / Build public push gateway (linux/amd64) (push) Has been cancelled
Docker image / Build public push gateway (linux/arm64) (push) Has been cancelled
Docker image / Publish public push gateway image (push) Has been cancelled
Sprig image / Build (linux/amd64) (push) Has been cancelled
Sprig image / Build (linux/arm64) (push) Has been cancelled
Sprig image / Merge multi-arch manifest (push) Has been cancelled
Harbor Buzz Orchestra / Python tests and lint (push) Has been cancelled
CI / Detect Changed Paths (push) Has been cancelled
CI / Rust Lint (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Desktop Core (push) Has been cancelled
CI / Desktop Smoke E2E (1) (push) Has been cancelled
CI / Desktop Smoke E2E (2) (push) Has been cancelled
CI / Desktop Smoke E2E (3) (push) Has been cancelled
CI / Desktop Smoke E2E (4) (push) Has been cancelled
CI / Desktop (push) Has been cancelled
CI / Desktop E2E Relay (push) Has been cancelled
CI / Desktop E2E Integration (1/2) (push) Has been cancelled
CI / Desktop E2E Integration (2/2) (push) Has been cancelled
CI / Desktop E2E Integration (push) Has been cancelled
CI / Backend Integration (relay e2e) (push) Has been cancelled
CI / Relay E2E (push) Has been cancelled
CI / Web (push) Has been cancelled
CI / Mobile (push) Has been cancelled
CI / Security (push) Has been cancelled
CI / Dead Token Reference Guard (push) Has been cancelled
CI / Server Cross-Compile (aarch64-unknown-linux-musl) (push) Has been cancelled
CI / Server Cross-Compile (x86_64-unknown-linux-musl) (push) Has been cancelled
CI / Windows Rust (x86_64-pc-windows-msvc) (push) Has been cancelled
CI / Desktop Build (macOS) (push) Has been cancelled
helm chart / lint + unittest + render matrix (push) Has been cancelled
helm chart / install on kind (gated) (push) Has been cancelled
helm chart / publish chart to GHCR (push) Has been cancelled
Mesh Lifecycle / Relay-Driven Mesh Lifecycle Smoke (push) Has been cancelled
Sprig / Build (aarch64-unknown-linux-musl) (push) Has been cancelled
Sprig / Build (x86_64-unknown-linux-musl) (push) Has been cancelled
Sprig / Publish rolling release (push) Has been cancelled
Sprig / Publish tagged release (push) Has been cancelled
feat: import Chinese-localized Buzz source snapshot
Signed-off-by: cls_宁波本机 <908705107@qq.com>
2026-08-13 18:34:25 +08:00

304 lines
7.9 KiB
Dart

import 'package:flutter_test/flutter_test.dart';
import 'package:buzz/features/activity/feed_item.dart';
void main() {
group('FeedItem.fromJson', () {
test('parses all fields', () {
final item = FeedItem.fromJson({
'id': 'evt1',
'kind': 9,
'pubkey': 'abc123',
'content': 'Hello world',
'created_at': 1700000000,
'channel_id': 'ch1',
'channel_name': 'general',
'tags': [
['p', 'abc123'],
],
'category': 'mention',
});
expect(item.id, 'evt1');
expect(item.kind, 9);
expect(item.pubkey, 'abc123');
expect(item.content, 'Hello world');
expect(item.createdAt, 1700000000);
expect(item.channelId, 'ch1');
expect(item.channelName, 'general');
expect(item.tags, [
['p', 'abc123'],
]);
expect(item.category, 'mention');
});
test('handles null channel_id', () {
final item = FeedItem.fromJson({
'id': 'evt2',
'kind': 9,
'pubkey': 'abc',
'content': '',
'created_at': 0,
'channel_id': null,
'channel_name': null,
'tags': null,
'category': 'activity',
});
expect(item.channelId, isNull);
expect(item.channelName, '');
expect(item.tags, isEmpty);
});
});
group('FeedItem.threadHeadId', () {
FeedItem makeItem(List<List<String>> tags) => FeedItem(
id: 'reply',
kind: 9,
pubkey: 'pk',
content: '',
createdAt: 0,
channelId: 'channel',
channelName: '',
tags: tags,
category: 'mention',
);
test('uses the reply marker for a direct thread reply', () {
expect(
makeItem(const [
['e', 'root', '', 'reply'],
]).threadHeadId,
'root',
);
});
test('uses the direct parent marker for a nested thread reply', () {
expect(
makeItem(const [
['e', 'root', '', 'root'],
['e', 'parent', '', 'reply'],
]).threadHeadId,
'parent',
);
});
test('does not treat unrelated event references as threads', () {
expect(
makeItem(const [
['e', 'linked-event'],
]).threadHeadId,
isNull,
);
});
});
group('FeedItem.headline', () {
FeedItem makeItem({required int kind, String category = 'activity'}) =>
FeedItem(
id: 'x',
kind: kind,
pubkey: 'pk',
content: '',
createdAt: 0,
channelId: null,
channelName: '',
tags: const [],
category: category,
);
test('returns known kind labels', () {
expect(makeItem(kind: 45001).headline, 'Forum post');
expect(makeItem(kind: 45003).headline, 'Forum reply');
expect(makeItem(kind: 46010).headline, 'Approval requested');
expect(makeItem(kind: 43001).headline, 'Job requested');
expect(makeItem(kind: 43002).headline, 'Job accepted');
expect(makeItem(kind: 43003).headline, 'Progress update');
expect(makeItem(kind: 43004).headline, 'Job result');
expect(makeItem(kind: 43005).headline, 'Job cancelled');
expect(makeItem(kind: 43006).headline, 'Job failed');
});
test('falls back to category for unknown kinds', () {
expect(makeItem(kind: 9, category: 'mention').headline, 'Mention');
expect(
makeItem(kind: 9, category: 'agent_activity').headline,
'Agent update',
);
expect(
makeItem(kind: 9, category: 'activity').headline,
'Channel update',
);
});
});
group('FeedItem.displayContent', () {
FeedItem makeItem({required String content, int kind = 9}) => FeedItem(
id: 'x',
kind: kind,
pubkey: 'pk',
content: content,
createdAt: 0,
channelId: null,
channelName: '',
tags: const [],
category: 'activity',
);
test('returns trimmed content when non-empty', () {
expect(makeItem(content: ' Hello ').displayContent, 'Hello');
});
test('returns approval fallback for empty approval events', () {
expect(
makeItem(content: '', kind: 46010).displayContent,
'A workflow is waiting for approval.',
);
});
test('returns generic fallback for other empty events', () {
expect(makeItem(content: '').displayContent, 'No additional details.');
expect(makeItem(content: ' ').displayContent, 'No additional details.');
});
});
group('HomeFeedResponse', () {
test('parses from JSON with all four categories', () {
final response = HomeFeedResponse.fromJson({
'feed': {
'mentions': [
{
'id': 'm1',
'kind': 9,
'pubkey': 'pk',
'content': 'hi',
'created_at': 100,
'channel_id': 'c1',
'channel_name': 'general',
'tags': [],
'category': 'mention',
},
],
'needs_action': [],
'activity': [
{
'id': 'a1',
'kind': 9,
'pubkey': 'pk',
'content': 'update',
'created_at': 200,
'channel_id': 'c2',
'channel_name': 'dev',
'tags': [],
'category': 'activity',
},
],
'agent_activity': [],
},
'meta': {'since': 0, 'total': 2, 'generated_at': 300},
});
expect(response.mentions.length, 1);
expect(response.needsAction, isEmpty);
expect(response.activity.length, 1);
expect(response.agentActivity, isEmpty);
});
test('handles null category lists gracefully', () {
final response = HomeFeedResponse.fromJson({
'feed': {
'mentions': null,
'needs_action': null,
'activity': null,
'agent_activity': null,
},
});
expect(response.mentions, isEmpty);
expect(response.isEmpty, isTrue);
});
test('all merges and sorts newest-first', () {
final response = HomeFeedResponse(
mentions: [
FeedItem(
id: 'old',
kind: 9,
pubkey: 'pk',
content: '',
createdAt: 100,
channelId: null,
channelName: '',
tags: const [],
category: 'mention',
),
],
needsAction: const [],
activity: [
FeedItem(
id: 'new',
kind: 9,
pubkey: 'pk',
content: '',
createdAt: 300,
channelId: null,
channelName: '',
tags: const [],
category: 'activity',
),
],
agentActivity: [
FeedItem(
id: 'mid',
kind: 9,
pubkey: 'pk',
content: '',
createdAt: 200,
channelId: null,
channelName: '',
tags: const [],
category: 'agent_activity',
),
],
);
final all = response.all;
expect(all.length, 3);
expect(all[0].id, 'new');
expect(all[1].id, 'mid');
expect(all[2].id, 'old');
});
test('isEmpty returns true when all lists empty', () {
final response = HomeFeedResponse(
mentions: [],
needsAction: [],
activity: [],
agentActivity: [],
);
expect(response.isEmpty, isTrue);
});
test('isEmpty returns false when any list has items', () {
final response = HomeFeedResponse(
mentions: [
FeedItem(
id: 'x',
kind: 9,
pubkey: 'pk',
content: '',
createdAt: 0,
channelId: null,
channelName: '',
tags: const [],
category: 'mention',
),
],
needsAction: const [],
activity: const [],
agentActivity: const [],
);
expect(response.isEmpty, isFalse);
});
});
}