Parse and validate AT Protocol Lexicons with DTO generation for Laravel
at dev 171 lines 6.3 kB view raw
1<?php 2 3namespace SocialDept\AtpSchema\Tests\Unit\Generator; 4 5use Orchestra\Testbench\TestCase; 6use SocialDept\AtpSchema\Generator\NamingConverter; 7 8class NamingConverterTest extends TestCase 9{ 10 protected NamingConverter $converter; 11 12 protected function setUp(): void 13 { 14 parent::setUp(); 15 16 $this->converter = new NamingConverter('App\\Lexicon'); 17 } 18 19 public function test_it_converts_nsid_to_class_name(): void 20 { 21 $className = $this->converter->nsidToClassName('app.bsky.feed.post'); 22 23 $this->assertSame('App\\Lexicon\\App\\Bsky\\Feed\\Post', $className); 24 } 25 26 public function test_it_converts_nsid_to_namespace(): void 27 { 28 $namespace = $this->converter->nsidToNamespace('app.bsky.feed.post'); 29 30 $this->assertSame('App\\Lexicon\\App\\Bsky\\Feed', $namespace); 31 } 32 33 public function test_it_handles_multi_part_names(): void 34 { 35 $className = $this->converter->toClassName('feed.post'); 36 37 $this->assertSame('FeedPost', $className); 38 } 39 40 public function test_it_handles_single_part_names(): void 41 { 42 $className = $this->converter->toClassName('post'); 43 44 $this->assertSame('Post', $className); 45 } 46 47 public function test_it_converts_to_pascal_case(): void 48 { 49 $this->assertSame('HelloWorld', $this->converter->toPascalCase('hello_world')); 50 $this->assertSame('HelloWorld', $this->converter->toPascalCase('hello-world')); 51 $this->assertSame('HelloWorld', $this->converter->toPascalCase('hello world')); 52 $this->assertSame('HelloWorld', $this->converter->toPascalCase('helloWorld')); 53 $this->assertSame('Foo', $this->converter->toPascalCase('foo')); 54 } 55 56 public function test_it_converts_to_camel_case(): void 57 { 58 $this->assertSame('helloWorld', $this->converter->toCamelCase('hello_world')); 59 $this->assertSame('helloWorld', $this->converter->toCamelCase('hello-world')); 60 $this->assertSame('helloWorld', $this->converter->toCamelCase('hello world')); 61 $this->assertSame('helloWorld', $this->converter->toCamelCase('HelloWorld')); 62 $this->assertSame('foo', $this->converter->toCamelCase('foo')); 63 } 64 65 public function test_it_converts_to_snake_case(): void 66 { 67 $this->assertSame('hello_world', $this->converter->toSnakeCase('HelloWorld')); 68 $this->assertSame('hello_world', $this->converter->toSnakeCase('helloWorld')); 69 $this->assertSame('foo', $this->converter->toSnakeCase('foo')); 70 $this->assertSame('foo_bar_baz', $this->converter->toSnakeCase('FooBarBaz')); 71 } 72 73 public function test_it_converts_to_kebab_case(): void 74 { 75 $this->assertSame('hello-world', $this->converter->toKebabCase('HelloWorld')); 76 $this->assertSame('hello-world', $this->converter->toKebabCase('helloWorld')); 77 $this->assertSame('foo', $this->converter->toKebabCase('foo')); 78 $this->assertSame('foo-bar-baz', $this->converter->toKebabCase('FooBarBaz')); 79 } 80 81 public function test_it_pluralizes_words(): void 82 { 83 $this->assertSame('posts', $this->converter->pluralize('post')); 84 $this->assertSame('categories', $this->converter->pluralize('category')); 85 $this->assertSame('boxes', $this->converter->pluralize('box')); 86 $this->assertSame('churches', $this->converter->pluralize('church')); 87 $this->assertSame('bushes', $this->converter->pluralize('bush')); 88 $this->assertSame('postses', $this->converter->pluralize('posts')); // 'posts' ends with 's', gets 'es' 89 } 90 91 public function test_it_singularizes_words(): void 92 { 93 $this->assertSame('post', $this->converter->singularize('posts')); 94 $this->assertSame('category', $this->converter->singularize('categories')); 95 $this->assertSame('box', $this->converter->singularize('boxes')); 96 $this->assertSame('church', $this->converter->singularize('churches')); 97 $this->assertSame('bush', $this->converter->singularize('bushes')); 98 $this->assertSame('post', $this->converter->singularize('post')); // Already singular 99 } 100 101 public function test_it_handles_complex_nsid(): void 102 { 103 $className = $this->converter->nsidToClassName('com.atproto.repo.getRecord'); 104 105 $this->assertSame('App\\Lexicon\\Com\\Atproto\\Repo\\GetRecord', $className); 106 } 107 108 public function test_it_gets_base_namespace(): void 109 { 110 $namespace = $this->converter->getBaseNamespace(); 111 112 $this->assertSame('App\\Lexicon', $namespace); 113 } 114 115 public function test_it_sets_base_namespace(): void 116 { 117 $this->converter->setBaseNamespace('Custom\\Namespace'); 118 119 $this->assertSame('Custom\\Namespace', $this->converter->getBaseNamespace()); 120 } 121 122 public function test_it_strips_trailing_slash_from_namespace(): void 123 { 124 $converter = new NamingConverter('App\\Lexicon\\'); 125 126 $this->assertSame('App\\Lexicon', $converter->getBaseNamespace()); 127 } 128 129 public function test_it_handles_three_part_authority(): void 130 { 131 $className = $this->converter->nsidToClassName('com.example.api.getUser'); 132 133 $this->assertSame('App\\Lexicon\\Com\\Example\\Api\\GetUser', $className); 134 } 135 136 public function test_it_handles_hyphens_in_names(): void 137 { 138 $className = $this->converter->toClassName('my-post'); 139 140 $this->assertSame('MyPost', $className); 141 } 142 143 public function test_it_handles_underscores_in_names(): void 144 { 145 $className = $this->converter->toClassName('my_post'); 146 147 $this->assertSame('MyPost', $className); 148 } 149 150 public function test_namespace_parts_are_reversed(): void 151 { 152 // app.bsky.feed should become App\Bsky\Feed (authority-first) 153 $namespace = $this->converter->nsidToNamespace('app.bsky.feed.post'); 154 155 $this->assertStringContainsString('App\\Bsky\\Feed', $namespace); 156 } 157 158 public function test_it_handles_single_letter_parts(): void 159 { 160 $pascalCase = $this->converter->toPascalCase('a'); 161 162 $this->assertSame('A', $pascalCase); 163 } 164 165 public function test_it_handles_numbers_in_names(): void 166 { 167 $className = $this->converter->toClassName('post2'); 168 169 $this->assertSame('Post2', $className); 170 } 171}