Build Reactive Signals for Bluesky's AT Protocol Firehose in Laravel
1<?php
2
3namespace SocialDept\AtpSignals\Tests\Unit;
4
5use Orchestra\Testbench\TestCase;
6use SocialDept\AtpSignals\Events\CommitEvent;
7use SocialDept\AtpSignals\Events\SignalEvent;
8use SocialDept\AtpSignals\Services\SignalRegistry;
9
10class SignalRegistryTest extends TestCase
11{
12 /** @test */
13 public function it_matches_exact_collections()
14 {
15 $registry = new SignalRegistry();
16
17 $event = new SignalEvent(
18 did: 'did:plc:test',
19 timeUs: time() * 1000000,
20 kind: 'commit',
21 commit: new CommitEvent(
22 rev: 'test',
23 operation: 'create',
24 collection: 'app.bsky.feed.post',
25 rkey: 'test',
26 ),
27 );
28
29 $result = $this->invokeMethod(
30 $registry,
31 'matchesCollection',
32 ['app.bsky.feed.post', ['app.bsky.feed.post']]
33 );
34
35 $this->assertTrue($result);
36 }
37
38 /** @test */
39 public function it_matches_wildcard_collections()
40 {
41 $registry = new SignalRegistry();
42
43 // Test app.bsky.feed.*
44 $this->assertTrue(
45 $this->invokeMethod(
46 $registry,
47 'matchesCollection',
48 ['app.bsky.feed.post', ['app.bsky.feed.*']]
49 )
50 );
51
52 $this->assertTrue(
53 $this->invokeMethod(
54 $registry,
55 'matchesCollection',
56 ['app.bsky.feed.like', ['app.bsky.feed.*']]
57 )
58 );
59
60 $this->assertFalse(
61 $this->invokeMethod(
62 $registry,
63 'matchesCollection',
64 ['app.bsky.graph.follow', ['app.bsky.feed.*']]
65 )
66 );
67
68 // Test app.bsky.*
69 $this->assertTrue(
70 $this->invokeMethod(
71 $registry,
72 'matchesCollection',
73 ['app.bsky.feed.post', ['app.bsky.*']]
74 )
75 );
76
77 $this->assertTrue(
78 $this->invokeMethod(
79 $registry,
80 'matchesCollection',
81 ['app.bsky.graph.follow', ['app.bsky.*']]
82 )
83 );
84 }
85
86 /** @test */
87 public function it_matches_multiple_patterns()
88 {
89 $registry = new SignalRegistry();
90
91 $patterns = [
92 'app.bsky.feed.post',
93 'app.bsky.graph.*',
94 ];
95
96 // Exact match
97 $this->assertTrue(
98 $this->invokeMethod(
99 $registry,
100 'matchesCollection',
101 ['app.bsky.feed.post', $patterns]
102 )
103 );
104
105 // Wildcard match
106 $this->assertTrue(
107 $this->invokeMethod(
108 $registry,
109 'matchesCollection',
110 ['app.bsky.graph.follow', $patterns]
111 )
112 );
113
114 // No match
115 $this->assertFalse(
116 $this->invokeMethod(
117 $registry,
118 'matchesCollection',
119 ['app.bsky.feed.like', $patterns]
120 )
121 );
122 }
123
124 /**
125 * Call protected/private method of a class.
126 */
127 protected function invokeMethod(&$object, $methodName, array $parameters = [])
128 {
129 $reflection = new \ReflectionClass(get_class($object));
130 $method = $reflection->getMethod($methodName);
131 $method->setAccessible(true);
132
133 return $method->invokeArgs($object, $parameters);
134 }
135}