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
Signed-off-by: cls_宁波本机 <908705107@qq.com>
304 lines
7.9 KiB
Dart
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);
|
|
});
|
|
});
|
|
}
|