Completed
Pull Request — master (#107)
by Simon
03:50 queued 01:55
created

testShortFileContentWithAnnotations()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 39
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 22
nc 1
nop 0
dl 0
loc 39
rs 8.8571
c 0
b 0
f 0
1
<?php
2
3
namespace SilverLeague\IDEAnnotator\Tests;
4
5
use PageController;
6
use PHPUnit_Framework_TestCase;
7
use RootTeam;
8
use SilverLeague\IDEAnnotator\Annotatable;
9
use SilverLeague\IDEAnnotator\AnnotateClassInfo;
10
use SilverLeague\IDEAnnotator\AnnotatePermissionChecker;
11
use SilverLeague\IDEAnnotator\DataObjectAnnotator;
12
use SilverStripe\Control\Director;
13
use SilverStripe\Core\Config\Config;
14
use SilverStripe\Core\Injector\Injector;
15
use SilverStripe\Dev\SapphireTest;
16
use SilverStripe\ORM\DataObject;
17
18
/**
19
 * Class DataObjectAnnotatorTest
20
 *
21
 * Several tests to make sure the Annotator does it's job correctly
22
 *
23
 * @mixin PHPUnit_Framework_TestCase
24
 */
25
class DataObjectAnnotatorTest extends SapphireTest
26
{
27
28
    /**
29
     * @var MockDataObjectAnnotator
30
     */
31
    private $annotator;
32
33
    /**
34
     * @var AnnotatePermissionChecker $permissionChecker
35
     */
36
    private $permissionChecker;
37
38
    /**
39
     * Setup Defaults
40
     */
41
    protected function setUp()
42
    {
43
        parent::setUp();
44
        Config::modify()->set(DataObjectAnnotator::class, 'use_short_name', false);
45
46
        Config::modify()->set(DataObjectAnnotator::class, 'enabled', true);
47
        Config::modify()->set(DataObjectAnnotator::class, 'enabled_modules', ['silverleague/ideannotator']);
48
49
        $this->annotator = Injector::inst()->get(MockDataObjectAnnotator::class);
50
        $this->permissionChecker = Injector::inst()->get(AnnotatePermissionChecker::class);
51
    }
52
53
    public function testIsEnabled()
54
    {
55
        $this->assertTrue(DataObjectAnnotator::isEnabled());
56
    }
57
58
    /**
59
     * Test the expected classes show up in the Classes for Module
60
     */
61
    public function testGetClassesForModule()
62
    {
63
        $expectedClasses = [
64
            Team::class                             => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'DataObjectAnnotatorTest_Team.php',
65
            TeamChanged::class                      => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'DataObjectAnnotatorTest_TeamChanged.php',
66
            TeamComment::class                      => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'DataObjectAnnotatorTest_TeamComment.php',
67
            DocBlockMockWithDocBlock::class         => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'DocBlockMockWithDocBlock.php',
68
            OtherDocBlockMockWithDocBlock::class    => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'DocBlockMockWithDocBlock.php',
69
            DataObjectWithOldStyleTagMarkers::class => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'DocBlockMockWithDocBlock.php',
70
            DoubleDataObjectInOneFile1::class       => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'DoubleDataObjectInOneFile.php',
71
            DoubleDataObjectInOneFile2::class       => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'DoubleDataObjectInOneFile.php',
72
            SubTeam::class                          => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'DataObjectAnnotatorTest_SubTeam.php',
73
            Player::class                           => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'DataObjectAnnotatorTest_Player.php',
74
            Team_Extension::class                   => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'DataObjectAnnotatorTest_Team_Extension.php',
75
            Annotatable::class                      => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'Extensions' . DIRECTORY_SEPARATOR . 'Annotatable.php',
76
            AnnotatorPageTest_Extension::class      => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'AnnotatorPageTest.php',
77
            RootTeam::class                         => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'RootTeam.php',
78
            AnnotatorPageTest::class                => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'AnnotatorPageTest.php',
79
            AnnotatorPageTestController::class      => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'AnnotatorPageTest.php',
80
            TeamSupporter::class                    => Director::baseFolder() . DIRECTORY_SEPARATOR . 'ideannotator' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR . 'DataObjectAnnotatorTest_TeamSupporter.php',
81
        ];
82
        $classes = $this->annotator->getClassesForModule('silverleague/ideannotator');
83
        // Sort the array, so we don't get accidental errors due to manual ordering
84
        ksort($expectedClasses);
85
        ksort($classes);
86
        $this->assertEquals($expectedClasses, $classes);
87
    }
88
89
90
    /**
91
     * As below, as we don't want to actively change the mocks, so enable mysite
92
     */
93
    public function testAnnotateObject()
94
    {
95
        $this->assertFalse($this->annotator->annotateObject(DataObject::class));
96
97
        Config::modify()->set(DataObjectAnnotator::class, 'enabled_modules', ['ideannotator', 'mysite']);
98
        $this->assertTrue($this->annotator->annotateObject(PageController::class));
99
    }
100
101
    /**
102
     * Not testing existing modules, as it wil actively alter the mock files, so enable mysite
103
     */
104
    public function testAnnotateModule()
105
    {
106
        $noModule = $this->annotator->annotateModule('');
107
        $this->assertFalse($noModule);
108
        $noModule = $this->annotator->annotateModule('mysite');
109
        $this->assertFalse($noModule);
110
        // Enable 'mysite' for testing
111
        Config::modify()->set(DataObjectAnnotator::class, 'enabled_modules', ['ideannotator', 'mysite']);
112
113
        $module = $this->annotator->annotateModule('mysite');
114
        $this->assertTrue($module);
115
    }
116
117
    /**
118
     * Test if the correct annotations are generated
119
     * for all database fields, relations and extensions
120
     * and that the start and end tags are present
121
     */
122
    public function testFileContentWithAnnotations()
123
    {
124
        $classInfo = new AnnotateClassInfo(Team::class);
125
        $filePath = $classInfo->getClassFilePath();
126
127
        $content = $this->annotator->getGeneratedFileContent(file_get_contents($filePath), Team::class);
128
129
        // ClassName title
130
        $this->assertContains(' * Class \SilverLeague\IDEAnnotator\Tests\Team', $content);
131
132
        // database fields
133
        $this->assertContains('@property string $Title', $content);
134
        $this->assertContains('@property int $VisitCount', $content);
135
        $this->assertContains('@property float $Price', $content);
136
        $this->assertContains('@property string $Dude', $content);
137
        $this->assertContains('@property string $Dudette', $content);
138
139
        // has_one ID
140
        $this->assertContains('@property int $CaptainID', $content);
141
        // has_one relation
142
        $this->assertContains('@method \SilverLeague\IDEAnnotator\Tests\Player Captain()', $content);
143
        // has_many relation
144
        $this->assertContains(
145
            '@method \SilverStripe\ORM\DataList|\SilverLeague\IDEAnnotator\Tests\SubTeam[] SubTeams()',
146
            $content
147
        );
148
        // many_many relation
149
        $this->assertContains(
150
            '@method \SilverStripe\ORM\ManyManyList|\SilverLeague\IDEAnnotator\Tests\Player[] Players()',
151
            $content
152
        );
153
        $this->assertContains(
154
            '@method \SilverStripe\ORM\ManyManyList|\SilverLeague\IDEAnnotator\Tests\Player[] Reserves()',
155
            $content
156
        );
157
        $this->assertContains(
158
            '@method \SilverStripe\ORM\DataList|\SilverLeague\IDEAnnotator\Tests\TeamSupporter[] Supporters()',
159
            $content
160
        );
161
162
        // DataExtension
163
        $this->assertContains('@mixin \SilverLeague\IDEAnnotator\Tests\Team_Extension', $content);
164
    }
165
166
    /**
167
     * Test if the correct annotations are generated
168
     * for all database fields, relations and extensions
169
     * and that the start and end tags are present
170
     */
171
    public function testShortFileContentWithAnnotations()
172
    {
173
        Config::modify()->set(DataObjectAnnotator::class, 'use_short_name', true);
174
175
        $classInfo = new AnnotateClassInfo(Team::class);
176
        $filePath = $classInfo->getClassFilePath();
177
178
        $content = $this->annotator->getGeneratedFileContent(file_get_contents($filePath), Team::class);
179
180
        // database fields
181
        $this->assertContains('@property string $Title', $content);
182
        $this->assertContains('@property int $VisitCount', $content);
183
        $this->assertContains('@property float $Price', $content);
184
185
        // has_one ID
186
        $this->assertContains('@property int $CaptainID', $content);
187
        // has_one relation
188
        $this->assertContains('@method Player Captain()', $content);
189
        // has_many relation
190
        $this->assertContains(
191
            '@method DataList|SubTeam[] SubTeams()',
192
            $content
193
        );
194
        // many_many relation
195
        $this->assertContains(
196
            '@method ManyManyList|Player[] Players()',
197
            $content
198
        );
199
        $this->assertContains(
200
            '@method ManyManyList|Player[] Reserves()',
201
            $content
202
        );
203
        $this->assertContains(
204
            '@method DataList|TeamSupporter[] Supporters()',
205
            $content
206
        );
207
208
        // DataExtension
209
        $this->assertContains('@mixin Team_Extension', $content);
210
    }
211
212
    
213
    public function testInversePlayerRelationOfTeam()
214
    {
215
        $classInfo = new AnnotateClassInfo(Player::class);
216
        $filePath = $classInfo->getClassFilePath();
217
218
        $content = $this->annotator->getGeneratedFileContent(file_get_contents($filePath), Player::class);
219
220
        $this->assertContains('@property boolean $IsRetired', $content);
221
        $this->assertContains('@property string $ShirtNumber', $content);
222
        $this->assertContains('@property string $Shirt', $content);
223
        $this->assertContains('@property int $FavouriteTeamID', $content);
224
        $this->assertContains('@method \SilverLeague\IDEAnnotator\Tests\Team FavouriteTeam()', $content);
225
226
        $this->assertContains(
227
            '@method \SilverStripe\ORM\ManyManyList|\SilverLeague\IDEAnnotator\Tests\Team[] TeamPlayer()',
228
            $content
229
        );
230
        $this->assertContains(
231
            '@method \SilverStripe\ORM\ManyManyList|\SilverLeague\IDEAnnotator\Tests\Team[] TeamReserve()',
232
            $content
233
        );
234
    }
235
    
236
    public function testShortInversePlayerRelationOfTeam()
237
    {
238
        Config::modify()->set(DataObjectAnnotator::class, 'use_short_name', true);
239
240
        $classInfo = new AnnotateClassInfo(Player::class);
241
        $filePath = $classInfo->getClassFilePath();
242
243
        $content = $this->annotator->getGeneratedFileContent(file_get_contents($filePath), Player::class);
244
245
        $this->assertContains('@property boolean $IsRetired', $content);
246
        $this->assertContains('@property string $ShirtNumber', $content);
247
        $this->assertContains('@property int $FavouriteTeamID', $content);
248
        $this->assertContains('@method Team FavouriteTeam()', $content);
249
250
        $this->assertContains(
251
            '@method ManyManyList|Team[] TeamPlayer()',
252
            $content
253
        );
254
        $this->assertContains(
255
            '@method ManyManyList|Team[] TeamReserve()',
256
            $content
257
        );
258
    }
259
260
    public function testExistingMethodsWillNotBeTagged()
261
    {
262
        $classInfo = new AnnotateClassInfo(Team::class);
263
        $filePath = $classInfo->getClassFilePath();
264
265
        $content = $this->annotator->getGeneratedFileContent(file_get_contents($filePath), Team::class);
266
        $this->assertNotContains(
267
            '@method \SilverStripe\ORM\ManyManyList|\SilverLeague\IDEAnnotator\Tests\SubTeam[] SecondarySubTeams()',
268
            $content
269
        );
270
    }
271
272
    public function testShortExistingMethodsWillNotBeTagged()
273
    {
274
        Config::modify()->set(DataObjectAnnotator::class, 'use_short_name', true);
275
276
        $classInfo = new AnnotateClassInfo(Team::class);
277
        $filePath = $classInfo->getClassFilePath();
278
279
        $content = $this->annotator->getGeneratedFileContent(file_get_contents($filePath), Team::class);
280
        $this->assertNotContains(
281
            '@method ManyManyList|SubTeam[] SecondarySubTeams()',
282
            $content
283
        );
284
    }
285
286
    /**
287
     * Test that multiple annotation runs won't generate ducplicate docblocks
288
     */
289
    public function testNothingHasChangedAfterSecondAnnotation()
290
    {
291
        $classInfo = new AnnotateClassInfo(Team::class);
292
        $filePath = $classInfo->getClassFilePath();
293
        $original = file_get_contents($filePath);
294
        $firstRun = $this->annotator->getGeneratedFileContent($original, Team::class);
295
        $secondRun = $this->annotator->getGeneratedFileContent($firstRun, Team::class);
296
        $this->assertEquals($firstRun, $secondRun);
297
    }
298
299
    /**
300
     * Test that root (non-namespaced) classes get annotated
301
     */
302
    public function testRootAnnotations()
303
    {
304
        $classInfo = new AnnotateClassInfo(RootTeam::class);
305
        $filePath = $classInfo->getClassFilePath();
306
        $run = $this->annotator->getGeneratedFileContent(file_get_contents($filePath), RootTeam::class);
307
        $this->assertContains('@property string $Title', $run);
308
    }
309
310
    /**
311
     * Test the generation of annotations for a DataExtension
312
     */
313
    public function testAnnotateDataExtension()
314
    {
315
        $classInfo = new AnnotateClassInfo(Team_Extension::class);
316
        $filePath = $classInfo->getClassFilePath();
317
        $original = file_get_contents($filePath);
318
        $annotated = $this->annotator->getGeneratedFileContent($original, Team_Extension::class);
319
320
        $this->assertContains(
321
            '@property \SilverLeague\IDEAnnotator\Tests\Team|\SilverLeague\IDEAnnotator\Tests\Team_Extension $owner',
322
            $annotated
323
        );
324
        $this->assertContains('@property string $ExtendedVarcharField', $annotated);
325
        $this->assertContains('@property int $ExtendedIntField', $annotated);
326
        $this->assertContains('@property int $ExtendedHasOneRelationshipID', $annotated);
327
        $this->assertContains(
328
            '@method \SilverLeague\IDEAnnotator\Tests\Player ExtendedHasOneRelationship()',
329
            $annotated
330
        );
331
    }
332
333
    /**
334
     * Test the generation of annotations for a DataExtension
335
     */
336
    public function testShortAnnotateDataExtension()
337
    {
338
        Config::modify()->set(DataObjectAnnotator::class, 'use_short_name', true);
339
340
        $classInfo = new AnnotateClassInfo(Team_Extension::class);
341
        $filePath = $classInfo->getClassFilePath();
342
        $original = file_get_contents($filePath);
343
        $annotated = $this->annotator->getGeneratedFileContent($original, Team_Extension::class);
344
345
        $this->assertContains(
346
            '@property Team|Team_Extension $owner',
347
            $annotated
348
        );
349
        $this->assertContains('@property string $ExtendedVarcharField', $annotated);
350
        $this->assertContains('@property int $ExtendedIntField', $annotated);
351
        $this->assertContains('@property int $ExtendedHasOneRelationshipID', $annotated);
352
        $this->assertContains(
353
            '@method Player ExtendedHasOneRelationship()',
354
            $annotated
355
        );
356
    }
357
358
    /**
359
     *
360
     */
361
    public function testTwoClassesInOneFile()
362
    {
363
        $classInfo = new AnnotateClassInfo(DoubleDataObjectInOneFile1::class);
364
        $filePath = $classInfo->getClassFilePath();
365
        $original = file_get_contents($filePath);
366
        $annotated = $this->annotator->getGeneratedFileContent($original, DoubleDataObjectInOneFile1::class);
367
368
        $this->assertContains('@property string $Title', $annotated);
369
370
        $annotated = $this->annotator->getGeneratedFileContent($annotated, DoubleDataObjectInOneFile2::class);
371
372
        $this->assertContains('@property string $Name', $annotated);
373
    }
374
375
    public function tearDown()
376
    {
377
        parent::tearDown();
378
    }
379
}
380