Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
| 1 | <?php |
||
| 19 | class PageTest extends KernelTestCase |
||
| 20 | { |
||
| 21 | /** @var Container The Symfony container. */ |
||
| 22 | protected $container; |
||
| 23 | |||
| 24 | /** |
||
| 25 | * A page has a title and an HTML display title. |
||
| 26 | */ |
||
| 27 | public function testTitles() |
||
| 28 | { |
||
| 29 | $project = new Project('TestProject'); |
||
| 30 | $pageRepo = $this->getMock(PagesRepository::class, ['getPageInfo']); |
||
| 31 | $data = [ |
||
| 32 | [$project, 'Test_Page_1', ['title' => 'Test_Page_1']], |
||
| 33 | [$project, 'Test_Page_2', ['title' => 'Test_Page_2', 'displaytitle' => '<em>Test</em> page 2']], |
||
| 34 | ]; |
||
| 35 | $pageRepo->method('getPageInfo')->will($this->returnValueMap($data)); |
||
| 36 | |||
| 37 | // Page with no display title. |
||
| 38 | $page = new Page($project, 'Test_Page_1'); |
||
| 39 | $page->setRepository($pageRepo); |
||
| 40 | $this->assertEquals('Test_Page_1', $page->getTitle()); |
||
| 41 | $this->assertEquals('Test_Page_1', $page->getDisplayTitle()); |
||
| 42 | |||
| 43 | // Page with a display title. |
||
| 44 | $page = new Page($project, 'Test_Page_2'); |
||
| 45 | $page->setRepository($pageRepo); |
||
| 46 | $this->assertEquals('Test_Page_2', $page->getTitle()); |
||
| 47 | $this->assertEquals('<em>Test</em> page 2', $page->getDisplayTitle()); |
||
| 48 | } |
||
| 49 | |||
| 50 | /** |
||
| 51 | * A page either exists or doesn't. |
||
| 52 | */ |
||
| 53 | public function testExists() |
||
| 54 | { |
||
| 55 | $pageRepo = $this->getMock(PagesRepository::class, ['getPageInfo']); |
||
| 56 | $project = new Project('TestProject'); |
||
| 57 | // Mock data (last element of each array is the return value). |
||
| 58 | $data = [ |
||
| 59 | [$project, 'Existing_page', []], |
||
| 60 | [$project, 'Missing_page', ['missing' => '']], |
||
| 61 | ]; |
||
| 62 | $pageRepo //->expects($this->exactly(2)) |
||
| 63 | ->method('getPageInfo') |
||
| 64 | ->will($this->returnValueMap($data)); |
||
| 65 | |||
| 66 | // Existing page. |
||
| 67 | $page1 = new Page($project, 'Existing_page'); |
||
| 68 | $page1->setRepository($pageRepo); |
||
| 69 | $this->assertTrue($page1->exists()); |
||
| 70 | |||
| 71 | // Missing page. |
||
| 72 | $page2 = new Page($project, 'Missing_page'); |
||
| 73 | $page2->setRepository($pageRepo); |
||
| 74 | $this->assertFalse($page2->exists()); |
||
| 75 | } |
||
| 76 | |||
| 77 | /** |
||
| 78 | * A page has an integer ID on a given project. |
||
| 79 | */ |
||
| 80 | public function testId() |
||
| 81 | { |
||
| 82 | $pageRepo = $this->getMock(PagesRepository::class, ['getPageInfo']); |
||
| 83 | $pageRepo->expects($this->once()) |
||
| 84 | ->method('getPageInfo') |
||
| 85 | ->willReturn(['pageid' => '42']); |
||
| 86 | |||
| 87 | $page = new Page(new Project('TestProject'), 'Test_Page'); |
||
| 88 | $page->setRepository($pageRepo); |
||
| 89 | $this->assertEquals(42, $page->getId()); |
||
| 90 | } |
||
| 91 | |||
| 92 | /** |
||
| 93 | * A page has a URL. |
||
| 94 | */ |
||
| 95 | public function testUrls() |
||
| 96 | { |
||
| 97 | $pageRepo = $this->getMock(PagesRepository::class, ['getPageInfo']); |
||
| 98 | $pageRepo->expects($this->once()) |
||
| 99 | ->method('getPageInfo') |
||
| 100 | ->willReturn(['fullurl' => 'https://example.org/Page']); |
||
| 101 | |||
| 102 | $page = new Page(new Project('exampleWiki'), 'Page'); |
||
| 103 | $page->setRepository($pageRepo); |
||
| 104 | $this->assertEquals('https://example.org/Page', $page->getUrl()); |
||
| 105 | } |
||
| 106 | |||
| 107 | /** |
||
| 108 | * A list of a single user's edits on this page can be retrieved, along with the count of |
||
| 109 | * these revisions, and the total bytes added and removed. |
||
| 110 | * @TODO this is not finished yet |
||
| 111 | */ |
||
| 112 | public function testUsersEdits() |
||
| 113 | { |
||
| 114 | $pageRepo = $this->getMock(PagesRepository::class, ['getRevisions']); |
||
| 115 | $pageRepo |
||
| 116 | ->method('getRevisions') |
||
| 117 | ->with() |
||
| 118 | ->willReturn([ |
||
| 119 | [ |
||
| 120 | 'id' => '1', |
||
| 121 | 'timestamp' => '20170505100000', |
||
| 122 | 'length_change' => '1', |
||
| 123 | 'comment' => 'One' |
||
| 124 | ], |
||
| 125 | ]); |
||
| 126 | |||
| 127 | $page = new Page(new Project('exampleWiki'), 'Page'); |
||
| 128 | $page->setRepository($pageRepo); |
||
| 129 | $user = new User('Testuser'); |
||
| 130 | //$this->assertCount(3, $page->getRevisions($user)->getCount()); |
||
| 131 | } |
||
| 132 | |||
| 133 | /** |
||
| 134 | * Wikidata errors. With this test getWikidataInfo doesn't return a Description, |
||
| 135 | * so getWikidataErrors should complain accordingly |
||
| 136 | */ |
||
| 137 | public function testWikidataErrors() |
||
| 138 | { |
||
| 139 | $pageRepo = $this->getMock(PagesRepository::class, ['getWikidataInfo', 'getPageInfo']); |
||
| 140 | |||
| 141 | $pageRepo |
||
| 142 | ->method('getWikidataInfo') |
||
| 143 | ->with() |
||
| 144 | ->willReturn([ |
||
| 145 | [ |
||
| 146 | 'term' => 'label', |
||
| 147 | 'term_text' => 'My article', |
||
| 148 | ], |
||
| 149 | ]); |
||
| 150 | $pageRepo |
||
| 151 | ->method('getPageInfo') |
||
| 152 | ->with() |
||
| 153 | ->willReturn([ |
||
| 154 | 'pagelanguage' => 'en', |
||
| 155 | 'pageprops' => [ |
||
| 156 | 'wikibase_item' => 'Q123', |
||
| 157 | ], |
||
| 158 | ]); |
||
| 159 | |||
| 160 | $page = new Page(new Project('exampleWiki'), 'Page'); |
||
| 161 | $page->setRepository($pageRepo); |
||
| 162 | |||
| 163 | $wikidataErrors = $page->getWikidataErrors(); |
||
| 164 | |||
| 165 | $this->assertArraySubset( |
||
| 166 | [ |
||
| 167 | 'prio' => 3, |
||
| 168 | 'name' => 'Wikidata', |
||
| 169 | ], |
||
| 170 | $wikidataErrors[0] |
||
| 171 | ); |
||
| 172 | $this->assertContains( |
||
| 173 | 'Description', |
||
| 174 | $wikidataErrors[0]['notice'] |
||
| 175 | ); |
||
| 176 | } |
||
| 177 | |||
| 178 | // public function testPageAssessments() |
||
| 179 | // { |
||
| 180 | // $projectRepo = $this->getMock(ProjectRepository::class, ['getAssessmentsConfig']); |
||
| 181 | // $projectRepo |
||
| 182 | // ->method('getAssessmentsConfig') |
||
| 183 | // ->willReturn([ |
||
| 184 | // 'wikiproject_prefix' => 'Wikipedia:WikiProject_' |
||
| 185 | // ]); |
||
| 186 | |||
| 187 | // $project = $this->getMock(Project::class, ['getDomain']); |
||
| 188 | // $project |
||
| 189 | // ->method('getDomain') |
||
| 190 | // ->willReturn('test.wiki.org'); |
||
| 191 | // $project->setRepository($projectRepo); |
||
| 192 | |||
| 193 | // $pageRepo = $this->getMock(PagesRepository::class, ['getAssessments', 'getPageInfo']); |
||
| 194 | // $pageRepo |
||
| 195 | // ->method('getAssessments') |
||
| 196 | // ->with($project) |
||
| 197 | // ->willReturn([ |
||
| 198 | // [ |
||
| 199 | // 'wikiproject' => 'Military history', |
||
| 200 | // 'class' => 'Start', |
||
| 201 | // 'importance' => 'Low', |
||
| 202 | // ], |
||
| 203 | // [ |
||
| 204 | // 'wikiproject' => 'Firearms', |
||
| 205 | // 'class' => 'C', |
||
| 206 | // 'importance' => 'High', |
||
| 207 | // ], |
||
| 208 | // ]); |
||
| 209 | // $pageRepo |
||
| 210 | // ->method('getPageInfo') |
||
| 211 | // ->with($project, 'Test_page') |
||
| 212 | // ->willReturn([ |
||
| 213 | // 'pageid' => 5, |
||
| 214 | // ]); |
||
| 215 | |||
| 216 | // $page = new Page($project, 'Test_page'); |
||
| 217 | // $page->setRepository($pageRepo); |
||
| 218 | |||
| 219 | // $assessments = $page->getAssessments(); |
||
| 220 | |||
| 221 | // $this->assertEquals('C', $assessments['assessment']); |
||
| 222 | // } |
||
| 223 | } |
||
| 224 |