Parse and validate AT Protocol Lexicons with DTO generation for Laravel
1<?php
2
3namespace SocialDept\AtpSchema\Tests\Unit\Parser;
4
5use PHPUnit\Framework\TestCase;
6use SocialDept\AtpSchema\Exceptions\SchemaException;
7use SocialDept\AtpSchema\Parser\Nsid;
8
9class NsidTest extends TestCase
10{
11 public function test_it_parses_valid_nsid(): void
12 {
13 $nsid = Nsid::parse('app.bsky.feed.post');
14
15 $this->assertInstanceOf(Nsid::class, $nsid);
16 $this->assertSame('app.bsky.feed.post', $nsid->toString());
17 }
18
19 public function test_it_extracts_authority(): void
20 {
21 $nsid = Nsid::parse('app.bsky.feed.post');
22
23 $this->assertSame('app.bsky.feed', $nsid->getAuthority());
24 }
25
26 public function test_it_extracts_name(): void
27 {
28 $nsid = Nsid::parse('app.bsky.feed.post');
29
30 $this->assertSame('post', $nsid->getName());
31 }
32
33 public function test_it_gets_segments(): void
34 {
35 $nsid = Nsid::parse('app.bsky.feed.post');
36
37 $this->assertSame(['app', 'bsky', 'feed', 'post'], $nsid->getSegments());
38 }
39
40 public function test_it_converts_to_domain(): void
41 {
42 $nsid = Nsid::parse('app.bsky.feed.post');
43
44 $this->assertSame('post.feed.bsky.app', $nsid->toDomain());
45 }
46
47 public function test_it_gets_authority_domain(): void
48 {
49 $nsid = Nsid::parse('app.bsky.feed.post');
50
51 $this->assertSame('feed.bsky.app', $nsid->getAuthorityDomain());
52 }
53
54 public function test_it_converts_to_string(): void
55 {
56 $nsid = Nsid::parse('app.bsky.feed.post');
57
58 $this->assertSame('app.bsky.feed.post', (string) $nsid);
59 }
60
61 public function test_it_validates_nsid_format(): void
62 {
63 $this->assertTrue(Nsid::isValid('app.bsky.feed.post'));
64 $this->assertTrue(Nsid::isValid('com.atproto.repo.getRecord'));
65 $this->assertTrue(Nsid::isValid('com.example.my-app.action'));
66 }
67
68 public function test_it_rejects_invalid_nsids(): void
69 {
70 $this->assertFalse(Nsid::isValid(''));
71 $this->assertFalse(Nsid::isValid('invalid'));
72 $this->assertFalse(Nsid::isValid('no.dots'));
73 $this->assertFalse(Nsid::isValid('app.bsky'));
74 $this->assertFalse(Nsid::isValid('.invalid.nsid'));
75 $this->assertFalse(Nsid::isValid('invalid.nsid.'));
76 $this->assertFalse(Nsid::isValid('invalid..nsid.test'));
77 }
78
79 public function test_it_throws_on_empty_nsid(): void
80 {
81 $this->expectException(SchemaException::class);
82 $this->expectExceptionMessage('NSID cannot be empty');
83
84 Nsid::parse('');
85 }
86
87 public function test_it_throws_on_too_few_segments(): void
88 {
89 $this->expectException(SchemaException::class);
90 $this->expectExceptionMessage('NSID must have at least 3 segments');
91
92 Nsid::parse('app.bsky');
93 }
94
95 public function test_it_throws_on_invalid_format(): void
96 {
97 $this->expectException(SchemaException::class);
98 $this->expectExceptionMessage('Invalid NSID format');
99
100 Nsid::parse('invalid-nsid');
101 }
102
103 public function test_it_checks_equality(): void
104 {
105 $nsid1 = Nsid::parse('app.bsky.feed.post');
106 $nsid2 = Nsid::parse('app.bsky.feed.post');
107 $nsid3 = Nsid::parse('app.bsky.feed.like');
108
109 $this->assertTrue($nsid1->equals($nsid2));
110 $this->assertFalse($nsid1->equals($nsid3));
111 }
112
113 public function test_it_handles_long_nsids(): void
114 {
115 $nsid = Nsid::parse('com.example.very.long.namespace.with.many.segments.action');
116
117 $this->assertSame('action', $nsid->getName());
118 $this->assertSame('com.example.very.long.namespace.with.many.segments', $nsid->getAuthority());
119 }
120
121 public function test_it_handles_hyphens(): void
122 {
123 $nsid = Nsid::parse('com.my-app.feed.get-posts');
124
125 $this->assertSame('get-posts', $nsid->getName());
126 $this->assertSame('com.my-app.feed', $nsid->getAuthority());
127 }
128
129 public function test_it_rejects_nsid_exceeding_max_length(): void
130 {
131 $this->expectException(SchemaException::class);
132 $this->expectExceptionMessage('NSID exceeds maximum length');
133
134 // Create a string longer than 317 characters
135 $longNsid = str_repeat('a.', 160) . 'test';
136 Nsid::parse($longNsid);
137 }
138}